abstract class
Analyzer::Crystal::CrystalEngine
- Analyzer::Crystal::CrystalEngine
- Analyzer
- Reference
- Object
Direct Known Subclasses
- Analyzer::Crystal::Amber
- Analyzer::Crystal::Grip
- Analyzer::Crystal::Http
- Analyzer::Crystal::Kemal
- Analyzer::Crystal::Lucky
- Analyzer::Crystal::Marten
Defined in:
analyzer/engines/crystal_engine.crConstant Summary
-
CLOSES_BLOCK_RE =
/^end\b/ -
DEF_DECL_RE =
/^(?:(?:private|protected)\s+)?def\s+(?:self\.)?([A-Za-z_]\w*[!?=]?)/ -
DO_WORD_RE =
/\bdo\b/ -
Precompiled block-structure probes used by extract_crystal_do_block / extract_crystal_def_block on every body line. Constant shapes — load once, match many times. Cheap
includes?gates reject the common non-structural body lines before any PCRE2 scan. -
END_WORD_RE =
/\bend\b/ -
HEREDOC_OPEN =
/(?<!['"])<<-['"]?([A-Z_]\w*)/ -
Opening token of a Crystal heredoc:
<<-DELIM, optionally quoted (<<-'SQL'). The delimiter must start with an uppercase letter or underscore — the universal Crystal convention (MD/HTML/SQL/EOF/…) — which keeps the matcher from firing onarr << -value. The negative lookbehind rejects a<<-that sits inside a string literal ("<<-MD"), so a stray quoted token can't open a phantom heredoc and blank the rest of the file. -
HTTP_ROUTE_VERBS =
["get", "post", "put", "delete", "patch", "head", "options"] of ::String -
Shared
verb "/path"matchers for Kemal/Lucky/Grip-style DSLs. One combined PCRE2 scan replaces the previous 7–8 sequential per-verb.scancalls that ran on every source line. Leftmost match wins, which matches real one-verb-per-line route DSLs and the prior first-matching-verb behaviour for those lines. Optionalextracovers framework-only verbs (Lucky'strace). -
INTERPOLATION_RE =
/\#\{([^}]+)\}/ -
Crystal
"…"strings interpolate#{expr}. The Kemal/Lucky/ Amber/Marten/Grip route extractors capture the literal characters between quotes, soget "/api/#{VERSION}/items"came out as/api/#{VERSION}/itemswith the#{VERSION}leaking into the URL. Rewrite it as{name}so the path- parameter extractor picks it up and the URL template reads cleanly. Mirrors the Python f-string, Ruby#{}, and PHP$varfixes earlier this pass.Most route literals have no interpolation; skip the PCRE2 gsub when the
#\{marker is absent. -
NAMESPACE_DECL_RE =
/^(?:abstract\s+)?(?:module|class|struct)\s+([A-Z]\w*(?:::[A-Z]\w*)*)/ -
Track the enclosing module/class by indentation rather than by counting
do/end. Method bodies in real controllers are full of heredocs,{% … %}macros, andXML.build do … endblocks that throw off keyword-based depth counting and prematurely "close" the module, dropping every method defined after them. Indentation is the one signal those constructs can't corrupt: a namespace stays open until a line dedents to or past the column where it was declared.Precompiled: this loop runs once per line of every .cr file when building the cross-file action index (
--include-callee/--ai-context). The shapes never change, so hoist the two PCRE2 patterns to class constants. -
SIMPLE_ROUTE_RE =
/(?:^|[^.\w])(get|post|put|delete|patch|head|options|ws)\s*(?:\(\s*)?['"](.+?)['"]/ -
Group 1 = verb (or
ws), group 2 = path.wsis folded in so a single scan covers WebSocket routes too; the caller mapsws→ GET + protocol=ws. -
STRUCT_OPEN_RE =
/(?:^|=[^=>])\s*(?:if|unless|case|begin|while|until|for|class|module|def|macro)\b/