module
Noir::PathScope
Overview
Path-boundary helpers shared by the analyzers and engines. Monorepo
scans (multiple -b base paths) have to answer two questions
repeatedly: does a file live under a given root, and which configured
base does it belong to? Both must respect path boundaries — a plain
String#starts_with? leaks siblings (/app would swallow /app2) —
so the comparison runs on File.expand_path-normalized paths.
This logic was copy-pasted across half a dozen call sites (FileHelper, Analyzer, PythonEngine, the Dart helper, the Express router scanner, FastAPI). This module is the single source of truth; a future tweak (Windows separators, symlink handling, …) now lands in one place.
Hot loops should normalize the loop-invariant root once via
#normalize_root and compare with #under_normalized_root? rather than
paying for File.expand_path of the root per file.
Extended Modules
Defined in:
utils/path_scope.crInstance Method Summary
-
#longest_base(path : String, bases : Enumerable(String)) : String | Nil
The most specific (longest normalized) base in
basesthat containspath, or nil if none does. -
#normalize_root(root : String) : String
Canonical comparison form of a root: expanded, with any trailing separator stripped (except the filesystem root itself).
-
#relative_under(path : String, base_path : String | Nil) : String
Remainder of
pathbeneathbase_path, or the bare basename whenpathis outsidebase_path(or no base given). -
#under_normalized_root?(expanded_path : String, normalized_root : String) : Bool
Boundary check against an already-expanded path and an already-normalized root.
-
#under_root?(path : String, root : String) : Bool
True when
pathisrootor sits beneath it on a path boundary.
Instance Method Detail
The most specific (longest normalized) base in bases that contains
path, or nil if none does. Returns the ORIGINAL base string (not its
normalized form) so callers can use it as a stable map key.
Canonical comparison form of a root: expanded, with any trailing separator stripped (except the filesystem root itself).
Remainder of path beneath base_path, or the bare basename when
path is outside base_path (or no base given). Backs the
Python/Dart test-path conventions, which key off the project-relative
path so nested fixture trees don't trip the tests//test/ filters.
Boundary check against an already-expanded path and an
already-normalized root. Use this in per-file loops where the root is
loop-invariant (normalize it once with #normalize_root).
True when path is root or sits beneath it on a path boundary.
root is expanded/normalized internally; an empty root matches
everything (mirrors the historical starts_with?("")).