@optave/codegraph 3.1.0 → 3.1.1

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.
Files changed (47) hide show
  1. package/README.md +5 -5
  2. package/grammars/tree-sitter-go.wasm +0 -0
  3. package/package.json +8 -9
  4. package/src/ast-analysis/rules/csharp.js +201 -0
  5. package/src/ast-analysis/rules/go.js +182 -0
  6. package/src/ast-analysis/rules/index.js +82 -0
  7. package/src/ast-analysis/rules/java.js +175 -0
  8. package/src/ast-analysis/rules/javascript.js +246 -0
  9. package/src/ast-analysis/rules/php.js +219 -0
  10. package/src/ast-analysis/rules/python.js +196 -0
  11. package/src/ast-analysis/rules/ruby.js +204 -0
  12. package/src/ast-analysis/rules/rust.js +173 -0
  13. package/src/ast-analysis/shared.js +223 -0
  14. package/src/ast.js +15 -28
  15. package/src/audit.js +4 -5
  16. package/src/boundaries.js +1 -1
  17. package/src/branch-compare.js +84 -79
  18. package/src/builder.js +0 -5
  19. package/src/cfg.js +106 -338
  20. package/src/check.js +3 -3
  21. package/src/cli.js +99 -179
  22. package/src/cochange.js +1 -1
  23. package/src/communities.js +13 -16
  24. package/src/complexity.js +196 -1239
  25. package/src/cycles.js +1 -1
  26. package/src/dataflow.js +269 -694
  27. package/src/db/connection.js +88 -0
  28. package/src/db/migrations.js +312 -0
  29. package/src/db/query-builder.js +280 -0
  30. package/src/db/repository.js +134 -0
  31. package/src/db.js +19 -399
  32. package/src/embedder.js +145 -141
  33. package/src/export.js +1 -1
  34. package/src/flow.js +161 -162
  35. package/src/index.js +34 -1
  36. package/src/kinds.js +49 -0
  37. package/src/manifesto.js +3 -8
  38. package/src/mcp.js +37 -20
  39. package/src/owners.js +132 -132
  40. package/src/queries-cli.js +866 -0
  41. package/src/queries.js +1323 -2267
  42. package/src/result-formatter.js +21 -0
  43. package/src/sequence.js +177 -182
  44. package/src/structure.js +200 -199
  45. package/src/test-filter.js +7 -0
  46. package/src/triage.js +120 -162
  47. package/src/viewer.js +1 -1
