class Analyzer::Python::Aiohttp

Defined in:

analyzer/analyzers/python/aiohttp.cr

Constant Summary

ADD_METHOD_ORIG_RE = HTTP_METHOD_NAMES.to_h do |m| {m, /\.add_#{m}\s*\(\s*[rf]?['"]([^'"]*)['"]/} end

Spaces are stripped before the add_<method> match, so the route path is re-extracted from the original (spaced) line. Precompile one matcher per method name so the re-extraction isn't a per-route PCRE2 compile. Keyed by the same names captured by ADD_METHOD_RE.

ADD_METHOD_RE = /(#{DOT_NATION})\.add_(#{METHODS_ALT})\([rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/
ADD_ROUTE_ALIAS_RE = /^(#{PYTHON_VAR_NAME_REGEX})\([rf]?['"]([A-Za-z*]+)['"]\s*,\s*[rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/
ADD_ROUTE_RE = /(#{DOT_NATION})\.add_route\([rf]?['"]([A-Za-z*]+)['"]\s*,\s*[rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/
ADD_ROUTES_CALL_RE = /(#{DOT_NATION})\.add_routes\s*\(/
ADD_ROUTES_VAR_RE = /(#{DOT_NATION})\.add_routes\s*\(\s*(#{PYTHON_VAR_NAME_REGEX})/
ADD_STATIC_RE = /(#{DOT_NATION})\.add_static\([rf]?['"]([^'"]*)['"]/
ADD_SUBAPP_RE = /(#{DOT_NATION})\.add_subapp\s*\(\s*[rf]?['"]([^'"]*)['"]\s*,\s*(#{DOT_NATION})/
ADD_VIEW_RE = /(#{DOT_NATION})\.add_view\([rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/
APP_PREFIX_RE = /^(#{PYTHON_VAR_NAME_REGEX})(?::#{PYTHON_VAR_NAME_REGEX})?=(?:web\.)?Application\(/

Prefix-collection matchers. collect_app_prefixes / collect_route_list_ranges scan every line of every file, so these were per-line PCRE2 recompiles before hoisting.

DEF_METHOD_RE = /^\s*(?:async\s+)?def\s+(#{METHODS_ALT})\s*\(/
DICT_ACCESSORS = {"headers" => "header", "cookies" => "cookie"}
DICT_METHOD_NAMES = Set {"get", "getall", "getone", "items", "keys", "values", "pop"}
HTTP_METHOD_NAMES = ["get", "post", "put", "delete", "patch", "head", "options"] of ::String
LIST_ASSIGN_RE = /^\s*(#{PYTHON_VAR_NAME_REGEX})\s*=\s*\[/
METHODS_ALT = HTTP_METHOD_NAMES.join("|")

The route-discovery patterns below interpolate only the PYTHON_VAR_NAME_REGEX/DOT_NATION constants and this fixed method alternation, so the inline literals were recompiling identical PCRE2 patterns on every source line of every file (and rebuilding methods_re with a join each line). Compile once here; the .to_s expansion of the interpolated constants is byte-identical to the previous inline form, so matching behaviour is unchanged.

ROUTE_ALIAS_RE = /^(#{PYTHON_VAR_NAME_REGEX})=(#{DOT_NATION})\.add_route/
ROUTE_DECO_RE = /@(#{PYTHON_VAR_NAME_REGEX})\.route\([rf]?['"]([A-Za-z*]+)['"]\s*,\s*[rf]?['"]([^'"]*)['"]/
WEB_METHOD_GUARD_RE = /\bweb\.(?:#{METHODS_ALT})\s*\(/
WEB_METHOD_RE = /\bweb\.(#{METHODS_ALT})\s*\(\s*[rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/
WEB_VIEW_RE = /\bweb\.view\s*\(\s*[rf]?['"]([^'"]*)['"]\s*,\s*(?:handler\s*=\s*)?(#{DOT_NATION})/

Instance Method Summary

Instance methods inherited from class Analyzer::Python::PythonEngine

build_callees_from(body : String, body_start_line : Int32, path : String, *, definition_base_path : String | Nil = nil, source : String | Nil = nil) : Array(Callee) build_callees_from, find_def_line(lines : Array(String), decorator_line : Int32) : Int32 | Nil find_def_line, find_imported_modules(app_base_path : String, file_path : String, content : String | Nil = nil) : Hash(String, Tuple(String, Int32)) find_imported_modules, find_imported_package(package_path : String, dotted_as_names : String) : Array(Tuple(String, String, Int32)) find_imported_package, find_json_params(codeblock_lines : Array(String), json_var_names : Array(String)) : Array(Param) find_json_params, join_until_python_call_closes(lines : Array(String), index : Int32, line : String) : String join_until_python_call_closes, parse_code_block(data : String | Array(String), after : Regex | Nil = nil) : String | Nil parse_code_block, parse_function_def(source_lines : Array(String), start_index : Int32) : FunctionDefinition | Nil parse_function_def, push_callees_from(endpoint : Endpoint, body : String, body_start_line : Int32, path : String, *, definition_base_path : String | Nil = nil, source : String | Nil = nil) : Nil push_callees_from, python_paren_delta(line : String) : Int32 python_paren_delta, python_signature_line_span(lines : Array(String)) : Int32 python_signature_line_span, return_literal_value(data : String) : String return_literal_value

Class methods inherited from class Analyzer::Python::PythonEngine

python_test_path?(path : String, base_path : String | Nil = nil) : Bool python_test_path?

Instance methods inherited from class Analyzer

analyze analyze, base_path : String base_path, base_paths : Array(String) base_paths, callees_needed? : Bool callees_needed?, logger : NoirLogger logger, parallel_analyze(files : Array(String), &block : String -> Nil) parallel_analyze, read_file_content(path : String) : String read_file_content, result : Array(Endpoint) result, url : String url

Constructor methods inherited from class Analyzer

new(options : Hash(String, YAML::Any)) new

Macros inherited from class Analyzer

define_getter_methods(names) define_getter_methods

Instance methods inherited from module FileHelper

all_files : Array(String) all_files, get_files_by_extension(extension : String) : Array(String) get_files_by_extension, get_files_by_prefix(prefix : String) : Array(String) get_files_by_prefix, get_files_by_prefix_and_extension(prefix : String, extension : String) : Array(String) get_files_by_prefix_and_extension, get_public_dir_files(base_path : String, folder : String) : Array(String) get_public_dir_files, get_public_files(base_path : String, anchors : Array(String) = ["shard.yml", "Gemfile"]) : Array(String) get_public_files

Instance Method Detail

def analyze #

[View source]