codebeacon 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codebeacon/__init__.py +1 -0
- codebeacon/__main__.py +3 -0
- codebeacon/cache.py +136 -0
- codebeacon/cli.py +391 -0
- codebeacon/common/__init__.py +0 -0
- codebeacon/common/filters.py +170 -0
- codebeacon/common/symbols.py +121 -0
- codebeacon/common/types.py +98 -0
- codebeacon/config.py +144 -0
- codebeacon/contextmap/__init__.py +0 -0
- codebeacon/contextmap/generator.py +602 -0
- codebeacon/discover/__init__.py +0 -0
- codebeacon/discover/detector.py +388 -0
- codebeacon/discover/scanner.py +192 -0
- codebeacon/export/__init__.py +0 -0
- codebeacon/export/mcp.py +515 -0
- codebeacon/export/obsidian.py +812 -0
- codebeacon/extract/__init__.py +22 -0
- codebeacon/extract/base.py +372 -0
- codebeacon/extract/components.py +357 -0
- codebeacon/extract/dependencies.py +140 -0
- codebeacon/extract/entities.py +575 -0
- codebeacon/extract/queries/README.md +116 -0
- codebeacon/extract/queries/actix.scm +115 -0
- codebeacon/extract/queries/angular.scm +155 -0
- codebeacon/extract/queries/aspnet.scm +159 -0
- codebeacon/extract/queries/django.scm +122 -0
- codebeacon/extract/queries/express.scm +124 -0
- codebeacon/extract/queries/fastapi.scm +152 -0
- codebeacon/extract/queries/flask.scm +120 -0
- codebeacon/extract/queries/gin.scm +142 -0
- codebeacon/extract/queries/ktor.scm +144 -0
- codebeacon/extract/queries/laravel.scm +172 -0
- codebeacon/extract/queries/nestjs.scm +183 -0
- codebeacon/extract/queries/rails.scm +114 -0
- codebeacon/extract/queries/react.scm +111 -0
- codebeacon/extract/queries/spring_boot.scm +204 -0
- codebeacon/extract/queries/svelte.scm +73 -0
- codebeacon/extract/queries/vapor.scm +130 -0
- codebeacon/extract/queries/vue.scm +123 -0
- codebeacon/extract/routes.py +910 -0
- codebeacon/extract/semantic.py +280 -0
- codebeacon/extract/services.py +597 -0
- codebeacon/graph/__init__.py +1 -0
- codebeacon/graph/analyze.py +281 -0
- codebeacon/graph/build.py +320 -0
- codebeacon/graph/cluster.py +160 -0
- codebeacon/graph/enrich.py +206 -0
- codebeacon/skill/SKILL.md +127 -0
- codebeacon/wave.py +292 -0
- codebeacon/wiki/__init__.py +0 -0
- codebeacon/wiki/generator.py +376 -0
- codebeacon/wiki/index.py +95 -0
- codebeacon/wiki/templates.py +467 -0
- codebeacon-0.1.2.dist-info/METADATA +319 -0
- codebeacon-0.1.2.dist-info/RECORD +59 -0
- codebeacon-0.1.2.dist-info/WHEEL +4 -0
- codebeacon-0.1.2.dist-info/entry_points.txt +2 -0
- codebeacon-0.1.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
; ── FastAPI (Python) ──────────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-python
|
|
3
|
+
;
|
|
4
|
+
; Captures:
|
|
5
|
+
; @route.decorator - @app.get / @router.post etc. decorator node
|
|
6
|
+
; @route.object - app/router object name
|
|
7
|
+
; @route.method - HTTP method (get/post/put/delete/patch)
|
|
8
|
+
; @route.path - path string
|
|
9
|
+
; @route.func_name - handler function name
|
|
10
|
+
; @route.prefix - APIRouter(prefix="...") value
|
|
11
|
+
; @service.func_name - Depends() dependency function name
|
|
12
|
+
; @service.class_name - class with methods using Depends
|
|
13
|
+
; @entity.class_name - BaseModel / SQLAlchemy Base subclass
|
|
14
|
+
; @entity.field_name - model field name
|
|
15
|
+
; @entity.field_type - model field type annotation
|
|
16
|
+
; @router.include - app.include_router(router, prefix="...")
|
|
17
|
+
; @import.path - import path
|
|
18
|
+
|
|
19
|
+
; ── @app.get("/path") / @router.post("/path") ────────────────────────────────
|
|
20
|
+
|
|
21
|
+
(decorated_definition
|
|
22
|
+
(decorator
|
|
23
|
+
(call
|
|
24
|
+
function: (attribute
|
|
25
|
+
object: (identifier) @route.object
|
|
26
|
+
attribute: (identifier) @route.method
|
|
27
|
+
(#match? @route.method "^(get|post|put|delete|patch|options|head)$")
|
|
28
|
+
)
|
|
29
|
+
arguments: (argument_list
|
|
30
|
+
(string) @route.path
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
definition: (function_definition
|
|
35
|
+
name: (identifier) @route.func_name
|
|
36
|
+
)
|
|
37
|
+
) @route.handler
|
|
38
|
+
|
|
39
|
+
; ── APIRouter(prefix="/api/v1") ───────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
(assignment
|
|
42
|
+
left: (identifier) @route.router_name
|
|
43
|
+
right: (call
|
|
44
|
+
function: (identifier) @_apiRouter
|
|
45
|
+
(#eq? @_apiRouter "APIRouter")
|
|
46
|
+
arguments: (argument_list
|
|
47
|
+
(keyword_argument
|
|
48
|
+
name: (identifier) @_prefix_key
|
|
49
|
+
(#eq? @_prefix_key "prefix")
|
|
50
|
+
value: (string) @route.prefix
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
) @route.router_decl
|
|
55
|
+
|
|
56
|
+
; ── app.include_router(router, prefix="...") ─────────────────────────────────
|
|
57
|
+
|
|
58
|
+
; With prefix keyword argument
|
|
59
|
+
(call
|
|
60
|
+
function: (attribute
|
|
61
|
+
object: (identifier) @_app
|
|
62
|
+
attribute: (identifier) @_include
|
|
63
|
+
(#eq? @_include "include_router")
|
|
64
|
+
)
|
|
65
|
+
arguments: (argument_list
|
|
66
|
+
(identifier) @router.include_router
|
|
67
|
+
(keyword_argument
|
|
68
|
+
name: (identifier) @_pk
|
|
69
|
+
(#eq? @_pk "prefix")
|
|
70
|
+
value: (string) @router.include_prefix
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
) @router.include
|
|
74
|
+
|
|
75
|
+
; Without prefix keyword argument
|
|
76
|
+
(call
|
|
77
|
+
function: (attribute
|
|
78
|
+
object: (identifier) @_app2
|
|
79
|
+
attribute: (identifier) @_include2
|
|
80
|
+
(#eq? @_include2 "include_router")
|
|
81
|
+
)
|
|
82
|
+
arguments: (argument_list
|
|
83
|
+
(identifier) @router.include_router
|
|
84
|
+
)
|
|
85
|
+
) @router.include_no_prefix
|
|
86
|
+
|
|
87
|
+
; ── Depends() function dependency ────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
; Functions that take parameters (potential service functions)
|
|
90
|
+
(function_definition
|
|
91
|
+
name: (identifier) @service.func_name
|
|
92
|
+
parameters: (parameters
|
|
93
|
+
(typed_parameter
|
|
94
|
+
(identifier) @_param
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
) @service.function
|
|
98
|
+
|
|
99
|
+
; Depends() in function signature
|
|
100
|
+
(call
|
|
101
|
+
function: (identifier) @_depends
|
|
102
|
+
(#eq? @_depends "Depends")
|
|
103
|
+
arguments: (argument_list
|
|
104
|
+
(identifier) @service.depends_func
|
|
105
|
+
)
|
|
106
|
+
) @service.depends
|
|
107
|
+
|
|
108
|
+
; ── BaseModel / SQLAlchemy subclass (entity) ─────────────────────────────────
|
|
109
|
+
|
|
110
|
+
; Direct identifier base class: class User(BaseModel)
|
|
111
|
+
(class_definition
|
|
112
|
+
name: (identifier) @entity.class_name
|
|
113
|
+
superclasses: (argument_list
|
|
114
|
+
(identifier) @_base
|
|
115
|
+
(#match? @_base "^(BaseModel|Base|DeclarativeBase|SQLModel)$")
|
|
116
|
+
)
|
|
117
|
+
) @entity.class
|
|
118
|
+
|
|
119
|
+
; Attribute base class: class User(db.Model)
|
|
120
|
+
(class_definition
|
|
121
|
+
name: (identifier) @entity.class_name
|
|
122
|
+
superclasses: (argument_list
|
|
123
|
+
(attribute
|
|
124
|
+
attribute: (identifier) @_base
|
|
125
|
+
(#match? @_base "^(Model|Base)$")
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
) @entity.class_attr
|
|
129
|
+
|
|
130
|
+
; Entity fields (type-annotated class attributes)
|
|
131
|
+
(class_definition
|
|
132
|
+
body: (block
|
|
133
|
+
(expression_statement
|
|
134
|
+
(assignment
|
|
135
|
+
left: (identifier) @entity.field_name
|
|
136
|
+
type: (type
|
|
137
|
+
(identifier) @entity.field_type
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
) @entity.with_fields
|
|
143
|
+
|
|
144
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
(import_from_statement
|
|
147
|
+
module_name: _ @import.path
|
|
148
|
+
) @import.from
|
|
149
|
+
|
|
150
|
+
(import_statement
|
|
151
|
+
name: _ @import.path
|
|
152
|
+
) @import.plain
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
; ── Flask (Python) ────────────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-python
|
|
3
|
+
;
|
|
4
|
+
; Captures:
|
|
5
|
+
; @route.decorator - @app.route / @bp.route decorator
|
|
6
|
+
; @route.object - app/blueprint object name
|
|
7
|
+
; @route.path - path string
|
|
8
|
+
; @route.methods - methods list ["GET","POST"]
|
|
9
|
+
; @route.func_name - handler function name
|
|
10
|
+
; @blueprint.name - Blueprint variable name
|
|
11
|
+
; @blueprint.url_prefix - url_prefix value
|
|
12
|
+
; @blueprint.import_name - blueprint name string
|
|
13
|
+
; @app.register_bp - app.register_blueprint(bp, url_prefix="...")
|
|
14
|
+
; @app.register_prefix - url_prefix in register_blueprint
|
|
15
|
+
; @entity.class_name - db.Model subclass name
|
|
16
|
+
; @entity.field_name - field name
|
|
17
|
+
; @entity.field_type - Column(...) type
|
|
18
|
+
; @import.path - import path
|
|
19
|
+
|
|
20
|
+
; ── @app.route("/path") / @blueprint.route("/path") ─────────────────────────
|
|
21
|
+
|
|
22
|
+
(decorated_definition
|
|
23
|
+
(decorator
|
|
24
|
+
(call
|
|
25
|
+
function: (attribute
|
|
26
|
+
object: (identifier) @route.object
|
|
27
|
+
attribute: (identifier) @_route_attr
|
|
28
|
+
(#eq? @_route_attr "route")
|
|
29
|
+
)
|
|
30
|
+
arguments: (argument_list
|
|
31
|
+
(string) @route.path
|
|
32
|
+
(keyword_argument
|
|
33
|
+
name: (identifier) @_methods_key
|
|
34
|
+
(#eq? @_methods_key "methods")
|
|
35
|
+
value: (list
|
|
36
|
+
(string) @route.methods
|
|
37
|
+
)
|
|
38
|
+
)?
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
definition: (function_definition
|
|
43
|
+
name: (identifier) @route.func_name
|
|
44
|
+
)
|
|
45
|
+
) @route.handler
|
|
46
|
+
|
|
47
|
+
; ── Blueprint declaration ─────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
(assignment
|
|
50
|
+
left: (identifier) @blueprint.name
|
|
51
|
+
right: (call
|
|
52
|
+
function: (identifier) @_bp
|
|
53
|
+
(#eq? @_bp "Blueprint")
|
|
54
|
+
arguments: (argument_list
|
|
55
|
+
(string) @blueprint.import_name
|
|
56
|
+
_
|
|
57
|
+
(keyword_argument
|
|
58
|
+
name: (identifier) @_upk
|
|
59
|
+
(#eq? @_upk "url_prefix")
|
|
60
|
+
value: (string) @blueprint.url_prefix
|
|
61
|
+
)?
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
) @blueprint.decl
|
|
65
|
+
|
|
66
|
+
; ── app.register_blueprint(bp, url_prefix="/api") ────────────────────────────
|
|
67
|
+
|
|
68
|
+
(call
|
|
69
|
+
function: (attribute
|
|
70
|
+
object: (identifier) @_app
|
|
71
|
+
attribute: (identifier) @_reg
|
|
72
|
+
(#eq? @_reg "register_blueprint")
|
|
73
|
+
)
|
|
74
|
+
arguments: (argument_list
|
|
75
|
+
(identifier) @app.register_bp
|
|
76
|
+
(keyword_argument
|
|
77
|
+
name: (identifier) @_upk
|
|
78
|
+
(#eq? @_upk "url_prefix")
|
|
79
|
+
value: (string) @app.register_prefix
|
|
80
|
+
)?
|
|
81
|
+
)
|
|
82
|
+
) @app.register
|
|
83
|
+
|
|
84
|
+
; ── SQLAlchemy / Flask-SQLAlchemy model ───────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
(class_definition
|
|
87
|
+
name: (identifier) @entity.class_name
|
|
88
|
+
superclasses: (argument_list
|
|
89
|
+
[
|
|
90
|
+
(attribute
|
|
91
|
+
attribute: (identifier) @_m
|
|
92
|
+
(#match? @_m "^(Model|Base)$")
|
|
93
|
+
)
|
|
94
|
+
(identifier) @_m
|
|
95
|
+
(#match? @_m "^(Model|Base)$")
|
|
96
|
+
]
|
|
97
|
+
)
|
|
98
|
+
) @entity.class
|
|
99
|
+
|
|
100
|
+
; SQLAlchemy Column fields
|
|
101
|
+
(assignment
|
|
102
|
+
left: (identifier) @entity.field_name
|
|
103
|
+
right: (call
|
|
104
|
+
function: [
|
|
105
|
+
(identifier) @entity.field_type
|
|
106
|
+
(attribute attribute: (identifier) @entity.field_type)
|
|
107
|
+
]
|
|
108
|
+
(#match? @entity.field_type "^(Column|relationship|backref)$")
|
|
109
|
+
)
|
|
110
|
+
) @entity.field
|
|
111
|
+
|
|
112
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
(import_from_statement
|
|
115
|
+
module_name: _ @import.path
|
|
116
|
+
) @import.from
|
|
117
|
+
|
|
118
|
+
(import_statement
|
|
119
|
+
name: _ @import.path
|
|
120
|
+
) @import.plain
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
; ── Gin / Echo / Fiber (Go) ───────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-go
|
|
3
|
+
;
|
|
4
|
+
; Go struct tag parsing note:
|
|
5
|
+
; GORM struct tags are raw string literals: `gorm:"primaryKey"`.
|
|
6
|
+
; These are parsed by extract/entities.py using regex on the raw text,
|
|
7
|
+
; not by tree-sitter queries (tree-sitter-go does not parse struct tags).
|
|
8
|
+
;
|
|
9
|
+
; Captures:
|
|
10
|
+
; @route.method - GET/POST/PUT/DELETE/PATCH/Any etc.
|
|
11
|
+
; @route.path - path string
|
|
12
|
+
; @route.object - router/group variable name
|
|
13
|
+
; @route.group_prefix - r.Group("/api") prefix string
|
|
14
|
+
; @route.handler_name - handler function identifier
|
|
15
|
+
; @service.struct_name - struct name (service)
|
|
16
|
+
; @service.field_type - field type (for DI via struct embedding)
|
|
17
|
+
; @entity.struct_name - GORM model struct name
|
|
18
|
+
; @entity.field_name - struct field name
|
|
19
|
+
; @entity.field_tag - raw struct tag string (for GORM parsing)
|
|
20
|
+
; @import.path - import path string
|
|
21
|
+
|
|
22
|
+
; ── r.GET("/path", handler) ──────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
(expression_statement
|
|
25
|
+
(call_expression
|
|
26
|
+
function: (selector_expression
|
|
27
|
+
operand: (identifier) @route.object
|
|
28
|
+
field: (field_identifier) @route.method
|
|
29
|
+
(#match? @route.method "^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD|Any|Handle|UseWithErr|Use)$")
|
|
30
|
+
)
|
|
31
|
+
arguments: (argument_list
|
|
32
|
+
(interpreted_string_literal) @route.path
|
|
33
|
+
(identifier) @route.handler_name
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
) @route.call
|
|
37
|
+
|
|
38
|
+
; Case-insensitive method names (Echo: e.GET, Fiber: app.Get)
|
|
39
|
+
(expression_statement
|
|
40
|
+
(call_expression
|
|
41
|
+
function: (selector_expression
|
|
42
|
+
operand: (identifier) @route.object
|
|
43
|
+
field: (field_identifier) @route.method
|
|
44
|
+
(#match? @route.method "^(Get|Post|Put|Patch|Delete|Options|Head|All|Add)$")
|
|
45
|
+
)
|
|
46
|
+
arguments: (argument_list
|
|
47
|
+
(interpreted_string_literal) @route.path
|
|
48
|
+
(identifier) @route.handler_name
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
) @route.call_lower
|
|
52
|
+
|
|
53
|
+
; ── r.Group("/prefix") ───────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
(short_var_declaration
|
|
56
|
+
left: (expression_list
|
|
57
|
+
(identifier) @route.group_name
|
|
58
|
+
)
|
|
59
|
+
right: (expression_list
|
|
60
|
+
(call_expression
|
|
61
|
+
function: (selector_expression
|
|
62
|
+
operand: (identifier) @_router
|
|
63
|
+
field: (field_identifier) @_group
|
|
64
|
+
(#eq? @_group "Group")
|
|
65
|
+
)
|
|
66
|
+
arguments: (argument_list
|
|
67
|
+
(interpreted_string_literal) @route.group_prefix
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
) @route.group_decl
|
|
72
|
+
|
|
73
|
+
; ── Service struct ────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
(type_declaration
|
|
76
|
+
(type_spec
|
|
77
|
+
name: (type_identifier) @service.struct_name
|
|
78
|
+
type: (struct_type
|
|
79
|
+
(field_declaration_list
|
|
80
|
+
(field_declaration
|
|
81
|
+
type: (pointer_type
|
|
82
|
+
(type_identifier) @service.field_type
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
) @service.struct
|
|
89
|
+
|
|
90
|
+
(type_declaration
|
|
91
|
+
(type_spec
|
|
92
|
+
name: (type_identifier) @service.struct_name
|
|
93
|
+
type: (struct_type
|
|
94
|
+
(field_declaration_list
|
|
95
|
+
(field_declaration
|
|
96
|
+
type: (type_identifier) @service.field_type
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
) @service.struct_plain
|
|
102
|
+
|
|
103
|
+
; ── GORM entity struct ────────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
(type_declaration
|
|
106
|
+
(type_spec
|
|
107
|
+
name: (type_identifier) @entity.struct_name
|
|
108
|
+
type: (struct_type
|
|
109
|
+
(field_declaration_list
|
|
110
|
+
(field_declaration
|
|
111
|
+
name: (field_identifier) @entity.field_name
|
|
112
|
+
type: _ @entity.field_type
|
|
113
|
+
tag: (raw_string_literal) @entity.field_tag
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
) @entity.struct
|
|
119
|
+
|
|
120
|
+
; Struct with no tags (still useful for type extraction)
|
|
121
|
+
(type_declaration
|
|
122
|
+
(type_spec
|
|
123
|
+
name: (type_identifier) @entity.struct_name
|
|
124
|
+
type: (struct_type)
|
|
125
|
+
)
|
|
126
|
+
) @entity.struct_bare
|
|
127
|
+
|
|
128
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
(import_declaration
|
|
131
|
+
(import_spec_list
|
|
132
|
+
(import_spec
|
|
133
|
+
path: (interpreted_string_literal) @import.path
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
) @import.block
|
|
137
|
+
|
|
138
|
+
(import_declaration
|
|
139
|
+
(import_spec
|
|
140
|
+
path: (interpreted_string_literal) @import.path
|
|
141
|
+
)
|
|
142
|
+
) @import.single
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
; ── Ktor (Kotlin) ─────────────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-kotlin
|
|
3
|
+
;
|
|
4
|
+
; Kotlin grammar note:
|
|
5
|
+
; - call_expression: f(args) — can have trailing lambda
|
|
6
|
+
; - annotated_lambda / lambda_literal: trailing { } block
|
|
7
|
+
; - value_arguments: (args)
|
|
8
|
+
; - value_argument → string_literal → string_content: path string
|
|
9
|
+
; - identifier: function name (get, post, route, routing)
|
|
10
|
+
; - qualified_identifier: import paths
|
|
11
|
+
;
|
|
12
|
+
; Ktor routing DSL nesting:
|
|
13
|
+
; routing {
|
|
14
|
+
; get("/a") { } → GET /a
|
|
15
|
+
; route("/prefix") {
|
|
16
|
+
; get("/b") { } → GET /prefix/b
|
|
17
|
+
; }
|
|
18
|
+
; }
|
|
19
|
+
; Path composition is done by extract/routes.py by tracking nesting depth
|
|
20
|
+
; using start_point line numbers. This file captures individual route/method calls.
|
|
21
|
+
;
|
|
22
|
+
; Captures:
|
|
23
|
+
; @route.method - get/post/put/patch/delete (HTTP method)
|
|
24
|
+
; @route.path - path string content
|
|
25
|
+
; @route.route_prefix - route("prefix") path — prefix scope
|
|
26
|
+
; @route.call_line - line number for nesting (via @route.call node)
|
|
27
|
+
; @service.koin_type - Koin: single/factory/scoped class
|
|
28
|
+
; @entity.table_name - Exposed Table object name
|
|
29
|
+
; @entity.column_name - Exposed column name
|
|
30
|
+
; @import.path - import qualified path
|
|
31
|
+
|
|
32
|
+
; ── routing { get("/path") { } } ─────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
; Direct HTTP method call: get("/path") { }
|
|
35
|
+
(call_expression
|
|
36
|
+
(call_expression
|
|
37
|
+
(identifier) @route.method
|
|
38
|
+
(#match? @route.method "^(get|post|put|patch|delete|options|head)$")
|
|
39
|
+
(value_arguments
|
|
40
|
+
(value_argument
|
|
41
|
+
(string_literal
|
|
42
|
+
(string_content) @route.path
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
(annotated_lambda)?
|
|
48
|
+
) @route.method_call
|
|
49
|
+
|
|
50
|
+
; Also handle: get("/path") without trailing lambda
|
|
51
|
+
(call_expression
|
|
52
|
+
(identifier) @route.method
|
|
53
|
+
(#match? @route.method "^(get|post|put|patch|delete|options|head)$")
|
|
54
|
+
(value_arguments
|
|
55
|
+
(value_argument
|
|
56
|
+
(string_literal
|
|
57
|
+
(string_content) @route.path
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
) @route.method_call_simple
|
|
62
|
+
|
|
63
|
+
; ── route("/prefix") { } — creates a path prefix scope ───────────────────────
|
|
64
|
+
|
|
65
|
+
(call_expression
|
|
66
|
+
(call_expression
|
|
67
|
+
(identifier) @_route_fn
|
|
68
|
+
(#eq? @_route_fn "route")
|
|
69
|
+
(value_arguments
|
|
70
|
+
(value_argument
|
|
71
|
+
(string_literal
|
|
72
|
+
(string_content) @route.route_prefix
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
(annotated_lambda)
|
|
78
|
+
) @route.prefix_scope
|
|
79
|
+
|
|
80
|
+
; ── Koin DI: single { UserService(get()) } ───────────────────────────────────
|
|
81
|
+
|
|
82
|
+
(call_expression
|
|
83
|
+
(identifier) @_koin_scope
|
|
84
|
+
(#match? @_koin_scope "^(single|factory|scoped|viewModel|worker)$")
|
|
85
|
+
(annotated_lambda
|
|
86
|
+
(lambda_literal
|
|
87
|
+
(call_expression
|
|
88
|
+
(identifier) @service.koin_type
|
|
89
|
+
(value_arguments)?
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
) @service.koin_binding
|
|
94
|
+
|
|
95
|
+
; ── Exposed ORM: object Users : Table() ──────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
(object_declaration
|
|
98
|
+
(identifier) @entity.table_name
|
|
99
|
+
(delegation_specifier
|
|
100
|
+
(constructor_invocation
|
|
101
|
+
(user_type (identifier) @_table (#match? @_table "^(Table|IntIdTable|LongIdTable|UUIDTable|IdTable)$"))
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
) @entity.table
|
|
105
|
+
|
|
106
|
+
; Exposed columns: val id = integer("id")
|
|
107
|
+
(property_declaration
|
|
108
|
+
(variable_declaration
|
|
109
|
+
(simple_identifier) @entity.column_name
|
|
110
|
+
)
|
|
111
|
+
(call_expression
|
|
112
|
+
(identifier) @entity.column_type
|
|
113
|
+
(#match? @entity.column_type "^(integer|long|varchar|text|bool|double|float|decimal|uuid|reference|optReference|enumeration|enumerationByName|date|datetime|timestamp)$")
|
|
114
|
+
(value_arguments
|
|
115
|
+
(value_argument
|
|
116
|
+
(string_literal
|
|
117
|
+
(string_content) @entity.column_key
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
) @entity.column
|
|
123
|
+
|
|
124
|
+
; ── Data class (Kotlin entity / DTO) ─────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
(class_declaration
|
|
127
|
+
(modifiers
|
|
128
|
+
(class_modifier) @_data
|
|
129
|
+
(#eq? @_data "data")
|
|
130
|
+
)
|
|
131
|
+
(simple_identifier) @entity.class_name
|
|
132
|
+
) @entity.data_class
|
|
133
|
+
|
|
134
|
+
; ── Regular class (service) ───────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
(class_declaration
|
|
137
|
+
(simple_identifier) @service.class_name
|
|
138
|
+
) @service.class
|
|
139
|
+
|
|
140
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
(import
|
|
143
|
+
(qualified_identifier) @import.path
|
|
144
|
+
) @import.decl
|