module Noir::LuaCalleeExtractor

Extended Modules

Defined in:

miniparsers/lua_callee_extractor.cr

Constant Summary

BARE_CALL_REGEX = /(?<![A-Za-z0-9_.:\\@])([A-Za-z_][A-Za-z0-9_]*)\s*(?:\(|(?=\s*(?:["'{]|\[\[)))/
COMMAND_CALL_REGEX = /(?:^\s*|[=,;]\s*|\breturn\s+)([A-Za-z_][A-Za-z0-9_]*)\s+(?=["'{A-Za-z_@\[])/
MOONSCRIPT_RESERVED = Set {"import", "export", "from", "class", "extends", "with", "using", "switch", "when", "unless", "continue"}

MoonScript-only keywords. These are NOT Lua keywords — class, import, from, with, switch, … are all legal (and common, e.g. middleclass's class("Foo")) Lua function names — so they are filtered ONLY when the source file is .moon, where import X from, class … extends …, and switch/when are statement keywords that would otherwise surface as phantom callees.

RECEIVER_CALL_REGEX = /(?<![A-Za-z0-9_@])(@?[A-Za-z_][A-Za-z0-9_]*(?:(?:\s*[.\\]\s*|:)[A-Za-z_][A-Za-z0-9_]*)+)\s*(?:\(|(?=\s+(?:["'{]|\[\[|@)))/

A receiver chain is a.b, a:b (Lua method call), or a\b (MoonScript method call). The : separator is kept space-free so a MoonScript table entry (success: Flow(...), where : is a hash separator, not method access) is not glued onto the following call — Lua's obj:method never carries surrounding whitespace, whereas a MoonScript key always does. . and \ keep optional whitespace.

RESERVED = Set {"and", "break", "do", "else", "elseif", "end", "false", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "assert", "collectgarbage", "dofile", "error", "getmetatable", "ipairs", "load", "loadfile", "next", "pairs", "pcall", "print", "rawequal", "rawget", "rawlen", "rawset", "require", "select", "setmetatable", "tonumber", "tostring", "type", "xpcall"}
SELF_CALL_REGEX = /(?<![A-Za-z0-9_])(@[A-Za-z_][A-Za-z0-9_]*)\s*(?:\(|(?=\s+(?:["'{]|\[\[|[A-Za-z_@])))/
STANDARD_LIB_ROOTS = Set {"coroutine", "debug", "io", "math", "os", "package", "string", "table", "utf8"}

Instance Method Summary

Instance Method Detail

def attach_to(endpoint : Endpoint, callees : Array(Entry)) #

[View source]
def callees_for_body(body : String, file_path : String, start_line : Int32) : Array(Entry) #

[View source]
def extract_function_after(source : String, start_index : Int32, search_limit : Int32 = source.size, body_limit : Int32 = source.size) : Tuple(String, Int32) | Nil #

[View source]
def extract_function_at(source : String, function_index : Int32, limit : Int32 = source.size) : Tuple(String, Int32) | Nil #

Public String overload kept for callers outside this module.


[View source]
def extract_function_at(chars : Array(Char), function_index : Int32, limit : Int32 = chars.size) : Tuple(String, Int32) | Nil #

[View source]
def extract_moonscript_block_after(source : String, arrow_end_index : Int32) : Tuple(String, Int32) | Nil #

Public String overload kept for callers outside this module.


[View source]
def extract_moonscript_block_after(chars : Array(Char), arrow_end_index : Int32) : Tuple(String, Int32) | Nil #

[View source]
def find_matching_delimiter(source : String, open_index : Int32, open_char : Char, close_char : Char, limit : Int32 = source.size) : Int32 | Nil #

Public String overload kept for callers outside this module.


[View source]
def find_matching_delimiter(chars : Array(Char), open_index : Int32, open_char : Char, close_char : Char, limit : Int32 = chars.size) : Int32 | Nil #

[View source]
def function_bodies(source : String, file_path : String) : Hash(String, FunctionBody) #

[View source]
def line_number_for(source : String, index : Int32) : Int32 #

Public String overload kept for callers outside this module.


[View source]
def line_number_for(chars : Array(Char), index : Int32) : Int32 #

[View source]
def moonscript_value_region(source : String, value_start : Int32) : Tuple(String, Int32) | Nil #

Extract a MoonScript class-action value: everything from value_start (just past a route header's :) through the end of the indentation block the header introduces. Unlike #extract_moonscript_block_after, which assumes an inline arrow and stops at the first body line, this keeps the header line's trailing content (respond_to {, a wrapper call, an inline arrow) together with every more-indented line that follows, so respond_to blocks and wrapped handlers are captured whole. start_line is the header line, matching the offsets callers already expect for inline arrows.

Public String overload kept for callers outside this module.


[View source]
def moonscript_value_region(chars : Array(Char), value_start : Int32) : Tuple(String, Int32) | Nil #

[View source]
def strip_comments(source : String) : String #

Blank out comments and long-bracket ([[ ]]/[=[ ]=]) string bodies but PRESERVE short-string contents verbatim. Route analyzers need the path literals (app:get("/login", …)) intact while still suppressing -- comments and here-strings that would otherwise leak phantom routes. Newlines are kept so line-anchored scans and line numbering stay aligned.


[View source]
def strip_comments(chars : Array(Char)) : String #

[View source]
def strip_non_code(source : String) : String #

Public String overload kept for callers outside this module.


[View source]
def strip_non_code(chars : Array(Char)) : String #

[View source]