Skip to content

Commit 93fde99

Browse files
authored
fix: rescue orphaned commits from release/3.1.0 (#379)
* fix(ci): refresh node_modules before generating DEPENDENCIES.json After publishing platform packages, node_modules still has the old version binaries. npm ls sees the mismatch and embeds an ELSPROBLEMS error into the JSON output. Add npm install --ignore-scripts after publish to pull the freshly published versions. * refactor: extract AST analysis rules into per-language files (#372) * refactor: extract AST analysis rules into per-language files Move language-specific rules (complexity, Halstead, CFG, dataflow, AST node types) from four monolithic modules into `src/ast-analysis/rules/` with one file per language and a shared utility module. - Create `src/ast-analysis/shared.js` with `makeRules()`, `makeCfgRules()`, `makeDataflowRules()`, `findFunctionNode()`, `truncate()`, `buildExtToLangMap()`, `buildExtensionSet()` - Create 8 per-language rule files under `src/ast-analysis/rules/` - Create `src/ast-analysis/rules/index.js` assembling all rule Maps - Update complexity.js, cfg.js, dataflow.js, ast.js to import from the new location with backward-compatible re-exports Zero behavior changes — all 1,457 tests pass unchanged. Impact: 16 functions changed, 29 affected * fix: replace removed CFG_LANG_IDS reference with CFG_RULES in WASM fallback Impact: 1 functions changed, 0 affected Impact: 16 functions changed, 39 affected * fix: remove unused LANGUAGE_REGISTRY imports, use buildExtToLangMap Remove unused LANGUAGE_REGISTRY import from ast.js (would fail lint). Replace inline extToLang map loops in cfg.js, complexity.js, and dataflow.js with the shared buildExtToLangMap() utility, eliminating dead-code export. Impact: 3 functions changed, 13 affected * refactor: remove DATAFLOW_LANG_IDS, use DATAFLOW_RULES.has() directly Impact: 1 functions changed, 14 affected
1 parent ecfca90 commit 93fde99

15 files changed

Lines changed: 1950 additions & 1755 deletions

File tree

.github/workflows/publish.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ jobs:
491491
git config user.name "github-actions[bot]"
492492
git config user.email "github-actions[bot]@users.noreply.github.com"
493493
494+
- name: Refresh node_modules after publish
495+
run: npm install --ignore-scripts
496+
494497
- name: Generate DEPENDENCIES.json
495498
run: mkdir -p generated && npm ls --json --all --omit=dev > generated/DEPENDENCIES.json 2>/dev/null || true
496499

src/ast-analysis/rules/csharp.js

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

src/ast-analysis/rules/go.js

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 commit comments

Comments
 (0)