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,172 @@
|
|
|
1
|
+
; ── Laravel (PHP) ─────────────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-php
|
|
3
|
+
;
|
|
4
|
+
; PHP grammar note:
|
|
5
|
+
; - scoped_call_expression: Route::get(...) (static method call)
|
|
6
|
+
; - member_call_expression: Route::prefix("api")->group(...)
|
|
7
|
+
; - class_constant_access_expression: UserController::class
|
|
8
|
+
; - encapsed_string: PHP double-quoted string
|
|
9
|
+
; - name nodes: identifiers in PHP
|
|
10
|
+
;
|
|
11
|
+
; Special handling in extract/routes.py:
|
|
12
|
+
; - Route::resource("users", ...) → 7 CRUD routes expanded
|
|
13
|
+
; - Route::prefix("api")->group(fn) → prefix propagation
|
|
14
|
+
;
|
|
15
|
+
; Captures:
|
|
16
|
+
; @route.method - get/post/put/patch/delete/any
|
|
17
|
+
; @route.path - path string content
|
|
18
|
+
; @route.controller - ControllerClass::class → class name
|
|
19
|
+
; @route.resource_name - Route::resource("users") → "users"
|
|
20
|
+
; @route.prefix - Route::prefix("api") value
|
|
21
|
+
; @entity.class_name - Eloquent Model subclass
|
|
22
|
+
; @entity.relation_type - hasMany/belongsTo/hasOne etc.
|
|
23
|
+
; @entity.relation_model - target model class
|
|
24
|
+
; @service.class_name - service/provider class
|
|
25
|
+
; @di.interface - $this->app->bind(Interface::class, ...)
|
|
26
|
+
; @di.implementation - bind target class
|
|
27
|
+
; @import.path - use Namespace\Class
|
|
28
|
+
|
|
29
|
+
; ── Route::get("/path", [Controller::class, "method"]) ───────────────────────
|
|
30
|
+
|
|
31
|
+
(expression_statement
|
|
32
|
+
(scoped_call_expression
|
|
33
|
+
name: (name) @_class (#eq? @_class "Route")
|
|
34
|
+
(name) @route.method
|
|
35
|
+
(#match? @route.method "^(get|post|put|patch|delete|options|any|match)$")
|
|
36
|
+
(arguments
|
|
37
|
+
(argument
|
|
38
|
+
[
|
|
39
|
+
(encapsed_string (string_content) @route.path)
|
|
40
|
+
(string (string_content) @route.path)
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
(argument
|
|
44
|
+
[
|
|
45
|
+
(array_creation_expression
|
|
46
|
+
(array_element_initializer
|
|
47
|
+
(class_constant_access_expression
|
|
48
|
+
(name) @route.controller
|
|
49
|
+
(name) @_class_kw (#eq? @_class_kw "class")
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
(string (string_content) @route.closure_action)
|
|
54
|
+
]
|
|
55
|
+
)?
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
) @route.call
|
|
59
|
+
|
|
60
|
+
; ── Route::resource("users", UserController::class) ──────────────────────────
|
|
61
|
+
|
|
62
|
+
(expression_statement
|
|
63
|
+
(scoped_call_expression
|
|
64
|
+
name: (name) @_class (#eq? @_class "Route")
|
|
65
|
+
(name) @_res (#match? @_res "^(resource|apiResource|resources|apiResources)$")
|
|
66
|
+
(arguments
|
|
67
|
+
(argument
|
|
68
|
+
[
|
|
69
|
+
(encapsed_string (string_content) @route.resource_name)
|
|
70
|
+
(string (string_content) @route.resource_name)
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
(argument
|
|
74
|
+
(class_constant_access_expression
|
|
75
|
+
(name) @route.resource_controller
|
|
76
|
+
(name) @_ck (#eq? @_ck "class")
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
) @route.resource
|
|
82
|
+
|
|
83
|
+
; ── Route::prefix("api")->group(...) ─────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
(expression_statement
|
|
86
|
+
(member_call_expression
|
|
87
|
+
object: (scoped_call_expression
|
|
88
|
+
name: (name) @_class (#eq? @_class "Route")
|
|
89
|
+
(name) @_prefix (#eq? @_prefix "prefix")
|
|
90
|
+
(arguments
|
|
91
|
+
(argument
|
|
92
|
+
[
|
|
93
|
+
(encapsed_string (string_content) @route.prefix)
|
|
94
|
+
(string (string_content) @route.prefix)
|
|
95
|
+
]
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
name: (name) @_group (#eq? @_group "group")
|
|
100
|
+
)
|
|
101
|
+
) @route.prefix_group
|
|
102
|
+
|
|
103
|
+
; ── Route::middleware(...)->prefix(...)->group(...) chains ────────────────────
|
|
104
|
+
; Covered by member_call_expression nesting — prefix propagation in routes.py
|
|
105
|
+
|
|
106
|
+
; ── Eloquent Model subclass ───────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
(class_declaration
|
|
109
|
+
name: (name) @entity.class_name
|
|
110
|
+
(base_clause
|
|
111
|
+
(qualified_name (name) @_base (#match? @_base "^(Model|Authenticatable)$"))
|
|
112
|
+
)
|
|
113
|
+
) @entity.model
|
|
114
|
+
|
|
115
|
+
; Eloquent relations
|
|
116
|
+
(method_declaration
|
|
117
|
+
name: (name) @entity.relation_type
|
|
118
|
+
(#match? @entity.relation_type "^(hasMany|hasOne|belongsTo|belongsToMany|hasManyThrough|hasOneThrough|morphTo|morphMany|morphOne)$")
|
|
119
|
+
(compound_statement
|
|
120
|
+
(return_statement
|
|
121
|
+
(member_call_expression
|
|
122
|
+
name: (name) @_rel_fn
|
|
123
|
+
(arguments
|
|
124
|
+
(argument
|
|
125
|
+
(class_constant_access_expression
|
|
126
|
+
(name) @entity.relation_model
|
|
127
|
+
(name) @_ck (#eq? @_ck "class")
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
) @entity.relation
|
|
135
|
+
|
|
136
|
+
; ── Service provider bindings ─────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
(member_call_expression
|
|
139
|
+
object: (member_access_expression
|
|
140
|
+
object: (variable_name (name) @_this (#eq? @_this "this"))
|
|
141
|
+
name: (name) @_app (#eq? @_app "app")
|
|
142
|
+
)
|
|
143
|
+
name: (name) @_bind (#match? @_bind "^(bind|singleton|scoped|transient)$")
|
|
144
|
+
(arguments
|
|
145
|
+
(argument
|
|
146
|
+
(class_constant_access_expression
|
|
147
|
+
(name) @di.interface
|
|
148
|
+
(name) @_ck (#eq? @_ck "class")
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
(argument
|
|
152
|
+
(class_constant_access_expression
|
|
153
|
+
(name) @di.implementation
|
|
154
|
+
(name) @_ck2 (#eq? @_ck2 "class")
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
) @di.binding
|
|
159
|
+
|
|
160
|
+
; ── Plain service class ───────────────────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
(class_declaration
|
|
163
|
+
name: (name) @service.class_name
|
|
164
|
+
) @service.class
|
|
165
|
+
|
|
166
|
+
; ── use statements ────────────────────────────────────────────────────────────
|
|
167
|
+
|
|
168
|
+
(namespace_use_declaration
|
|
169
|
+
(namespace_use_clause
|
|
170
|
+
(qualified_name) @import.path
|
|
171
|
+
)
|
|
172
|
+
) @import.use
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
; ── NestJS (TypeScript) ───────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-typescript
|
|
3
|
+
;
|
|
4
|
+
; TypeScript AST note:
|
|
5
|
+
; In tree-sitter-typescript, class-level decorators (@Controller, @Injectable,
|
|
6
|
+
; @Entity) are siblings of class_declaration inside export_statement, not
|
|
7
|
+
; children of class_declaration.
|
|
8
|
+
; Method-level decorators (@Get, @Post) are siblings of method_definition
|
|
9
|
+
; inside class_body, connected via the `.` (immediate sibling) anchor.
|
|
10
|
+
;
|
|
11
|
+
; Captures:
|
|
12
|
+
; @route.controller_prefix - @Controller("prefix") value
|
|
13
|
+
; @route.class_name - controller class name
|
|
14
|
+
; @route.method_decorator - @Get/@Post/@Put/@Delete/@Patch
|
|
15
|
+
; @route.method_name - handler method name
|
|
16
|
+
; @route.path_value - path string literal
|
|
17
|
+
; @service.class_name - @Injectable() class name
|
|
18
|
+
; @service.inject_type - constructor injected type
|
|
19
|
+
; @module.providers - providers array items
|
|
20
|
+
; @entity.class_name - @Entity() class name
|
|
21
|
+
; @import.path - import source
|
|
22
|
+
|
|
23
|
+
; ── @Controller("prefix") class ──────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
; export_statement wraps the decorator + class_declaration
|
|
26
|
+
(export_statement
|
|
27
|
+
(decorator
|
|
28
|
+
(call_expression
|
|
29
|
+
function: (identifier) @_ctrl
|
|
30
|
+
(#eq? @_ctrl "Controller")
|
|
31
|
+
arguments: (arguments
|
|
32
|
+
(string) @route.controller_prefix
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
declaration: (class_declaration
|
|
37
|
+
name: (type_identifier) @route.class_name
|
|
38
|
+
)
|
|
39
|
+
) @route.controller_with_prefix
|
|
40
|
+
|
|
41
|
+
; @Controller() without prefix
|
|
42
|
+
(export_statement
|
|
43
|
+
(decorator
|
|
44
|
+
(call_expression
|
|
45
|
+
function: (identifier) @_ctrl2
|
|
46
|
+
(#eq? @_ctrl2 "Controller")
|
|
47
|
+
arguments: (arguments)
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
declaration: (class_declaration
|
|
51
|
+
name: (type_identifier) @route.class_name
|
|
52
|
+
)
|
|
53
|
+
) @route.controller_no_prefix
|
|
54
|
+
|
|
55
|
+
; Non-exported @Controller
|
|
56
|
+
(class_declaration
|
|
57
|
+
(decorator
|
|
58
|
+
(call_expression
|
|
59
|
+
function: (identifier) @_ctrl3
|
|
60
|
+
(#eq? @_ctrl3 "Controller")
|
|
61
|
+
arguments: (arguments
|
|
62
|
+
(string) @route.controller_prefix
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
name: (type_identifier) @route.class_name
|
|
67
|
+
) @route.controller_with_prefix_noexport
|
|
68
|
+
|
|
69
|
+
; ── HTTP method decorators on methods (sibling pattern) ─────────────────────
|
|
70
|
+
|
|
71
|
+
; Decorator + method_definition as adjacent siblings in class_body
|
|
72
|
+
(class_body
|
|
73
|
+
(decorator
|
|
74
|
+
(call_expression
|
|
75
|
+
function: (identifier) @route.method_decorator
|
|
76
|
+
(#match? @route.method_decorator "^(Get|Post|Put|Delete|Patch|Options|Head|All)$")
|
|
77
|
+
arguments: (arguments
|
|
78
|
+
(string) @route.path_value
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
.
|
|
83
|
+
(method_definition
|
|
84
|
+
name: (property_identifier) @route.method_name
|
|
85
|
+
)
|
|
86
|
+
) @route.handler
|
|
87
|
+
|
|
88
|
+
; Decorator without path argument
|
|
89
|
+
(class_body
|
|
90
|
+
(decorator
|
|
91
|
+
(call_expression
|
|
92
|
+
function: (identifier) @route.method_decorator
|
|
93
|
+
(#match? @route.method_decorator "^(Get|Post|Put|Delete|Patch|Options|Head|All)$")
|
|
94
|
+
arguments: (arguments)
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
.
|
|
98
|
+
(method_definition
|
|
99
|
+
name: (property_identifier) @route.method_name
|
|
100
|
+
)
|
|
101
|
+
) @route.handler_no_path
|
|
102
|
+
|
|
103
|
+
; ── @Injectable() service ────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
(export_statement
|
|
106
|
+
(decorator
|
|
107
|
+
(call_expression
|
|
108
|
+
function: (identifier) @_inj
|
|
109
|
+
(#eq? @_inj "Injectable")
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
declaration: (class_declaration
|
|
113
|
+
name: (type_identifier) @service.class_name
|
|
114
|
+
)
|
|
115
|
+
) @service.injectable
|
|
116
|
+
|
|
117
|
+
; Non-exported @Injectable
|
|
118
|
+
(class_declaration
|
|
119
|
+
(decorator
|
|
120
|
+
(call_expression
|
|
121
|
+
function: (identifier) @_inj2
|
|
122
|
+
(#eq? @_inj2 "Injectable")
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
name: (type_identifier) @service.class_name
|
|
126
|
+
) @service.injectable_noexport
|
|
127
|
+
|
|
128
|
+
; Constructor DI (inside any class)
|
|
129
|
+
; required_parameter uses field "pattern" for the identifier, not "name"
|
|
130
|
+
(method_definition
|
|
131
|
+
name: (property_identifier) @_ctor
|
|
132
|
+
(#eq? @_ctor "constructor")
|
|
133
|
+
parameters: (formal_parameters
|
|
134
|
+
(required_parameter
|
|
135
|
+
pattern: (identifier) @_pname
|
|
136
|
+
type: (type_annotation
|
|
137
|
+
(type_identifier) @service.inject_type
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
) @service.constructor_di
|
|
142
|
+
|
|
143
|
+
; ── @Module({ providers: [...] }) ────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
(export_statement
|
|
146
|
+
(decorator
|
|
147
|
+
(call_expression
|
|
148
|
+
function: (identifier) @_mod
|
|
149
|
+
(#eq? @_mod "Module")
|
|
150
|
+
arguments: (arguments
|
|
151
|
+
(object
|
|
152
|
+
(pair
|
|
153
|
+
key: (property_identifier) @_providers_key
|
|
154
|
+
(#eq? @_providers_key "providers")
|
|
155
|
+
value: (array
|
|
156
|
+
(identifier) @module.providers
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
) @module.class
|
|
164
|
+
|
|
165
|
+
; ── @Entity() / @Schema() ───────────────────────────────────────────────────
|
|
166
|
+
|
|
167
|
+
(export_statement
|
|
168
|
+
(decorator
|
|
169
|
+
(call_expression
|
|
170
|
+
function: (identifier) @_ent
|
|
171
|
+
(#match? @_ent "^(Entity|Schema)$")
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
declaration: (class_declaration
|
|
175
|
+
name: (type_identifier) @entity.class_name
|
|
176
|
+
)
|
|
177
|
+
) @entity.class
|
|
178
|
+
|
|
179
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
(import_statement
|
|
182
|
+
source: (string) @import.path
|
|
183
|
+
) @import.decl
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
; ── Rails (Ruby) ──────────────────────────────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-ruby
|
|
3
|
+
;
|
|
4
|
+
; Special handling note:
|
|
5
|
+
; - `resources :users` → 7 CRUD routes expanded by extract/routes.py
|
|
6
|
+
; - `db/schema.rb` parsed separately for table columns
|
|
7
|
+
; - `routes.rb` is dispatched to this query by the extractor
|
|
8
|
+
;
|
|
9
|
+
; Captures:
|
|
10
|
+
; @route.resources_name - resources :users name
|
|
11
|
+
; @route.http_method - get/post/put/patch/delete
|
|
12
|
+
; @route.path - path string
|
|
13
|
+
; @route.to - "controller#action" string
|
|
14
|
+
; @route.namespace - namespace/scope block
|
|
15
|
+
; @route.member_action - member/collection route method
|
|
16
|
+
; @entity.class_name - ApplicationRecord subclass
|
|
17
|
+
; @entity.relation_type - has_many/belongs_to/has_one/has_and_belongs_to_many
|
|
18
|
+
; @entity.relation_target - relation target name (symbol)
|
|
19
|
+
; @service.class_name - plain Ruby service class
|
|
20
|
+
; @import.path - require path
|
|
21
|
+
|
|
22
|
+
; ── resources :model_name ────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
(call
|
|
25
|
+
method: (identifier) @_res
|
|
26
|
+
(#match? @_res "^(resources|resource)$")
|
|
27
|
+
arguments: (argument_list
|
|
28
|
+
(simple_symbol) @route.resources_name
|
|
29
|
+
)
|
|
30
|
+
) @route.resources
|
|
31
|
+
|
|
32
|
+
; resources :users, only: [:index, :show]
|
|
33
|
+
(call
|
|
34
|
+
method: (identifier) @_res
|
|
35
|
+
(#match? @_res "^(resources|resource)$")
|
|
36
|
+
arguments: (argument_list
|
|
37
|
+
(simple_symbol) @route.resources_name
|
|
38
|
+
(pair
|
|
39
|
+
key: (hash_key_symbol) @_only
|
|
40
|
+
(#match? @_only "^(only|except)$")
|
|
41
|
+
value: (array
|
|
42
|
+
(simple_symbol) @route.resources_filter
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
) @route.resources_filtered
|
|
47
|
+
|
|
48
|
+
; ── get/post/put/patch/delete "path", to: "ctrl#action" ──────────────────────
|
|
49
|
+
|
|
50
|
+
(call
|
|
51
|
+
method: (identifier) @route.http_method
|
|
52
|
+
(#match? @route.http_method "^(get|post|put|patch|delete|match|root)$")
|
|
53
|
+
arguments: (argument_list
|
|
54
|
+
(string) @route.path
|
|
55
|
+
(pair
|
|
56
|
+
key: (hash_key_symbol) @_to
|
|
57
|
+
(#eq? @_to "to")
|
|
58
|
+
value: (string) @route.to
|
|
59
|
+
)?
|
|
60
|
+
)
|
|
61
|
+
) @route.explicit
|
|
62
|
+
|
|
63
|
+
; ── namespace/scope blocks ────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
(call
|
|
66
|
+
method: (identifier) @route.namespace
|
|
67
|
+
(#match? @route.namespace "^(namespace|scope|constraints|concern)$")
|
|
68
|
+
arguments: (argument_list
|
|
69
|
+
(string)? @route.namespace_path
|
|
70
|
+
(simple_symbol)? @route.namespace_path
|
|
71
|
+
)
|
|
72
|
+
block: _
|
|
73
|
+
) @route.namespace_block
|
|
74
|
+
|
|
75
|
+
; ── ApplicationRecord / ActiveRecord model ────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
(class
|
|
78
|
+
name: (constant) @entity.class_name
|
|
79
|
+
superclass: (superclass
|
|
80
|
+
[
|
|
81
|
+
(constant) @_base
|
|
82
|
+
(#match? @_base "^(ApplicationRecord|ActiveRecord)$")
|
|
83
|
+
(scope_resolution
|
|
84
|
+
name: (constant) @_base
|
|
85
|
+
(#eq? @_base "Base")
|
|
86
|
+
)
|
|
87
|
+
]
|
|
88
|
+
)
|
|
89
|
+
) @entity.model
|
|
90
|
+
|
|
91
|
+
; Associations
|
|
92
|
+
(call
|
|
93
|
+
method: (identifier) @entity.relation_type
|
|
94
|
+
(#match? @entity.relation_type "^(has_many|has_one|belongs_to|has_and_belongs_to_many)$")
|
|
95
|
+
arguments: (argument_list
|
|
96
|
+
(simple_symbol) @entity.relation_target
|
|
97
|
+
)
|
|
98
|
+
) @entity.association
|
|
99
|
+
|
|
100
|
+
; ── Plain service class ───────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
(class
|
|
103
|
+
name: (constant) @service.class_name
|
|
104
|
+
) @service.class
|
|
105
|
+
|
|
106
|
+
; ── require ───────────────────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
(call
|
|
109
|
+
method: (identifier) @_req
|
|
110
|
+
(#match? @_req "^(require|require_relative)$")
|
|
111
|
+
arguments: (argument_list
|
|
112
|
+
(string) @import.path
|
|
113
|
+
)
|
|
114
|
+
) @import.require
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
; ── React / Next.js (TSX / TypeScript) ───────────────────────────────────────
|
|
2
|
+
; Grammar: tree-sitter-typescript (for .ts) / tree-sitter-tsx (for .tsx)
|
|
3
|
+
;
|
|
4
|
+
; Component detection heuristic:
|
|
5
|
+
; - Exported function/arrow-function whose name starts with uppercase
|
|
6
|
+
; - Function returning JSX (jsx_element, jsx_self_closing_element) — TSX grammar
|
|
7
|
+
; - React.memo(Component), React.forwardRef(Component) wrappers
|
|
8
|
+
;
|
|
9
|
+
; Next.js routes: handled by convention in detector.py (file path → route).
|
|
10
|
+
; This file captures component names and hooks for the graph.
|
|
11
|
+
;
|
|
12
|
+
; Captures:
|
|
13
|
+
; @component.func_name - exported function component name
|
|
14
|
+
; @component.arrow_name - arrow function component name (const Foo = ...)
|
|
15
|
+
; @component.memo_name - React.memo(Component) → inner component
|
|
16
|
+
; @hook.name - used hooks (useState, useEffect, custom useX)
|
|
17
|
+
; @prop.name - prop destructuring pattern names
|
|
18
|
+
; @route.pages_path - file-system route (extracted from filename in routes.py)
|
|
19
|
+
; @server.directive - "use server" / "use client" directive
|
|
20
|
+
; @import.path - import source
|
|
21
|
+
|
|
22
|
+
; ── Exported function component ───────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
(export_statement
|
|
25
|
+
(function_declaration
|
|
26
|
+
name: (identifier) @component.func_name
|
|
27
|
+
)
|
|
28
|
+
) @component.export_func
|
|
29
|
+
|
|
30
|
+
(export_statement
|
|
31
|
+
(function_declaration
|
|
32
|
+
name: (identifier) @component.func_name
|
|
33
|
+
(#match? @component.func_name "^[A-Z]")
|
|
34
|
+
)
|
|
35
|
+
) @component.export_func_upper
|
|
36
|
+
|
|
37
|
+
; export default function Component
|
|
38
|
+
(export_statement
|
|
39
|
+
"default"
|
|
40
|
+
(function_declaration
|
|
41
|
+
name: (identifier) @component.func_name
|
|
42
|
+
)
|
|
43
|
+
) @component.export_default_func
|
|
44
|
+
|
|
45
|
+
; ── Arrow function component: export const Foo = (...) => ────────────────────
|
|
46
|
+
|
|
47
|
+
(export_statement
|
|
48
|
+
(lexical_declaration
|
|
49
|
+
(variable_declarator
|
|
50
|
+
name: (identifier) @component.arrow_name
|
|
51
|
+
(#match? @component.arrow_name "^[A-Z]")
|
|
52
|
+
value: (arrow_function)
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
) @component.export_arrow
|
|
56
|
+
|
|
57
|
+
; Non-exported: const Foo = () => (used as sub-component)
|
|
58
|
+
(lexical_declaration
|
|
59
|
+
(variable_declarator
|
|
60
|
+
name: (identifier) @component.arrow_name
|
|
61
|
+
(#match? @component.arrow_name "^[A-Z]")
|
|
62
|
+
value: (arrow_function)
|
|
63
|
+
)
|
|
64
|
+
) @component.local_arrow
|
|
65
|
+
|
|
66
|
+
; ── React.memo / React.forwardRef ────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
(export_statement
|
|
69
|
+
(lexical_declaration
|
|
70
|
+
(variable_declarator
|
|
71
|
+
name: (identifier) @component.memo_name
|
|
72
|
+
value: (call_expression
|
|
73
|
+
function: (member_expression
|
|
74
|
+
object: (identifier) @_react (#eq? @_react "React")
|
|
75
|
+
property: (property_identifier) @_hoc
|
|
76
|
+
(#match? @_hoc "^(memo|forwardRef|lazy)$")
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
) @component.hoc
|
|
82
|
+
|
|
83
|
+
; ── Hook usage ────────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
(call_expression
|
|
86
|
+
function: (identifier) @hook.name
|
|
87
|
+
(#match? @hook.name "^use[A-Z]")
|
|
88
|
+
) @hook.call
|
|
89
|
+
|
|
90
|
+
(call_expression
|
|
91
|
+
function: (member_expression
|
|
92
|
+
object: (identifier) @_react (#eq? @_react "React")
|
|
93
|
+
property: (property_identifier) @hook.name
|
|
94
|
+
(#match? @hook.name "^use[A-Z]")
|
|
95
|
+
)
|
|
96
|
+
) @hook.react_call
|
|
97
|
+
|
|
98
|
+
; ── "use client" / "use server" directive (Next.js App Router) ───────────────
|
|
99
|
+
|
|
100
|
+
(expression_statement
|
|
101
|
+
(string
|
|
102
|
+
(string_fragment) @server.directive
|
|
103
|
+
(#match? @server.directive "^use (client|server)$")
|
|
104
|
+
)
|
|
105
|
+
) @server.directive_stmt
|
|
106
|
+
|
|
107
|
+
; ── imports ───────────────────────────────────────────────────────────────────
|
|
108
|
+
|
|
109
|
+
(import_statement
|
|
110
|
+
source: (string) @import.path
|
|
111
|
+
) @import.decl
|