module

Noir::ClojureScanner

Low-level Clojure reader primitives, shared by the callee extractor in this directory and by the Clojure framework analyzers, so the two never drift again.

Every offset here is a byte offset into the raw source (byte_at), never a character index, so the values stay usable with String#byte_slice on sources containing non-ASCII text.

Constants

CLOJURE_EXTENSIONS = {".clj", ".cljc", ".cljs"}
TEST_PATH_RE = /\/(?:perf-)?test\/|_test\./i

Leiningen/tools.deps test trees (test/, perf-test/ router micro-benchmarks) and foo_test.clj files: routes there are test handlers and benchmark fixtures nothing serves.

Instance methods

base_symbol(symbol : String) : String
Source
clojure_file?(path : String) : Bool
Source
comment_form?(symbol : String) : Bool

(comment ...) is a REPL scratch block the compiler drops, so routes in it never run. A namespaced (db/comment ...) is an ordinary call.

Source
decode_string_literal(raw : String) : String
Source
end_of_form(source : String, index : Int32, limit : Int32) : Int32

Offset just past the form that starts at index (a non-whitespace byte). Quote/unquote/deref prefixes and the #{, #(, #", #?(, #?@( dispatch forms stay attached to the form they introduce. An unterminated collection runs to limit.

Source
extract_path_param_names(route_path : String) : Array(String)

:name segments of a route path, in order (duplicates kept).

Source
find_matching_delimiter(source : String, index : Int32, open_char : Char, close_char : Char, limit : Int32) : Int32

Find the offset of the delimiter closing the one at index, skipping over comments, string literals and character literals so a ) inside ";)" or a \( never moves the depth counter. Returns index unchanged when no match is found.

Source
first_string_literal(source : String, index : Int32, limit : Int32) : Tuple(String | Nil, Int32)

The first string literal before the next nested form, decoded, plus the offset of its closing quote.

Source
function_name(symbol : String) : String
Source
handler_symbol?(token : String) : Bool
Source
line_number_for(source : String, index : Int32, start_line : Int32 = 1) : Int32

Line number of a byte offset, counted from start_line (1-based by default, matching a whole-file offset).

Source
normalized_handler_symbol(token : String) : String | Nil

A handler reference (handler, #'ns/handler, 'handler) reduced to its unqualified function name; nil for keywords, strings and literals.

Source
read_form_token(source : String, start : Int32, limit : Int32, commas : Bool = true) : Tuple(String, Int32)

Reads the next (...) / [...] / {...} form, "..." string or bare symbol, returning its raw text and the offset after it (whitespace skipped). commas is forwarded to read_symbol only.

Source
read_symbol(source : String, index : Int32, limit : Int32, commas : Bool = true) : Tuple(String, Int32)

Read a bare symbol/keyword starting at index. Commas are whitespace in Clojure, so by default they terminate a symbol just like spaces (keeps [x, y] from reading x, as one token); pass commas: false to read through them.

Source
skip_char_literal(source : String, index : Int32, limit : Int32) : Int32

Advance from the \ that opens a character literal to the literal's last byte (the same "last byte consumed" contract as skip_string).

Clojure character literals are \a, \", \(, \\, \; (a single character, reader-significant ones included), the named forms \newline, \space, \tab, \formfeed, \backspace and \return, \uXXXX and \oNNN. Without this, \" opens a string that runs to the next quote in the file and \( counts as a real open paren, so depth accounting — and with it every route below the literal — collapses.

Source
skip_comment(source : String, index : Int32, limit : Int32) : Int32

Advance past a ; line comment, stopping on the newline that ends it.

Source
skip_hash(source : String, index : Int32, limit : Int32) : Int32

A walker's char loop calls this on #: past a #_ discarded form (and the whitespace after it), otherwise just past the #.

Source
skip_string(source : String, index : Int32, limit : Int32) : Int32

Advance from the opening " of a string literal to its closing quote, honouring \ escapes. Returns the last in-range offset when the literal is unterminated so callers still make progress.

Source
skip_ws_and_comments(source : String, index : Int32, limit : Int32, commas : Bool = true) : Int32

Advance past whitespace, ; comments and #_ discarded forms (the reader drops the next form entirely, so #_(GET "/x" ...) is not code). Clojure reads commas as whitespace; pass commas: false to stop on them.

Source
test_path?(relative_path : String) : Bool

Pass a scan-base-relative path (Analyzer#base_relative_path), never an absolute one: a test/ directory ABOVE the scan base is not this project's test tree.

Source