@kernlang/review 3.1.5 → 3.1.7
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.
- package/LICENSE +17 -0
- package/dist/cache.d.ts +1 -1
- package/dist/cache.js +5 -3
- package/dist/cache.js.map +1 -1
- package/dist/call-graph.d.ts +63 -0
- package/dist/call-graph.js +380 -0
- package/dist/call-graph.js.map +1 -0
- package/dist/concept-rules/boundary-mutation.d.ts +1 -1
- package/dist/concept-rules/boundary-mutation.js.map +1 -1
- package/dist/concept-rules/ignored-error.d.ts +1 -1
- package/dist/concept-rules/ignored-error.js.map +1 -1
- package/dist/concept-rules/illegal-dependency.d.ts +1 -1
- package/dist/concept-rules/illegal-dependency.js.map +1 -1
- package/dist/concept-rules/index.js +1 -6
- package/dist/concept-rules/index.js.map +1 -1
- package/dist/concept-rules/unguarded-effect.d.ts +1 -1
- package/dist/concept-rules/unguarded-effect.js.map +1 -1
- package/dist/concept-rules/unrecovered-effect.d.ts +1 -1
- package/dist/concept-rules/unrecovered-effect.js +2 -1
- package/dist/concept-rules/unrecovered-effect.js.map +1 -1
- package/dist/confidence.js +12 -8
- package/dist/confidence.js.map +1 -1
- package/dist/differ.js +3 -7
- package/dist/differ.js.map +1 -1
- package/dist/external-tools.js +5 -6
- package/dist/external-tools.js.map +1 -1
- package/dist/file-context.d.ts +21 -0
- package/dist/file-context.js +234 -0
- package/dist/file-context.js.map +1 -0
- package/dist/file-role.js +14 -7
- package/dist/file-role.js.map +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/graph.js +24 -16
- package/dist/graph.js.map +1 -1
- package/dist/index.d.ts +44 -35
- package/dist/index.js +221 -68
- package/dist/index.js.map +1 -1
- package/dist/inferrer.d.ts +8 -2
- package/dist/inferrer.js +80 -47
- package/dist/inferrer.js.map +1 -1
- package/dist/kern-lint.d.ts +3 -4
- package/dist/kern-lint.js +7 -5
- package/dist/kern-lint.js.map +1 -1
- package/dist/llm-bridge.d.ts +23 -7
- package/dist/llm-bridge.js +267 -31
- package/dist/llm-bridge.js.map +1 -1
- package/dist/llm-review.d.ts +16 -2
- package/dist/llm-review.js +240 -35
- package/dist/llm-review.js.map +1 -1
- package/dist/mappers/ts-concepts.d.ts +1 -1
- package/dist/mappers/ts-concepts.js +303 -32
- package/dist/mappers/ts-concepts.js.map +1 -1
- package/dist/norm-miner.d.ts +31 -0
- package/dist/norm-miner.js +119 -0
- package/dist/norm-miner.js.map +1 -0
- package/dist/obligations.d.ts +63 -0
- package/dist/obligations.js +158 -0
- package/dist/obligations.js.map +1 -0
- package/dist/quality-rules.d.ts +3 -3
- package/dist/quality-rules.js +4 -2
- package/dist/quality-rules.js.map +1 -1
- package/dist/reporter.d.ts +7 -2
- package/dist/reporter.js +82 -51
- package/dist/reporter.js.map +1 -1
- package/dist/rule-eval.d.ts +1 -2
- package/dist/rule-eval.js +5 -9
- package/dist/rule-eval.js.map +1 -1
- package/dist/rule-loader.js +16 -14
- package/dist/rule-loader.js.map +1 -1
- package/dist/rules/base.js +153 -69
- package/dist/rules/base.js.map +1 -1
- package/dist/rules/cli.d.ts +7 -0
- package/dist/rules/cli.js +99 -0
- package/dist/rules/cli.js.map +1 -0
- package/dist/rules/confidence.d.ts +1 -1
- package/dist/rules/confidence.js +5 -5
- package/dist/rules/confidence.js.map +1 -1
- package/dist/rules/dead-code.d.ts +10 -0
- package/dist/rules/dead-code.js +75 -0
- package/dist/rules/dead-code.js.map +1 -0
- package/dist/rules/dead-logic.js +35 -31
- package/dist/rules/dead-logic.js.map +1 -1
- package/dist/rules/express.d.ts +2 -1
- package/dist/rules/express.js +380 -126
- package/dist/rules/express.js.map +1 -1
- package/dist/rules/fastapi.d.ts +10 -0
- package/dist/rules/fastapi.js +183 -0
- package/dist/rules/fastapi.js.map +1 -0
- package/dist/rules/ground-layer.js +3 -3
- package/dist/rules/ground-layer.js.map +1 -1
- package/dist/rules/index.d.ts +5 -1
- package/dist/rules/index.js +602 -84
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/ink.d.ts +8 -0
- package/dist/rules/ink.js +88 -0
- package/dist/rules/ink.js.map +1 -0
- package/dist/rules/kern-source.js +202 -63
- package/dist/rules/kern-source.js.map +1 -1
- package/dist/rules/nextjs.js +88 -33
- package/dist/rules/nextjs.js.map +1 -1
- package/dist/rules/null-safety.js +52 -26
- package/dist/rules/null-safety.js.map +1 -1
- package/dist/rules/nuxt.js +24 -29
- package/dist/rules/nuxt.js.map +1 -1
- package/dist/rules/react.js +355 -69
- package/dist/rules/react.js.map +1 -1
- package/dist/rules/security-v2.js +71 -57
- package/dist/rules/security-v2.js.map +1 -1
- package/dist/rules/security-v3.js.map +1 -1
- package/dist/rules/security-v4.js +54 -27
- package/dist/rules/security-v4.js.map +1 -1
- package/dist/rules/security.js +35 -5
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/terminal.d.ts +8 -0
- package/dist/rules/terminal.js +139 -0
- package/dist/rules/terminal.js.map +1 -0
- package/dist/rules/vue.js +162 -107
- package/dist/rules/vue.js.map +1 -1
- package/dist/semantic-diff.d.ts +52 -0
- package/dist/semantic-diff.js +342 -0
- package/dist/semantic-diff.js.map +1 -0
- package/dist/spec-checker.js +11 -10
- package/dist/spec-checker.js.map +1 -1
- package/dist/suppression/apply-suppression.d.ts +2 -3
- package/dist/suppression/apply-suppression.js +3 -3
- package/dist/suppression/apply-suppression.js.map +1 -1
- package/dist/suppression/index.d.ts +2 -2
- package/dist/suppression/index.js +1 -1
- package/dist/suppression/index.js.map +1 -1
- package/dist/suppression/parse-directives.d.ts +1 -1
- package/dist/suppression/parse-directives.js +9 -4
- package/dist/suppression/parse-directives.js.map +1 -1
- package/dist/taint-ast.d.ts +20 -0
- package/dist/taint-ast.js +427 -0
- package/dist/taint-ast.js.map +1 -0
- package/dist/taint-crossfile.d.ts +28 -0
- package/dist/taint-crossfile.js +174 -0
- package/dist/taint-crossfile.js.map +1 -0
- package/dist/taint-findings.d.ts +17 -0
- package/dist/taint-findings.js +131 -0
- package/dist/taint-findings.js.map +1 -0
- package/dist/taint-regex.d.ts +61 -0
- package/dist/taint-regex.js +379 -0
- package/dist/taint-regex.js.map +1 -0
- package/dist/taint-types.d.ts +128 -0
- package/dist/taint-types.js +174 -0
- package/dist/taint-types.js.map +1 -0
- package/dist/taint.d.ts +13 -107
- package/dist/taint.js +16 -1067
- package/dist/taint.js.map +1 -1
- package/dist/template-detector.d.ts +2 -2
- package/dist/template-detector.js +11 -16
- package/dist/template-detector.js.map +1 -1
- package/dist/types.d.ts +35 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
package/dist/rules/vue.js
CHANGED
|
@@ -3,38 +3,18 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Catches Vue 3 Composition API pitfalls.
|
|
5
5
|
*/
|
|
6
|
-
import { SyntaxKind } from 'ts-morph';
|
|
7
|
-
import {
|
|
8
|
-
function span(file, line, col = 1) {
|
|
9
|
-
return { file, startLine: line, startCol: col, endLine: line, endCol: col };
|
|
10
|
-
}
|
|
11
|
-
function finding(ruleId, severity, category, message, file, line, extra) {
|
|
12
|
-
return {
|
|
13
|
-
source: 'kern',
|
|
14
|
-
ruleId,
|
|
15
|
-
severity,
|
|
16
|
-
category,
|
|
17
|
-
message,
|
|
18
|
-
primarySpan: span(file, line),
|
|
19
|
-
fingerprint: createFingerprint(ruleId, line, 1),
|
|
20
|
-
...extra,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
6
|
+
import { Node, SyntaxKind } from 'ts-morph';
|
|
7
|
+
import { finding } from './utils.js';
|
|
23
8
|
// ── Rule 17: missing-ref-value ───────────────────────────────────────────
|
|
24
9
|
// Using ref() result without .value in script setup
|
|
25
10
|
function missingRefValue(ctx) {
|
|
26
11
|
const findings = [];
|
|
27
|
-
|
|
28
|
-
const refVarNames = new Map(); // name → declaration line
|
|
12
|
+
const refVarNames = new Map();
|
|
29
13
|
for (const stmt of ctx.sourceFile.getVariableStatements()) {
|
|
30
14
|
for (const decl of stmt.getDeclarations()) {
|
|
31
15
|
const init = decl.getInitializer();
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
// Match ref() or ref<T>() calls
|
|
35
|
-
if (init.getKind() === SyntaxKind.CallExpression) {
|
|
36
|
-
const call = init;
|
|
37
|
-
const calleeName = call.getExpression().getText();
|
|
16
|
+
if (init && Node.isCallExpression(init)) {
|
|
17
|
+
const calleeName = init.getExpression().getText();
|
|
38
18
|
if (calleeName === 'ref') {
|
|
39
19
|
refVarNames.set(decl.getName(), stmt.getStartLineNumber());
|
|
40
20
|
}
|
|
@@ -43,134 +23,111 @@ function missingRefValue(ctx) {
|
|
|
43
23
|
}
|
|
44
24
|
if (refVarNames.size === 0)
|
|
45
25
|
return findings;
|
|
46
|
-
// Walk all identifiers and check if ref vars are used without .value
|
|
47
26
|
for (const ident of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)) {
|
|
48
27
|
const name = ident.getText();
|
|
49
28
|
if (!refVarNames.has(name))
|
|
50
29
|
continue;
|
|
51
|
-
// Skip the declaration itself
|
|
52
30
|
if (ident.getStartLineNumber() === refVarNames.get(name))
|
|
53
31
|
continue;
|
|
54
32
|
const parent = ident.getParent();
|
|
55
33
|
if (!parent)
|
|
56
34
|
continue;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (propAccess.getExpression() === ident) {
|
|
61
|
-
if (propAccess.getName() === 'value')
|
|
62
|
-
continue; // correct: ref.value
|
|
63
|
-
// Accessing some other property on ref without .value — still a bug
|
|
64
|
-
}
|
|
35
|
+
if (Node.isPropertyAccessExpression(parent)) {
|
|
36
|
+
if (parent.getExpression() === ident && parent.getName() === 'value')
|
|
37
|
+
continue;
|
|
65
38
|
}
|
|
66
|
-
|
|
67
|
-
if (parent.getKind() === SyntaxKind.CallExpression)
|
|
39
|
+
if (Node.isCallExpression(parent))
|
|
68
40
|
continue;
|
|
69
|
-
// Also skip if it's an argument in a call's argument list
|
|
70
41
|
const grandparent = parent.getParent();
|
|
71
|
-
if (grandparent
|
|
72
|
-
continue;
|
|
73
|
-
// Skip type contexts
|
|
74
|
-
if (parent.getKind() === SyntaxKind.TypeReference)
|
|
75
|
-
continue;
|
|
76
|
-
if (parent.getKind() === SyntaxKind.TypeQuery)
|
|
42
|
+
if (grandparent && Node.isCallExpression(grandparent))
|
|
77
43
|
continue;
|
|
78
|
-
|
|
79
|
-
if (parent.getKind() === SyntaxKind.ShorthandPropertyAssignment)
|
|
44
|
+
if (Node.isTypeReference(parent) || Node.isTypeQuery(parent))
|
|
80
45
|
continue;
|
|
81
|
-
|
|
82
|
-
if (parent.getKind() === SyntaxKind.ImportSpecifier)
|
|
46
|
+
if (Node.isShorthandPropertyAssignment(parent))
|
|
83
47
|
continue;
|
|
84
|
-
if (
|
|
48
|
+
if (Node.isImportSpecifier(parent) || Node.isVariableDeclaration(parent))
|
|
85
49
|
continue;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
findings.push(finding('missing-ref-value', 'warning', 'bug', `'${name}' is a ref — did you mean '${name}.value'?`, ctx.filePath, ident.getStartLineNumber(), { suggestion: `${name}.value` }));
|
|
93
|
-
// One finding per ref variable to avoid noise
|
|
50
|
+
if (Node.isBinaryExpression(parent) ||
|
|
51
|
+
Node.isConditionalExpression(parent) ||
|
|
52
|
+
Node.isTemplateSpan(parent) ||
|
|
53
|
+
Node.isReturnStatement(parent) ||
|
|
54
|
+
Node.isElementAccessExpression(parent)) {
|
|
55
|
+
findings.push(finding('missing-ref-value', 'warning', 'bug', `'${name}' is a ref — did you mean '${name}.value'?`, ctx.filePath, ident.getStartLineNumber(), 1, { suggestion: `${name}.value` }));
|
|
94
56
|
refVarNames.delete(name);
|
|
95
57
|
}
|
|
96
58
|
}
|
|
97
59
|
return findings;
|
|
98
60
|
}
|
|
99
61
|
// ── Rule 18: missing-onUnmounted ─────────────────────────────────────────
|
|
100
|
-
// watch/addEventListener without cleanup in onUnmounted
|
|
62
|
+
// watch/watchEffect/addEventListener without cleanup in onUnmounted
|
|
63
|
+
const WATCH_FUNCTIONS = new Set(['watch', 'watchEffect', 'watchSyncEffect', 'watchPostEffect']);
|
|
101
64
|
function missingOnUnmounted(ctx) {
|
|
102
65
|
const findings = [];
|
|
103
|
-
// AST pre-check: find onUnmounted/onBeforeUnmount CallExpressions
|
|
104
66
|
let hasLifecycleCleanup = false;
|
|
105
67
|
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
106
|
-
const callee = call.getExpression();
|
|
107
|
-
if (callee
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
hasLifecycleCleanup = true;
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
68
|
+
const callee = call.getExpression().getText();
|
|
69
|
+
if (callee === 'onUnmounted' || callee === 'onBeforeUnmount') {
|
|
70
|
+
hasLifecycleCleanup = true;
|
|
71
|
+
break;
|
|
113
72
|
}
|
|
114
73
|
}
|
|
115
|
-
// Check for watch() calls via AST
|
|
116
74
|
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
117
|
-
const callee = call.getExpression();
|
|
118
|
-
if (
|
|
75
|
+
const callee = call.getExpression().getText();
|
|
76
|
+
if (!WATCH_FUNCTIONS.has(callee))
|
|
119
77
|
continue;
|
|
120
|
-
// Check if parent is VariableDeclaration (stop handle assigned)
|
|
121
78
|
const parent = call.getParent();
|
|
122
|
-
const hasStopHandle = parent
|
|
79
|
+
const hasStopHandle = Node.isVariableDeclaration(parent);
|
|
123
80
|
if (!hasStopHandle && !hasLifecycleCleanup) {
|
|
124
|
-
findings.push(finding('missing-onUnmounted', 'error', 'bug',
|
|
81
|
+
findings.push(finding('missing-onUnmounted', 'error', 'bug', `${callee}() without stop handle or onUnmounted cleanup — potential memory leak`, ctx.filePath, call.getStartLineNumber(), 1, { suggestion: `Assign ${callee} to a variable and call stop() in onUnmounted` }));
|
|
125
82
|
}
|
|
126
83
|
}
|
|
127
|
-
// Check for addEventListener via AST
|
|
128
84
|
let hasRemoveListener = false;
|
|
129
85
|
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
130
86
|
const callee = call.getExpression();
|
|
131
|
-
if (callee.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
hasRemoveListener = true;
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
87
|
+
if (Node.isPropertyAccessExpression(callee) && callee.getName() === 'removeEventListener') {
|
|
88
|
+
hasRemoveListener = true;
|
|
89
|
+
break;
|
|
137
90
|
}
|
|
138
91
|
}
|
|
139
92
|
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
140
93
|
const callee = call.getExpression();
|
|
141
|
-
if (callee.
|
|
142
|
-
continue;
|
|
143
|
-
const pa = callee;
|
|
144
|
-
if (pa.getName() !== 'addEventListener')
|
|
94
|
+
if (!Node.isPropertyAccessExpression(callee) || callee.getName() !== 'addEventListener')
|
|
145
95
|
continue;
|
|
146
96
|
if (!hasRemoveListener && !hasLifecycleCleanup) {
|
|
147
|
-
findings.push(finding('missing-onUnmounted', 'error', 'bug', 'addEventListener without removeEventListener in onUnmounted — memory leak', ctx.filePath, call.getStartLineNumber(), { suggestion: 'Clean up event listeners in onUnmounted()' }));
|
|
97
|
+
findings.push(finding('missing-onUnmounted', 'error', 'bug', 'addEventListener without removeEventListener in onUnmounted — memory leak', ctx.filePath, call.getStartLineNumber(), 1, { suggestion: 'Clean up event listeners in onUnmounted()' }));
|
|
148
98
|
}
|
|
149
99
|
}
|
|
150
100
|
return findings;
|
|
151
101
|
}
|
|
152
102
|
// ── Rule 19: setup-side-effect ───────────────────────────────────────────
|
|
153
|
-
//
|
|
103
|
+
// Top-level await in setup without onMounted wrapper (SSR safety)
|
|
154
104
|
function setupSideEffect(ctx) {
|
|
155
105
|
const findings = [];
|
|
156
106
|
const fullText = ctx.sourceFile.getFullText();
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
107
|
+
const isVueFile = ctx.filePath.endsWith('.vue') || fullText.includes('defineComponent');
|
|
108
|
+
if (!isVueFile)
|
|
109
|
+
return findings;
|
|
110
|
+
const hasOnMounted = ctx.sourceFile
|
|
111
|
+
.getDescendantsOfKind(SyntaxKind.CallExpression)
|
|
112
|
+
.some((c) => Node.isIdentifier(c.getExpression()) && c.getExpression().getText() === 'onMounted');
|
|
113
|
+
if (hasOnMounted)
|
|
160
114
|
return findings;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
115
|
+
for (const awaitExpr of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.AwaitExpression)) {
|
|
116
|
+
let isInsideFunction = false;
|
|
117
|
+
let cur = awaitExpr.getParent();
|
|
118
|
+
while (cur && cur !== ctx.sourceFile) {
|
|
119
|
+
if (Node.isArrowFunction(cur) || Node.isFunctionExpression(cur) || Node.isFunctionDeclaration(cur)) {
|
|
120
|
+
isInsideFunction = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
// MethodDeclaration with name 'setup' counts as top-level setup scope
|
|
124
|
+
if (Node.isMethodDeclaration(cur) && cur.getName() === 'setup')
|
|
125
|
+
break;
|
|
126
|
+
cur = cur.getParent();
|
|
173
127
|
}
|
|
128
|
+
if (isInsideFunction)
|
|
129
|
+
continue;
|
|
130
|
+
findings.push(finding('setup-side-effect', 'warning', 'pattern', 'Top-level await in setup — consider wrapping in onMounted() for SSR compatibility', ctx.filePath, awaitExpr.getStartLineNumber(), 1, { suggestion: 'onMounted(async () => { ... })' }));
|
|
174
131
|
}
|
|
175
132
|
return findings;
|
|
176
133
|
}
|
|
@@ -178,13 +135,109 @@ function setupSideEffect(ctx) {
|
|
|
178
135
|
// Destructuring reactive() loses reactivity
|
|
179
136
|
function reactiveDestructure(ctx) {
|
|
180
137
|
const findings = [];
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
138
|
+
for (const decl of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.VariableDeclaration)) {
|
|
139
|
+
const nameNode = decl.getNameNode();
|
|
140
|
+
if (!Node.isObjectBindingPattern(nameNode))
|
|
141
|
+
continue;
|
|
142
|
+
const init = decl.getInitializer();
|
|
143
|
+
if (init && Node.isCallExpression(init)) {
|
|
144
|
+
const callee = init.getExpression().getText();
|
|
145
|
+
if (callee === 'reactive') {
|
|
146
|
+
findings.push(finding('reactive-destructure', 'warning', 'bug', 'Destructuring reactive() loses reactivity — use toRefs() or access properties directly', ctx.filePath, decl.getStartLineNumber(), 1, { suggestion: 'const state = reactive({...}); use state.prop, or const { prop } = toRefs(state)' }));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return findings;
|
|
151
|
+
}
|
|
152
|
+
// ── Rule: computed-side-effect ───────────────────────────────────────────
|
|
153
|
+
// Side effects inside computed() properties
|
|
154
|
+
function computedSideEffect(ctx) {
|
|
155
|
+
const findings = [];
|
|
156
|
+
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
157
|
+
if (call.getExpression().getText() !== 'computed')
|
|
158
|
+
continue;
|
|
159
|
+
const args = call.getArguments();
|
|
160
|
+
if (args.length === 0)
|
|
161
|
+
continue;
|
|
162
|
+
const getter = args[0];
|
|
163
|
+
if (!Node.isArrowFunction(getter) && !Node.isFunctionExpression(getter))
|
|
164
|
+
continue;
|
|
165
|
+
// Detect side-effect calls: fetch, axios.*, set* (state setters)
|
|
166
|
+
const sideEffectCalls = getter.getDescendantsOfKind(SyntaxKind.CallExpression).filter((c) => {
|
|
167
|
+
const name = c.getExpression().getText();
|
|
168
|
+
return name === 'fetch' || name.startsWith('axios.');
|
|
169
|
+
});
|
|
170
|
+
// Detect mutations: assignments (=, +=, -=, etc.) and ++/--
|
|
171
|
+
const mutations = getter.getDescendantsOfKind(SyntaxKind.BinaryExpression).filter((b) => {
|
|
172
|
+
const op = b.getOperatorToken().getKind();
|
|
173
|
+
return op === SyntaxKind.EqualsToken || op === SyntaxKind.PlusEqualsToken || op === SyntaxKind.MinusEqualsToken;
|
|
174
|
+
});
|
|
175
|
+
const prefixMutations = getter.getDescendantsOfKind(SyntaxKind.PrefixUnaryExpression).filter((p) => {
|
|
176
|
+
const op = p.getOperatorToken();
|
|
177
|
+
return op === SyntaxKind.PlusPlusToken || op === SyntaxKind.MinusMinusToken;
|
|
178
|
+
});
|
|
179
|
+
const postfixMutations = getter.getDescendantsOfKind(SyntaxKind.PostfixUnaryExpression).filter((p) => {
|
|
180
|
+
const op = p.getOperatorToken();
|
|
181
|
+
return op === SyntaxKind.PlusPlusToken || op === SyntaxKind.MinusMinusToken;
|
|
182
|
+
});
|
|
183
|
+
if (sideEffectCalls.length > 0 ||
|
|
184
|
+
mutations.length > 0 ||
|
|
185
|
+
prefixMutations.length > 0 ||
|
|
186
|
+
postfixMutations.length > 0) {
|
|
187
|
+
findings.push(finding('computed-side-effect', 'warning', 'bug', 'Side effect detected inside computed property — computed should be pure', ctx.filePath, call.getStartLineNumber(), 1, { suggestion: 'Move side effects to watch() or a method' }));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return findings;
|
|
191
|
+
}
|
|
192
|
+
// ── Rule: shallow-ref-mutation ───────────────────────────────────────────
|
|
193
|
+
// Deep mutation on shallowRef without triggerRef — change won't be reactive
|
|
194
|
+
// Source: vuejs.org/api/reactivity-advanced.html#shallowref
|
|
195
|
+
function shallowRefMutation(ctx) {
|
|
196
|
+
const findings = [];
|
|
197
|
+
// Collect shallowRef variable names
|
|
198
|
+
const shallowRefs = new Set();
|
|
199
|
+
for (const decl of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.VariableDeclaration)) {
|
|
200
|
+
const init = decl.getInitializer();
|
|
201
|
+
if (init && Node.isCallExpression(init) && init.getExpression().getText() === 'shallowRef') {
|
|
202
|
+
shallowRefs.add(decl.getName());
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (shallowRefs.size === 0)
|
|
206
|
+
return findings;
|
|
207
|
+
// Collect which shallowRefs have matching triggerRef(refName) calls
|
|
208
|
+
const triggeredRefs = new Set();
|
|
209
|
+
for (const call of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
210
|
+
if (call.getExpression().getText() !== 'triggerRef')
|
|
211
|
+
continue;
|
|
212
|
+
const args = call.getArguments();
|
|
213
|
+
if (args.length > 0 && Node.isIdentifier(args[0])) {
|
|
214
|
+
triggeredRefs.add(args[0].getText());
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Find deep property access: state.value.prop = ... (not state.value = ...)
|
|
218
|
+
for (const bin of ctx.sourceFile.getDescendantsOfKind(SyntaxKind.BinaryExpression)) {
|
|
219
|
+
const op = bin.getOperatorToken().getKind();
|
|
220
|
+
if (op !== SyntaxKind.EqualsToken && op !== SyntaxKind.PlusEqualsToken && op !== SyntaxKind.MinusEqualsToken)
|
|
221
|
+
continue;
|
|
222
|
+
const left = bin.getLeft();
|
|
223
|
+
if (!Node.isPropertyAccessExpression(left))
|
|
224
|
+
continue;
|
|
225
|
+
// Check for pattern: shallowRef.value.deepProp = ...
|
|
226
|
+
const obj = left.getExpression();
|
|
227
|
+
if (!Node.isPropertyAccessExpression(obj))
|
|
228
|
+
continue;
|
|
229
|
+
if (obj.getName() !== 'value')
|
|
230
|
+
continue;
|
|
231
|
+
const root = obj.getExpression();
|
|
232
|
+
if (!Node.isIdentifier(root) || !shallowRefs.has(root.getText()))
|
|
233
|
+
continue;
|
|
234
|
+
const refName = root.getText();
|
|
235
|
+
// Only suppress if triggerRef is called on THIS specific ref
|
|
236
|
+
if (!triggeredRefs.has(refName)) {
|
|
237
|
+
findings.push(finding('shallow-ref-mutation', 'warning', 'bug', `Deep mutation on shallowRef '${refName}' won't trigger reactivity — use triggerRef() or reassign .value`, ctx.filePath, bin.getStartLineNumber(), 1, {
|
|
238
|
+
suggestion: `Use ${refName}.value = { ...${refName}.value, ${left.getName()}: newVal } or call triggerRef(${refName})`,
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
188
241
|
}
|
|
189
242
|
return findings;
|
|
190
243
|
}
|
|
@@ -194,5 +247,7 @@ export const vueRules = [
|
|
|
194
247
|
missingOnUnmounted,
|
|
195
248
|
setupSideEffect,
|
|
196
249
|
reactiveDestructure,
|
|
250
|
+
computedSideEffect,
|
|
251
|
+
shallowRefMutation,
|
|
197
252
|
];
|
|
198
253
|
//# sourceMappingURL=vue.js.map
|
package/dist/rules/vue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../src/rules/vue.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../src/rules/vue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Diff — detects behavior changes between old and new versions of code.
|
|
3
|
+
*
|
|
4
|
+
* Compares IR (InferResult[]) and concept maps (ConceptMap) between git versions
|
|
5
|
+
* to detect guard removals, error handling changes, new effects, param changes, etc.
|
|
6
|
+
*
|
|
7
|
+
* Used in `kern review --diff <base>` to augment line-level diffs with
|
|
8
|
+
* semantic understanding of WHAT changed.
|
|
9
|
+
*/
|
|
10
|
+
import type { ConceptMap } from '@kernlang/core';
|
|
11
|
+
import type { InferResult } from './types.js';
|
|
12
|
+
export type SemanticChangeType = 'guard-removed' | 'guard-added' | 'error-handling-removed' | 'error-handling-added' | 'effect-added' | 'effect-removed' | 'return-type-changed' | 'new-code-path' | 'param-changed';
|
|
13
|
+
export interface SemanticChange {
|
|
14
|
+
type: SemanticChangeType;
|
|
15
|
+
severity: 'error' | 'warning' | 'info';
|
|
16
|
+
functionName: string;
|
|
17
|
+
filePath: string;
|
|
18
|
+
line: number;
|
|
19
|
+
description: string;
|
|
20
|
+
oldValue?: string;
|
|
21
|
+
newValue?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get the old version of a file from git.
|
|
25
|
+
* Returns null for new files (no old version exists).
|
|
26
|
+
*/
|
|
27
|
+
export declare function getOldFileContent(filePath: string, baseRef: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Compute semantic differences between old and new versions of a file.
|
|
30
|
+
*
|
|
31
|
+
* Compares:
|
|
32
|
+
* - Functions (InferResult[]) for parameter and return type changes
|
|
33
|
+
* - Concepts (ConceptMap) for guard, error handling, and effect changes
|
|
34
|
+
* - New functions in the new version
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeSemanticDiff(oldInferred: InferResult[], newInferred: InferResult[], oldConcepts: ConceptMap | undefined, newConcepts: ConceptMap | undefined, filePath: string): SemanticChange[];
|
|
37
|
+
/**
|
|
38
|
+
* Compute semantic diff given old source string and new report data.
|
|
39
|
+
*
|
|
40
|
+
* This is the main entry point for the CLI — handles IR inference and
|
|
41
|
+
* concept extraction from both old and new source internally.
|
|
42
|
+
*
|
|
43
|
+
* @param oldSource - Source code from the base version
|
|
44
|
+
* @param newInferred - Inferred IR from the new version (from review pipeline)
|
|
45
|
+
* @param filePath - Relative or absolute file path
|
|
46
|
+
* @param newSource - New source code (used to extract concepts if provided)
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeSemanticDiffFromSource(oldSource: string, newInferred: InferResult[], filePath: string, newSource?: string): SemanticChange[];
|
|
49
|
+
/** Format semantic changes as a <kern-diff> section for LLM review. */
|
|
50
|
+
export declare function formatSemanticDiff(changes: SemanticChange[], filePath: string): string;
|
|
51
|
+
/** Convert semantic changes to ReviewFindings for inclusion in reports. */
|
|
52
|
+
export declare function semanticChangesToFindings(changes: SemanticChange[]): import('./types.js').ReviewFinding[];
|