module Noir::TreeSitterJavaParameterExtractor

Overview

Tree-sitter-backed parameter extractor for Java/Spring.

Pairs with TreeSitterJavaRouteExtractor: after the route discovery pass tells us which methods are routes, this module walks the matching method_declaration to extract request parameters from @RequestParam / @RequestBody / @RequestHeader / @CookieValue / @PathVariable annotations, primitive typed args, HttpServletRequest body scans, and user-defined DTO fields.

DTO resolution is caller-provided (class_fields map) so the same extractor works whether fields come from a same-file scan, a same- package Dir.glob, or a cross-file import resolver. Keeping that concern out of here keeps the extractor source-scoped and testable.

Extended Modules

Defined in:

miniparsers/java_parameter_extractor_ts.cr

Constant Summary

HTTP_HEADER_SPECIAL_CASES = {"Etag" => "ETag", "Te" => "TE", "Www-Authenticate" => "WWW-Authenticate", "X-Frame-Options" => "X-Frame-Options"}

Spring HttpHeaders constant → canonical header name. Matches the table the legacy analyzer maintained; necessary because tree-sitter reports the constant as a field_access node (e.g. HttpHeaders.AUTHORIZATION), not the string value.

PRIMITIVE_TYPES = Set {"long", "int", "integer", "char", "boolean", "string", "multipartfile"}

Primitive / stdlib types whose name we emit directly as a parameter. Everything else is looked up in class_fields for DTO expansion.

SERVLET_REQUEST_TYPES = Set {"HttpServletRequest"}

Subset of servlet types whose method body is scanned for request.getParameter("x") / request.getHeader("x") calls.

Instance Method Summary

Instance Method Detail

def extract_class_fields(source : String) : Hash(String, Array(FieldInfo)) #

Scan every class_declaration / interface_declaration in source and return {class_name => [FieldInfo]}. Only classes with at least one field appear; setter detection walks sibling method_declarations looking for setFoo(...).


[View source]
def extract_class_fields_from(root : LibTreeSitter::TSNode, source : String) : Hash(String, Array(FieldInfo)) #

_from(root, source) variants accept a pre-parsed root node so callers (typically the Spring analyzer) can amortise the tree-sitter parse across multiple extractions on the same file — extract_routes_from, #extract_consumes_from, #extract_method_parameters_from, and the rest can all share a single Noir::TreeSitter.parse_java block. Tree lifetime is the caller's responsibility (it must keep root valid by staying inside the parse_java block while these are invoked).


[View source]
def extract_consumes(source : String, class_name : String, method_name : String) : String | Nil #

Find @*Mapping annotation on (class_name, method_name) and read its consumes = ... attribute. Returns "form" / "json" / nil — matches spring.cr's legacy helper semantics so the analyzer can swap this in without behaviour drift.


[View source]
def extract_consumes_from(root : LibTreeSitter::TSNode, source : String, class_name : String, method_name : String) : String | Nil #

[View source]
def extract_feign_client_classes(source : String) : Set(String) #

Return the set of class/interface simple names annotated with @FeignClient in source. Spring Cloud Feign interfaces are treated as remote clients in the analyzer's output.


[View source]
def extract_feign_client_classes_from(root : LibTreeSitter::TSNode, source : String) : Set(String) #

[View source]
def extract_http_exchange_client_classes_from(root : LibTreeSitter::TSNode, source : String) : Set(String) #

Return the set of class/interface simple names that declare a Spring HTTP Interface. These are remote client contracts when used with HttpServiceProxyFactory, so Spring analyzer output marks them internal like Feign clients.


[View source]
def extract_imports(source : String) : Array(ImportDecl) #

Return every import in the source as ImportDecl. Static imports (import static ...) are skipped since they don't contribute DTO classes.


[View source]
def extract_imports_from(root : LibTreeSitter::TSNode, source : String) : Array(ImportDecl) #

[View source]
def extract_method_parameters(source : String, class_name : String, method_name : String, verb : String, parameter_format : String | Nil, class_fields : Hash(String, Array(FieldInfo))) : Array(Param) #

Extract parameters for method_name on class_name. Returns [] when the method isn't found. parameter_format is the method's default-shape hint (e.g. "form" when @PostMapping + no explicit consumes); individual parameter annotations override it.

class_fields is the pre-built DTO index — a parameter whose type matches a key is expanded into one Param per public / setter-backed field on that class.


[View source]
def extract_method_parameters_from(root : LibTreeSitter::TSNode, source : String, class_name : String, method_name : String, verb : String, parameter_format : String | Nil, class_fields : Hash(String, Array(FieldInfo))) : Array(Param) #

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

Return the file's package com.foo.bar; declaration as a dotted name, or "" when no package declaration is present.


[View source]
def extract_package_name_from(root : LibTreeSitter::TSNode, source : String) : String #

[View source]