package/README.md CHANGED
@@ -562,14 +562,14 @@ Self-measured on every release via CI ([build benchmarks](generated/benchmarks/B
562
562
 
563
563
  | Metric | Latest |
564
564
  |---|---|
565
- | Build speed (native) | **6.2 ms/file** |
566
- | Build speed (WASM) | **19 ms/file** |
565
+ | Build speed (native) | **6.1 ms/file** |
566
+ | Build speed (WASM) | **16.5 ms/file** |
567
567
  | Query time | **3ms** |
568
- | No-op rebuild (native) | **329ms** |
569
- | 1-file rebuild (native) | **335ms** |
568
+ | No-op rebuild (native) | **5ms** |
569
+ | 1-file rebuild (native) | **332ms** |
570
570
  | Query: fn-deps | **0.8ms** |
571
571
  | Query: path | **0.8ms** |
572
- | ~50,000 files (est.) | **~310.0s build** |
572
+ | ~50,000 files (est.) | **~305.0s build** |
573
573
 
574
574
  Metrics are normalized per file for cross-version comparability. Times above are for a full initial build — incremental rebuilds only re-parse changed files.
575
575
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optave/codegraph",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Local code graph CLI — parse codebases with tree-sitter, build dependency graphs, query them",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -71,13 +71,12 @@
71
71
  },
72
72
  "optionalDependencies": {
73
73
  "@modelcontextprotocol/sdk": "^1.0.0",
74
- "@optave/codegraph-darwin-arm64": "3.1.0",
75
- "@optave/codegraph-darwin-x64": "3.1.0",
76
- "@optave/codegraph-linux-arm64-gnu": "3.1.0",
77
- "@optave/codegraph-linux-arm64-musl": "3.1.0",
78
- "@optave/codegraph-linux-x64-gnu": "3.1.0",
79
- "@optave/codegraph-linux-x64-musl": "3.1.0",
80
- "@optave/codegraph-win32-x64-msvc": "3.1.0"
74
+ "@optave/codegraph-darwin-arm64": "3.1.1",
75
+ "@optave/codegraph-darwin-x64": "3.1.1",
76
+ "@optave/codegraph-linux-arm64-gnu": "3.1.1",
77
+ "@optave/codegraph-linux-x64-gnu": "3.1.1",
78
+ "@optave/codegraph-linux-x64-musl": "3.1.1",
79
+ "@optave/codegraph-win32-x64-msvc": "3.1.1"
81
80
  },
82
81
  "devDependencies": {
83
82
  "@biomejs/biome": "^2.4.4",
@@ -90,7 +89,7 @@
90
89
  "husky": "^9.1",
91
90
  "tree-sitter-c-sharp": "^0.23.1",
92
91
  "tree-sitter-cli": "^0.26.5",
93
- "tree-sitter-go": "^0.23.4",
92
+ "tree-sitter-go": "^0.25.0",
94
93
  "tree-sitter-java": "^0.23.5",
95
94
  "tree-sitter-javascript": "^0.25.0",
96
95
  "tree-sitter-php": "^0.24.2",
@@ -0,0 +1,201 @@
1
+ /**
2
+ * C# — AST analysis rules.
3
+ */
4
+
5
+ import { makeCfgRules, makeDataflowRules } from '../shared.js';
6
+
7
+ // ─── Complexity ───────────────────────────────────────────────────────────
8
+
9
+ export const complexity = {
10
+ branchNodes: new Set([
11
+ 'if_statement',
12
+ 'else_clause',
13
+ 'for_statement',
14
+ 'foreach_statement',
15
+ 'while_statement',
16
+ 'do_statement',
17
+ 'catch_clause',
18
+ 'conditional_expression',
19
+ 'switch_statement',
20
+ ]),
21
+ caseNodes: new Set(['switch_section']),
22
+ logicalOperators: new Set(['&&', '||', '??']),
23
+ logicalNodeType: 'binary_expression',
24
+ optionalChainType: 'conditional_access_expression',
25
+ nestingNodes: new Set([
26
+ 'if_statement',
27
+ 'for_statement',
28
+ 'foreach_statement',
29
+ 'while_statement',
30
+ 'do_statement',
31
+ 'catch_clause',
32
+ 'conditional_expression',
33
+ 'switch_statement',
34
+ ]),
35
+ functionNodes: new Set([
36
+ 'method_declaration',
37
+ 'constructor_declaration',
38
+ 'lambda_expression',
39
+ 'local_function_statement',
40
+ ]),
41
+ ifNodeType: 'if_statement',
42
+ elseNodeType: null,
43
+ elifNodeType: null,
44
+ elseViaAlternative: true,
45
+ switchLikeNodes: new Set(['switch_statement']),
46
+ };
47
+
48
+ // ─── Halstead ─────────────────────────────────────────────────────────────
49
+
50
+ export const halstead = {
51
+ operatorLeafTypes: new Set([
52
+ '+',
53
+ '-',
54
+ '*',
55
+ '/',
56
+ '%',
57
+ '=',
58
+ '+=',
59
+ '-=',
60
+ '*=',
61
+ '/=',
62
+ '%=',
63
+ '&=',
64
+ '|=',
65
+ '^=',
66
+ '<<=',
67
+ '>>=',
68
+ '==',
69
+ '!=',
70
+ '<',
71
+ '>',
72
+ '<=',
73
+ '>=',
74
+ '&&',
75
+ '||',
76
+ '!',
77
+ '??',
78
+ '??=',
79
+ '&',
80
+ '|',
81
+ '^',
82
+ '~',
83
+ '<<',
84
+ '>>',
85
+ '++',
86
+ '--',
87
+ 'is',
88
+ 'as',
89
+ 'new',
90
+ 'typeof',
91
+ 'sizeof',
92
+ 'nameof',
93
+ 'if',
94
+ 'else',
95
+ 'for',
96
+ 'foreach',
97
+ 'while',
98
+ 'do',
99
+ 'switch',
100
+ 'case',
101
+ 'return',
102
+ 'throw',
103
+ 'break',
104
+ 'continue',
105
+ 'try',
106
+ 'catch',
107
+ 'finally',
108
+ 'await',
109
+ 'yield',
110
+ '.',
111
+ '?.',
112
+ ',',
113
+ ';',
114
+ ':',
115
+ '=>',
116
+ '->',
117
+ ]),
118
+ operandLeafTypes: new Set([
119
+ 'identifier',
120
+ 'integer_literal',
121
+ 'real_literal',
122
+ 'string_literal',
123
+ 'character_literal',
124
+ 'verbatim_string_literal',
125
+ 'interpolated_string_text',
126
+ 'true',
127
+ 'false',
128
+ 'null',
129
+ 'this',
130
+ 'base',
131
+ ]),
132
+ compoundOperators: new Set([
133
+ 'invocation_expression',
134
+ 'element_access_expression',
135
+ 'object_creation_expression',
136
+ ]),
137
+ skipTypes: new Set(['type_argument_list', 'type_parameter_list']),
138
+ };
139
+
140
+ // ─── CFG ──────────────────────────────────────────────────────────────────
141
+
142
+ export const cfg = makeCfgRules({
143
+ ifNode: 'if_statement',
144
+ elseViaAlternative: true,
145
+ forNodes: new Set(['for_statement', 'foreach_statement']),
146
+ whileNode: 'while_statement',
147
+ doNode: 'do_statement',
148
+ switchNode: 'switch_statement',
149
+ caseNode: 'switch_section',
150
+ tryNode: 'try_statement',
151
+ catchNode: 'catch_clause',
152
+ finallyNode: 'finally_clause',
153
+ returnNode: 'return_statement',
154
+ throwNode: 'throw_statement',
155
+ breakNode: 'break_statement',
156
+ continueNode: 'continue_statement',
157
+ blockNode: 'block',
158
+ labeledNode: 'labeled_statement',
159
+ functionNodes: new Set([
160
+ 'method_declaration',
161
+ 'constructor_declaration',
162
+ 'lambda_expression',
163
+ 'local_function_statement',
164
+ ]),
165
+ });
166
+
167
+ // ─── Dataflow ─────────────────────────────────────────────────────────────
168
+
169
+ export const dataflow = makeDataflowRules({
170
+ functionNodes: new Set([
171
+ 'method_declaration',
172
+ 'constructor_declaration',
173
+ 'lambda_expression',
174
+ 'local_function_statement',
175
+ ]),
176
+ returnNode: 'return_statement',
177
+ varDeclaratorNode: 'variable_declarator',
178
+ varNameField: 'name',
179
+ assignmentNode: 'assignment_expression',
180
+ callNode: 'invocation_expression',
181
+ callFunctionField: 'function',
182
+ callArgsField: 'arguments',
183
+ memberNode: 'member_access_expression',
184
+ memberObjectField: 'expression',
185
+ memberPropertyField: 'name',
186
+ awaitNode: 'await_expression',
187
+ argumentWrapperType: 'argument',
188
+ mutatingMethods: new Set(['Add', 'Remove', 'Clear', 'Insert', 'Sort', 'Reverse', 'Push', 'Pop']),
189
+ extractParamName(node) {
190
+ if (node.type === 'parameter') {
191
+ const nameNode = node.childForFieldName('name');
192
+ return nameNode ? [nameNode.text] : null;
193
+ }
194
+ if (node.type === 'identifier') return [node.text];
195
+ return null;
196
+ },
197
+ });
198
+
199
+ // ─── AST Node Types ───────────────────────────────────────────────────────
200
+
201
+ export const astTypes = null;
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Go — AST analysis rules.
3
+ */
4
+
5
+ import { makeCfgRules, makeDataflowRules } from '../shared.js';
6
+
7
+ // ─── Complexity ───────────────────────────────────────────────────────────
8
+
9
+ export const complexity = {
10
+ branchNodes: new Set([
11
+ 'if_statement',
12
+ 'for_statement',
13
+ 'expression_switch_statement',
14
+ 'type_switch_statement',
15
+ 'select_statement',
16
+ ]),
17
+ caseNodes: new Set(['expression_case', 'type_case', 'default_case', 'communication_case']),
18
+ logicalOperators: new Set(['&&', '||']),
19
+ logicalNodeType: 'binary_expression',
20
+ optionalChainType: null,
21
+ nestingNodes: new Set([
22
+ 'if_statement',
23
+ 'for_statement',
24
+ 'expression_switch_statement',
25
+ 'type_switch_statement',
26
+ 'select_statement',
27
+ ]),
28
+ functionNodes: new Set(['function_declaration', 'method_declaration', 'func_literal']),
29
+ ifNodeType: 'if_statement',
30
+ elseNodeType: null,
31
+ elifNodeType: null,
32
+ elseViaAlternative: true,
33
+ switchLikeNodes: new Set(['expression_switch_statement', 'type_switch_statement']),
34
+ };
35
+
36
+ // ─── Halstead ─────────────────────────────────────────────────────────────
37
+
38
+ export const halstead = {
39
+ operatorLeafTypes: new Set([
40
+ '+',
41
+ '-',
42
+ '*',
43
+ '/',
44
+ '%',
45
+ '=',
46
+ ':=',
47
+ '+=',
48
+ '-=',
49
+ '*=',
50
+ '/=',
51
+ '%=',
52
+ '&=',
53
+ '|=',
54
+ '^=',
55
+ '<<=',
56
+ '>>=',
57
+ '==',
58
+ '!=',
59
+ '<',
60
+ '>',
61
+ '<=',
62
+ '>=',
63
+ '&&',
64
+ '||',
65
+ '!',
66
+ '&',
67
+ '|',
68
+ '^',
69
+ '~',
70
+ '<<',
71
+ '>>',
72
+ '&^',
73
+ '++',
74
+ '--',
75
+ 'if',
76
+ 'else',
77
+ 'for',
78
+ 'switch',
79
+ 'select',
80
+ 'case',
81
+ 'default',
82
+ 'return',
83
+ 'break',
84
+ 'continue',
85
+ 'goto',
86
+ 'fallthrough',
87
+ 'go',
88
+ 'defer',
89
+ 'range',
90
+ 'chan',
91
+ 'func',
92
+ 'var',
93
+ 'const',
94
+ 'type',
95
+ 'struct',
96
+ 'interface',
97
+ '.',
98
+ ',',
99
+ ';',
100
+ ':',
101
+ '<-',
102
+ ]),
103
+ operandLeafTypes: new Set([
104
+ 'identifier',
105
+ 'field_identifier',
106
+ 'package_identifier',
107
+ 'type_identifier',
108
+ 'int_literal',
109
+ 'float_literal',
110
+ 'imaginary_literal',
111
+ 'rune_literal',
112
+ 'interpreted_string_literal',
113
+ 'raw_string_literal',
114
+ 'true',
115
+ 'false',
116
+ 'nil',
117
+ 'iota',
118
+ ]),
119
+ compoundOperators: new Set(['call_expression', 'index_expression', 'selector_expression']),
120
+ skipTypes: new Set([]),
121
+ };
122
+
123
+ // ─── CFG ──────────────────────────────────────────────────────────────────
124
+
125
+ export const cfg = makeCfgRules({
126
+ ifNode: 'if_statement',
127
+ elseViaAlternative: true,
128
+ forNodes: new Set(['for_statement']),
129
+ switchNodes: new Set([
130
+ 'expression_switch_statement',
131
+ 'type_switch_statement',
132
+ 'select_statement',
133
+ ]),
134
+ caseNode: 'expression_case',
135
+ caseNodes: new Set(['type_case', 'communication_case']),
136
+ defaultNode: 'default_case',
137
+ returnNode: 'return_statement',
138
+ breakNode: 'break_statement',
139
+ continueNode: 'continue_statement',
140
+ blockNode: 'block',
141
+ labeledNode: 'labeled_statement',
142
+ functionNodes: new Set(['function_declaration', 'method_declaration', 'func_literal']),
143
+ });
144
+
145
+ // ─── Dataflow ─────────────────────────────────────────────────────────────
146
+
147
+ export const dataflow = makeDataflowRules({
148
+ functionNodes: new Set(['function_declaration', 'method_declaration', 'func_literal']),
149
+ returnNode: 'return_statement',
150
+ varDeclaratorNodes: new Set(['short_var_declaration', 'var_declaration']),
151
+ varNameField: 'left',
152
+ varValueField: 'right',
153
+ assignmentNode: 'assignment_statement',
154
+ assignLeftField: 'left',
155
+ assignRightField: 'right',
156
+ callNode: 'call_expression',
157
+ callFunctionField: 'function',
158
+ callArgsField: 'arguments',
159
+ memberNode: 'selector_expression',
160
+ memberObjectField: 'operand',
161
+ memberPropertyField: 'field',
162
+ mutatingMethods: new Set(),
163
+ expressionListType: 'expression_list',
164
+ extractParamName(node) {
165
+ if (node.type === 'parameter_declaration') {
166
+ const names = [];
167
+ for (const c of node.namedChildren) {
168
+ if (c.type === 'identifier') names.push(c.text);
169
+ }
170
+ return names.length > 0 ? names : null;
171
+ }
172
+ if (node.type === 'variadic_parameter_declaration') {
173
+ const nameNode = node.childForFieldName('name');
174
+ return nameNode ? [nameNode.text] : null;
175
+ }
176
+ return null;
177
+ },
178
+ });
179
+
180
+ // ─── AST Node Types ───────────────────────────────────────────────────────
181
+
182
+ export const astTypes = null;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Assembled rule maps for all AST analysis modules.
3
+ *
4
+ * Re-exports per-language rules as Maps keyed by language ID.
5
+ */
6
+
7
+ import * as csharp from './csharp.js';
8
+ import * as go from './go.js';
9
+ import * as java from './java.js';
10
+ import * as javascript from './javascript.js';
11
+ import * as php from './php.js';
12
+ import * as python from './python.js';
13
+ import * as ruby from './ruby.js';
14
+ import * as rust from './rust.js';
15
+
16
+ // ─── Complexity Rules ─────────────────────────────────────────────────────
17
+
18
+ export const COMPLEXITY_RULES = new Map([
19
+ ['javascript', javascript.complexity],
20
+ ['typescript', javascript.complexity],
21
+ ['tsx', javascript.complexity],
22
+ ['python', python.complexity],
23
+ ['go', go.complexity],
24
+ ['rust', rust.complexity],
25
+ ['java', java.complexity],
26
+ ['csharp', csharp.complexity],
27
+ ['ruby', ruby.complexity],
28
+ ['php', php.complexity],
29
+ ]);
30
+
31
+ // ─── Halstead Rules ───────────────────────────────────────────────────────
32
+
33
+ export const HALSTEAD_RULES = new Map([
34
+ ['javascript', javascript.halstead],
35
+ ['typescript', javascript.halstead],
36
+ ['tsx', javascript.halstead],
37
+ ['python', python.halstead],
38
+ ['go', go.halstead],
39
+ ['rust', rust.halstead],
40
+ ['java', java.halstead],
41
+ ['csharp', csharp.halstead],
42
+ ['ruby', ruby.halstead],
43
+ ['php', php.halstead],
44
+ ]);
45
+
46
+ // ─── CFG Rules ────────────────────────────────────────────────────────────
47
+
48
+ export const CFG_RULES = new Map([
49
+ ['javascript', javascript.cfg],
50
+ ['typescript', javascript.cfg],
51
+ ['tsx', javascript.cfg],
52
+ ['python', python.cfg],
53
+ ['go', go.cfg],
54
+ ['rust', rust.cfg],
55
+ ['java', java.cfg],
56
+ ['csharp', csharp.cfg],
57
+ ['ruby', ruby.cfg],
58
+ ['php', php.cfg],
59
+ ]);
60
+
61
+ // ─── Dataflow Rules ──────────────────────────────────────────────────────
62
+
63
+ export const DATAFLOW_RULES = new Map([
64
+ ['javascript', javascript.dataflow],
65
+ ['typescript', javascript.dataflow],
66
+ ['tsx', javascript.dataflow],
67
+ ['python', python.dataflow],
68
+ ['go', go.dataflow],
69
+ ['rust', rust.dataflow],
70
+ ['java', java.dataflow],
71
+ ['csharp', csharp.dataflow],
72
+ ['php', php.dataflow],
73
+ ['ruby', ruby.dataflow],
74
+ ]);
75
+
76
+ // ─── AST Type Maps ───────────────────────────────────────────────────────
77
+
78
+ export const AST_TYPE_MAPS = new Map([
79
+ ['javascript', javascript.astTypes],
80
+ ['typescript', javascript.astTypes],
81
+ ['tsx', javascript.astTypes],
82
+ ]);
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Java — AST analysis rules.
3
+ */
4
+
5
+ import { makeCfgRules, makeDataflowRules } from '../shared.js';
6
+
7
+ // ─── Complexity ───────────────────────────────────────────────────────────
8
+
9
+ export const complexity = {
10
+ branchNodes: new Set([
11
+ 'if_statement',
12
+ 'for_statement',
13
+ 'enhanced_for_statement',
14
+ 'while_statement',
15
+ 'do_statement',
16
+ 'catch_clause',
17
+ 'ternary_expression',
18
+ 'switch_expression',
19
+ ]),
20
+ caseNodes: new Set(['switch_label']),
21
+ logicalOperators: new Set(['&&', '||']),
22
+ logicalNodeType: 'binary_expression',
23
+ optionalChainType: null,
24
+ nestingNodes: new Set([
25
+ 'if_statement',
26
+ 'for_statement',
27
+ 'enhanced_for_statement',
28
+ 'while_statement',
29
+ 'do_statement',
30
+ 'catch_clause',
31
+ 'ternary_expression',
32
+ ]),
33
+ functionNodes: new Set(['method_declaration', 'constructor_declaration', 'lambda_expression']),
34
+ ifNodeType: 'if_statement',
35
+ elseNodeType: null,
36
+ elifNodeType: null,
37
+ elseViaAlternative: true,
38
+ switchLikeNodes: new Set(['switch_expression']),
39
+ };
40
+
41
+ // ─── Halstead ─────────────────────────────────────────────────────────────
42
+
43
+ export const halstead = {
44
+ operatorLeafTypes: new Set([
45
+ '+',
46
+ '-',
47
+ '*',
48
+ '/',
49
+ '%',
50
+ '=',
51
+ '+=',
52
+ '-=',
53
+ '*=',
54
+ '/=',
55
+ '%=',
56
+ '&=',
57
+ '|=',
58
+ '^=',
59
+ '<<=',
60
+ '>>=',
61
+ '>>>=',
62
+ '==',
63
+ '!=',
64
+ '<',
65
+ '>',
66
+ '<=',
67
+ '>=',
68
+ '&&',
69
+ '||',
70
+ '!',
71
+ '&',
72
+ '|',
73
+ '^',
74
+ '~',
75
+ '<<',
76
+ '>>',
77
+ '>>>',
78
+ '++',
79
+ '--',
80
+ 'instanceof',
81
+ 'new',
82
+ 'if',
83
+ 'else',
84
+ 'for',
85
+ 'while',
86
+ 'do',
87
+ 'switch',
88
+ 'case',
89
+ 'return',
90
+ 'throw',
91
+ 'break',
92
+ 'continue',
93
+ 'try',
94
+ 'catch',
95
+ 'finally',
96
+ '.',
97
+ ',',
98
+ ';',
99
+ ':',
100
+ '?',
101
+ '->',
102
+ ]),
103
+ operandLeafTypes: new Set([
104
+ 'identifier',
105
+ 'type_identifier',
106
+ 'decimal_integer_literal',
107
+ 'hex_integer_literal',
108
+ 'octal_integer_literal',
109
+ 'binary_integer_literal',
110
+ 'decimal_floating_point_literal',
111
+ 'hex_floating_point_literal',
112
+ 'string_literal',
113
+ 'character_literal',
114
+ 'true',
115
+ 'false',
116
+ 'null',
117
+ 'this',
118
+ 'super',
119
+ ]),
120
+ compoundOperators: new Set(['method_invocation', 'array_access', 'object_creation_expression']),
121
+ skipTypes: new Set(['type_arguments', 'type_parameters']),
122
+ };
123
+
124
+ // ─── CFG ──────────────────────────────────────────────────────────────────
125
+
126
+ export const cfg = makeCfgRules({
127
+ ifNode: 'if_statement',
128
+ elseViaAlternative: true,
129
+ forNodes: new Set(['for_statement', 'enhanced_for_statement']),
130
+ whileNode: 'while_statement',
131
+ doNode: 'do_statement',
132
+ switchNode: 'switch_expression',
133
+ caseNode: 'switch_block_statement_group',
134
+ caseNodes: new Set(['switch_rule']),
135
+ tryNode: 'try_statement',
136
+ catchNode: 'catch_clause',
137
+ finallyNode: 'finally_clause',
138
+ returnNode: 'return_statement',
139
+ throwNode: 'throw_statement',
140
+ breakNode: 'break_statement',
141
+ continueNode: 'continue_statement',
142
+ blockNode: 'block',
143
+ labeledNode: 'labeled_statement',
144
+ functionNodes: new Set(['method_declaration', 'constructor_declaration', 'lambda_expression']),
145
+ });
146
+
147
+ // ─── Dataflow ─────────────────────────────────────────────────────────────
148
+
149
+ export const dataflow = makeDataflowRules({
150
+ functionNodes: new Set(['method_declaration', 'constructor_declaration', 'lambda_expression']),
151
+ returnNode: 'return_statement',
152
+ varDeclaratorNode: 'variable_declarator',
153
+ assignmentNode: 'assignment_expression',
154
+ callNodes: new Set(['method_invocation', 'object_creation_expression']),
155
+ callFunctionField: 'name',
156
+ callArgsField: 'arguments',
157
+ memberNode: 'field_access',
158
+ memberObjectField: 'object',
159
+ memberPropertyField: 'field',
160
+ callObjectField: 'object',
161
+ argumentWrapperType: 'argument',
162
+ mutatingMethods: new Set(['add', 'remove', 'clear', 'put', 'set', 'push', 'pop', 'sort']),
163
+ extractParamName(node) {
164
+ if (node.type === 'formal_parameter' || node.type === 'spread_parameter') {
165
+ const nameNode = node.childForFieldName('name');
166
+ return nameNode ? [nameNode.text] : null;
167
+ }
168
+ if (node.type === 'identifier') return [node.text];
169
+ return null;
170
+ },
171
+ });
172
+
173
+ // ─── AST Node Types ───────────────────────────────────────────────────────
174
+
175
+ export const astTypes = null;