@ontrails/warden 1.0.0-beta.1 → 1.0.0-beta.10
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +148 -0
- package/README.md +27 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/ast.d.ts +15 -8
- package/dist/rules/ast.d.ts.map +1 -1
- package/dist/rules/ast.js +99 -44
- package/dist/rules/ast.js.map +1 -1
- package/dist/rules/context-no-surface-types.js +1 -1
- package/dist/rules/context-no-surface-types.js.map +1 -1
- package/dist/rules/follow-declarations.d.ts +13 -0
- package/dist/rules/follow-declarations.d.ts.map +1 -0
- package/dist/rules/follow-declarations.js +264 -0
- package/dist/rules/follow-declarations.js.map +1 -0
- package/dist/rules/implementation-returns-result.d.ts +1 -1
- package/dist/rules/implementation-returns-result.d.ts.map +1 -1
- package/dist/rules/implementation-returns-result.js +52 -6
- package/dist/rules/implementation-returns-result.js.map +1 -1
- package/dist/rules/index.d.ts +2 -8
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +4 -8
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/no-direct-impl-in-route.d.ts +4 -4
- package/dist/rules/no-direct-impl-in-route.d.ts.map +1 -1
- package/dist/rules/no-direct-impl-in-route.js +15 -14
- package/dist/rules/no-direct-impl-in-route.js.map +1 -1
- package/dist/rules/no-direct-implementation-call.d.ts +3 -3
- package/dist/rules/no-direct-implementation-call.js +7 -7
- package/dist/rules/no-direct-implementation-call.js.map +1 -1
- package/dist/rules/no-sync-result-assumption.d.ts +1 -1
- package/dist/rules/no-sync-result-assumption.js +5 -5
- package/dist/rules/no-sync-result-assumption.js.map +1 -1
- package/dist/rules/no-throw-in-detour-target.js +2 -2
- package/dist/rules/no-throw-in-detour-target.js.map +1 -1
- package/dist/rules/no-throw-in-implementation.d.ts +1 -1
- package/dist/rules/no-throw-in-implementation.js +3 -3
- package/dist/rules/no-throw-in-implementation.js.map +1 -1
- package/dist/rules/specs.d.ts +1 -1
- package/dist/rules/specs.d.ts.map +1 -1
- package/dist/rules/specs.js +2 -2
- package/dist/rules/specs.js.map +1 -1
- package/dist/trails/context-no-surface-types.trail.d.ts +13 -0
- package/dist/trails/context-no-surface-types.trail.d.ts.map +1 -0
- package/dist/trails/context-no-surface-types.trail.js +21 -0
- package/dist/trails/context-no-surface-types.trail.js.map +1 -0
- package/dist/trails/follow-declarations.trail.d.ts +13 -0
- package/dist/trails/follow-declarations.trail.d.ts.map +1 -0
- package/dist/trails/follow-declarations.trail.js +22 -0
- package/dist/trails/follow-declarations.trail.js.map +1 -0
- package/dist/trails/implementation-returns-result.trail.d.ts +13 -0
- package/dist/trails/implementation-returns-result.trail.d.ts.map +1 -0
- package/dist/trails/implementation-returns-result.trail.js +20 -0
- package/dist/trails/implementation-returns-result.trail.js.map +1 -0
- package/dist/trails/index.d.ts +14 -0
- package/dist/trails/index.d.ts.map +1 -0
- package/dist/trails/index.js +13 -0
- package/dist/trails/index.js.map +1 -0
- package/dist/trails/no-direct-impl-in-route.trail.d.ts +13 -0
- package/dist/trails/no-direct-impl-in-route.trail.d.ts.map +1 -0
- package/dist/trails/no-direct-impl-in-route.trail.js +22 -0
- package/dist/trails/no-direct-impl-in-route.trail.js.map +1 -0
- package/dist/trails/no-direct-implementation-call.trail.d.ts +13 -0
- package/dist/trails/no-direct-implementation-call.trail.d.ts.map +1 -0
- package/dist/trails/no-direct-implementation-call.trail.js +16 -0
- package/dist/trails/no-direct-implementation-call.trail.js.map +1 -0
- package/dist/trails/no-sync-result-assumption.trail.d.ts +13 -0
- package/dist/trails/no-sync-result-assumption.trail.d.ts.map +1 -0
- package/dist/trails/no-sync-result-assumption.trail.js +19 -0
- package/dist/trails/no-sync-result-assumption.trail.js.map +1 -0
- package/dist/trails/no-throw-in-detour-target.trail.d.ts +14 -0
- package/dist/trails/no-throw-in-detour-target.trail.d.ts.map +1 -0
- package/dist/trails/no-throw-in-detour-target.trail.js +20 -0
- package/dist/trails/no-throw-in-detour-target.trail.js.map +1 -0
- package/dist/trails/no-throw-in-implementation.trail.d.ts +13 -0
- package/dist/trails/no-throw-in-implementation.trail.d.ts.map +1 -0
- package/dist/trails/no-throw-in-implementation.trail.js +20 -0
- package/dist/trails/no-throw-in-implementation.trail.js.map +1 -0
- package/dist/trails/prefer-schema-inference.trail.d.ts +13 -0
- package/dist/trails/prefer-schema-inference.trail.d.ts.map +1 -0
- package/dist/trails/prefer-schema-inference.trail.js +21 -0
- package/dist/trails/prefer-schema-inference.trail.js.map +1 -0
- package/dist/trails/run.d.ts +16 -0
- package/dist/trails/run.d.ts.map +1 -0
- package/dist/trails/run.js +30 -0
- package/dist/trails/run.js.map +1 -0
- package/dist/trails/schema.d.ts +52 -0
- package/dist/trails/schema.d.ts.map +1 -0
- package/dist/trails/schema.js +38 -0
- package/dist/trails/schema.js.map +1 -0
- package/dist/trails/topo.d.ts +3 -0
- package/dist/trails/topo.d.ts.map +1 -0
- package/dist/trails/topo.js +5 -0
- package/dist/trails/topo.js.map +1 -0
- package/dist/trails/valid-describe-refs.trail.d.ts +14 -0
- package/dist/trails/valid-describe-refs.trail.d.ts.map +1 -0
- package/dist/trails/valid-describe-refs.trail.js +18 -0
- package/dist/trails/valid-describe-refs.trail.js.map +1 -0
- package/dist/trails/valid-detour-refs.trail.d.ts +14 -0
- package/dist/trails/valid-detour-refs.trail.d.ts.map +1 -0
- package/dist/trails/valid-detour-refs.trail.js +24 -0
- package/dist/trails/valid-detour-refs.trail.js.map +1 -0
- package/dist/trails/wrap-rule.d.ts +29 -0
- package/dist/trails/wrap-rule.d.ts.map +1 -0
- package/dist/trails/wrap-rule.js +43 -0
- package/dist/trails/wrap-rule.js.map +1 -0
- package/package.json +5 -4
- package/src/__tests__/cli.test.ts +7 -7
- package/src/__tests__/drift.test.ts +1 -1
- package/src/__tests__/follow-declarations.test.ts +303 -0
- package/src/__tests__/implementation-returns-result.test.ts +60 -6
- package/src/__tests__/no-direct-implementation-call.test.ts +8 -8
- package/src/__tests__/no-sync-result-assumption.test.ts +6 -6
- package/src/__tests__/no-throw-in-detour-target.test.ts +6 -6
- package/src/__tests__/prefer-schema-inference.test.ts +4 -4
- package/src/__tests__/rules.test.ts +59 -20
- package/src/__tests__/trails.test.ts +19 -0
- package/src/__tests__/valid-describe-refs.test.ts +4 -4
- package/src/cli.ts +1 -4
- package/src/index.ts +21 -0
- package/src/rules/ast.ts +126 -57
- package/src/rules/context-no-surface-types.ts +1 -1
- package/src/rules/follow-declarations.ts +380 -0
- package/src/rules/implementation-returns-result.ts +63 -6
- package/src/rules/index.ts +4 -8
- package/src/rules/no-direct-impl-in-route.ts +20 -16
- package/src/rules/no-direct-implementation-call.ts +7 -7
- package/src/rules/no-sync-result-assumption.ts +5 -5
- package/src/rules/no-throw-in-detour-target.ts +2 -2
- package/src/rules/no-throw-in-implementation.ts +3 -3
- package/src/rules/specs.ts +5 -5
- package/src/trails/context-no-surface-types.trail.ts +21 -0
- package/src/trails/follow-declarations.trail.ts +22 -0
- package/src/trails/implementation-returns-result.trail.ts +20 -0
- package/src/trails/index.ts +14 -0
- package/src/trails/no-direct-impl-in-route.trail.ts +22 -0
- package/src/trails/no-direct-implementation-call.trail.ts +16 -0
- package/src/trails/no-sync-result-assumption.trail.ts +19 -0
- package/src/trails/no-throw-in-detour-target.trail.ts +20 -0
- package/src/trails/no-throw-in-implementation.trail.ts +20 -0
- package/src/trails/prefer-schema-inference.trail.ts +21 -0
- package/src/trails/run.ts +40 -0
- package/src/trails/schema.ts +46 -0
- package/src/trails/topo.ts +6 -0
- package/src/trails/valid-describe-refs.trail.ts +18 -0
- package/src/trails/valid-detour-refs.trail.ts +24 -0
- package/src/trails/wrap-rule.ts +84 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that `ctx.follow()` calls match the declared `follow` array.
|
|
3
|
+
*
|
|
4
|
+
* Statically analyzes trail run functions to find `ctx.follow('trailId', ...)`
|
|
5
|
+
* calls and compares them against the `follow: [...]` declaration in the trail
|
|
6
|
+
* config. Reports errors for undeclared follows and warnings for unused ones.
|
|
7
|
+
*/
|
|
8
|
+
import { findConfigProperty, findRunBodies, findTrailDefinitions, offsetToLine, parse, walk, } from './ast.js';
|
|
9
|
+
import { isTestFile } from './scan.js';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Shared identifier helpers
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
/** Get the name of an Identifier node, or null. */
|
|
14
|
+
const identifierName = (node) => {
|
|
15
|
+
if (node?.type !== 'Identifier') {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return node.name ?? null;
|
|
19
|
+
};
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// String literal helpers
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/** Check if a node is a string literal (covers `StringLiteral` and `Literal` with string value). */
|
|
24
|
+
const isStringLiteral = (node) => {
|
|
25
|
+
if (node.type === 'StringLiteral') {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (node.type === 'Literal') {
|
|
29
|
+
return typeof node.value === 'string';
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
/** Extract the string value from a string literal node. */
|
|
34
|
+
const getStringValue = (node) => {
|
|
35
|
+
const val = node.value;
|
|
36
|
+
return typeof val === 'string' ? val : null;
|
|
37
|
+
};
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Const identifier resolution
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
/**
|
|
42
|
+
* Best-effort resolution of `const NAME = 'value'` declarations via regex.
|
|
43
|
+
*
|
|
44
|
+
* Returns the string value if a simple `const <name> = '...'` or `"..."` is
|
|
45
|
+
* found in the source. Returns null for anything more complex.
|
|
46
|
+
*/
|
|
47
|
+
const resolveConstString = (name, sourceCode) => {
|
|
48
|
+
const pattern = new RegExp(`const\\s+${name}\\s*=\\s*(?:'([^']*)'|"([^"]*)")`);
|
|
49
|
+
const match = pattern.exec(sourceCode);
|
|
50
|
+
if (!match) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return match[1] ?? match[2] ?? null;
|
|
54
|
+
};
|
|
55
|
+
/** Try to resolve an Identifier element to a string via const declaration. */
|
|
56
|
+
const resolveIdentifierElement = (el, sourceCode) => {
|
|
57
|
+
const name = identifierName(el);
|
|
58
|
+
if (!name) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return resolveConstString(name, sourceCode);
|
|
62
|
+
};
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// Declared follow extraction
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
/** Extract the ArrayExpression elements from a config's `follow` property. */
|
|
67
|
+
const getFollowElements = (config) => {
|
|
68
|
+
const followProp = findConfigProperty(config, 'follow');
|
|
69
|
+
if (!followProp) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const arrayNode = followProp.value;
|
|
73
|
+
if (!arrayNode || arrayNode.type !== 'ArrayExpression') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const elements = arrayNode['elements'];
|
|
77
|
+
return elements ?? null;
|
|
78
|
+
};
|
|
79
|
+
/** Collect string IDs from array elements, resolving identifiers when possible. */
|
|
80
|
+
const collectStringIds = (elements, sourceCode) => {
|
|
81
|
+
const ids = new Set();
|
|
82
|
+
for (const el of elements) {
|
|
83
|
+
if (isStringLiteral(el)) {
|
|
84
|
+
const val = getStringValue(el);
|
|
85
|
+
if (val) {
|
|
86
|
+
ids.add(val);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (el.type === 'Identifier') {
|
|
90
|
+
const resolved = resolveIdentifierElement(el, sourceCode);
|
|
91
|
+
if (resolved) {
|
|
92
|
+
ids.add(resolved);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return ids;
|
|
97
|
+
};
|
|
98
|
+
/** Extract string literal elements from a `follow: [...]` array property. */
|
|
99
|
+
const extractDeclaredFollows = (config, sourceCode) => {
|
|
100
|
+
const elements = getFollowElements(config);
|
|
101
|
+
return elements ? collectStringIds(elements, sourceCode) : new Set();
|
|
102
|
+
};
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Called follow extraction — member expression helpers
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
const MEMBER_TYPES = new Set(['StaticMemberExpression', 'MemberExpression']);
|
|
107
|
+
/** Extract object and property Identifier names from a MemberExpression. */
|
|
108
|
+
const extractMemberPair = (callee) => {
|
|
109
|
+
if (!MEMBER_TYPES.has(callee.type)) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const objName = identifierName(callee.object);
|
|
113
|
+
const propName = identifierName(callee.property);
|
|
114
|
+
return objName && propName ? { objName, propName } : null;
|
|
115
|
+
};
|
|
116
|
+
/** Extract the first argument string from a CallExpression's arguments list. */
|
|
117
|
+
const extractFirstStringArg = (node) => {
|
|
118
|
+
const args = node['arguments'];
|
|
119
|
+
if (!args || args.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const [firstArg] = args;
|
|
123
|
+
if (!firstArg || !isStringLiteral(firstArg)) {
|
|
124
|
+
// Dynamic ID — cannot resolve statically
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return getStringValue(firstArg);
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Extract the second parameter name from a run function node.
|
|
131
|
+
*
|
|
132
|
+
* Handles `(input, ctx) => ...` and `async (input, context) => ...` and
|
|
133
|
+
* `function(input, ctx) { ... }` forms.
|
|
134
|
+
*/
|
|
135
|
+
const extractContextParamName = (runBody) => {
|
|
136
|
+
const params = runBody['params'];
|
|
137
|
+
if (!params || params.length < 2) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
return identifierName(params[1]);
|
|
141
|
+
};
|
|
142
|
+
/** Check if a callee is a member-style follow call: <ctxName>.follow(...). */
|
|
143
|
+
const isMemberFollowCall = (callee, ctxNames) => {
|
|
144
|
+
const pair = extractMemberPair(callee);
|
|
145
|
+
return !!pair && ctxNames.has(pair.objName) && pair.propName === 'follow';
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Check if a node is a `<ctxName>.follow(...)` call and return the string trail ID.
|
|
149
|
+
*
|
|
150
|
+
* Also matches bare `follow(...)` calls (destructured pattern).
|
|
151
|
+
*/
|
|
152
|
+
const extractFollowCallId = (node, ctxNames) => {
|
|
153
|
+
if (node.type !== 'CallExpression') {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const callee = node['callee'];
|
|
157
|
+
if (!callee) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
if (isMemberFollowCall(callee, ctxNames)) {
|
|
161
|
+
return extractFirstStringArg(node);
|
|
162
|
+
}
|
|
163
|
+
// Match bare follow(...) — destructured pattern
|
|
164
|
+
if (identifierName(callee) === 'follow') {
|
|
165
|
+
return extractFirstStringArg(node);
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
};
|
|
169
|
+
/** Build the set of context parameter names to match against. */
|
|
170
|
+
const buildCtxNames = (body) => {
|
|
171
|
+
const ctxNames = new Set(['ctx', 'context']);
|
|
172
|
+
const paramName = extractContextParamName(body);
|
|
173
|
+
if (paramName) {
|
|
174
|
+
ctxNames.add(paramName);
|
|
175
|
+
}
|
|
176
|
+
return ctxNames;
|
|
177
|
+
};
|
|
178
|
+
/** Walk run bodies and collect all statically resolvable ctx.follow() trail IDs. */
|
|
179
|
+
const extractCalledFollows = (config) => {
|
|
180
|
+
const ids = new Set();
|
|
181
|
+
for (const body of findRunBodies(config)) {
|
|
182
|
+
const ctxNames = buildCtxNames(body);
|
|
183
|
+
walk(body, (node) => {
|
|
184
|
+
const id = extractFollowCallId(node, ctxNames);
|
|
185
|
+
if (id) {
|
|
186
|
+
ids.add(id);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return ids;
|
|
191
|
+
};
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Diagnostic builders
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
const buildUndeclaredDiagnostic = (trailId, followId, filePath, line) => ({
|
|
196
|
+
filePath,
|
|
197
|
+
line,
|
|
198
|
+
message: `Trail "${trailId}": ctx.follow('${followId}') called but '${followId}' is not declared in follow`,
|
|
199
|
+
rule: 'follow-declarations',
|
|
200
|
+
severity: 'error',
|
|
201
|
+
});
|
|
202
|
+
const buildUnusedDiagnostic = (trailId, followId, filePath, line) => ({
|
|
203
|
+
filePath,
|
|
204
|
+
line,
|
|
205
|
+
message: `Trail "${trailId}": '${followId}' declared in follow but ctx.follow('${followId}') never called`,
|
|
206
|
+
rule: 'follow-declarations',
|
|
207
|
+
severity: 'warn',
|
|
208
|
+
});
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Comparison
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
/** Emit error for each called ID not present in declared set. */
|
|
213
|
+
const reportUndeclared = (called, declared, ctx, diagnostics) => {
|
|
214
|
+
for (const id of called) {
|
|
215
|
+
if (!declared.has(id)) {
|
|
216
|
+
diagnostics.push(buildUndeclaredDiagnostic(ctx.trailId, id, ctx.filePath, ctx.line));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
/** Emit warning for each declared ID not present in called set. */
|
|
221
|
+
const reportUnused = (declared, called, ctx, diagnostics) => {
|
|
222
|
+
for (const id of declared) {
|
|
223
|
+
if (!called.has(id)) {
|
|
224
|
+
diagnostics.push(buildUnusedDiagnostic(ctx.trailId, id, ctx.filePath, ctx.line));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const checkTrailDefinition = (def, filePath, sourceCode, diagnostics) => {
|
|
229
|
+
const declared = extractDeclaredFollows(def.config, sourceCode);
|
|
230
|
+
const called = extractCalledFollows(def.config);
|
|
231
|
+
if (declared.size === 0 && called.size === 0) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const line = offsetToLine(sourceCode, def.start);
|
|
235
|
+
const ctx = { filePath, line, trailId: def.id };
|
|
236
|
+
reportUndeclared(called, declared, ctx, diagnostics);
|
|
237
|
+
reportUnused(declared, called, ctx, diagnostics);
|
|
238
|
+
};
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// Rule
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
/**
|
|
243
|
+
* Validates that `ctx.follow()` calls align with declared `follow` arrays.
|
|
244
|
+
*/
|
|
245
|
+
export const followDeclarations = {
|
|
246
|
+
check(sourceCode, filePath) {
|
|
247
|
+
if (isTestFile(filePath)) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
const ast = parse(filePath, sourceCode);
|
|
251
|
+
if (!ast) {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
const diagnostics = [];
|
|
255
|
+
for (const def of findTrailDefinitions(ast)) {
|
|
256
|
+
checkTrailDefinition(def, filePath, sourceCode, diagnostics);
|
|
257
|
+
}
|
|
258
|
+
return diagnostics;
|
|
259
|
+
},
|
|
260
|
+
description: 'Ensure ctx.follow() calls match the declared follow array in trail definitions.',
|
|
261
|
+
name: 'follow-declarations',
|
|
262
|
+
severity: 'error',
|
|
263
|
+
};
|
|
264
|
+
//# sourceMappingURL=follow-declarations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow-declarations.js","sourceRoot":"","sources":["../../src/rules/follow-declarations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Finds implementations that return raw values instead of `Result`.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find `
|
|
4
|
+
* Uses AST parsing to find `run:` bodies and check that
|
|
5
5
|
* every return statement returns Result.ok(), Result.err(), ctx.follow(),
|
|
6
6
|
* or a tracked Result-typed variable.
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implementation-returns-result.d.ts","sourceRoot":"","sources":["../../src/rules/implementation-returns-result.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"implementation-returns-result.d.ts","sourceRoot":"","sources":["../../src/rules/implementation-returns-result.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;AA2W/D;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAiBzC,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Finds implementations that return raw values instead of `Result`.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find `
|
|
4
|
+
* Uses AST parsing to find `run:` bodies and check that
|
|
5
5
|
* every return statement returns Result.ok(), Result.err(), ctx.follow(),
|
|
6
6
|
* or a tracked Result-typed variable.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { findRunBodies, findTrailDefinitions, offsetToLine, parse, walk, } from './ast.js';
|
|
9
9
|
import { isTestFile } from './scan.js';
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
// Member expression helpers
|
|
@@ -35,7 +35,7 @@ const isResultMemberCall = (callee) => {
|
|
|
35
35
|
if (objName === 'ctx' && propName === 'follow') {
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
|
-
return propName === '
|
|
38
|
+
return propName === 'run';
|
|
39
39
|
};
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
// Expression classification
|
|
@@ -109,12 +109,58 @@ const trackResultVariable = (node, resultVars) => {
|
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
111
|
// ---------------------------------------------------------------------------
|
|
112
|
+
// Shallow walk (stops at nested function boundaries)
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
const FUNCTION_BOUNDARY_TYPES = new Set([
|
|
115
|
+
'ArrowFunctionExpression',
|
|
116
|
+
'FunctionExpression',
|
|
117
|
+
'FunctionDeclaration',
|
|
118
|
+
]);
|
|
119
|
+
/** Check if a value is a function-boundary AST node that should not be recursed into. */
|
|
120
|
+
const isFunctionBoundary = (val) => !!val &&
|
|
121
|
+
typeof val === 'object' &&
|
|
122
|
+
FUNCTION_BOUNDARY_TYPES.has(val.type);
|
|
123
|
+
/** Recurse into a single AST property value, skipping function boundaries. */
|
|
124
|
+
const visitValue = (val, visit, recurse) => {
|
|
125
|
+
if (Array.isArray(val)) {
|
|
126
|
+
for (const item of val) {
|
|
127
|
+
if (!isFunctionBoundary(item)) {
|
|
128
|
+
recurse(item, visit);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (val &&
|
|
133
|
+
typeof val === 'object' &&
|
|
134
|
+
val.type &&
|
|
135
|
+
!isFunctionBoundary(val)) {
|
|
136
|
+
recurse(val, visit);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Walk an AST node tree without recursing into nested function bodies.
|
|
141
|
+
*
|
|
142
|
+
* This ensures that return statements inside `.map()`, `.filter()`, `.then()`
|
|
143
|
+
* callbacks etc. are not mistakenly checked as implementation-level returns.
|
|
144
|
+
*/
|
|
145
|
+
const walkShallow = (node, visit) => {
|
|
146
|
+
if (!node || typeof node !== 'object') {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const n = node;
|
|
150
|
+
if (n.type) {
|
|
151
|
+
visit(n);
|
|
152
|
+
}
|
|
153
|
+
for (const val of Object.values(n)) {
|
|
154
|
+
visitValue(val, visit, walkShallow);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
112
158
|
// Return statement checking
|
|
113
159
|
// ---------------------------------------------------------------------------
|
|
114
160
|
/** Check return statements in a block body for non-Result returns. */
|
|
115
161
|
const checkReturnStatements = (blockBody, trailInfo, filePath, sourceCode, helperNames, diagnostics) => {
|
|
116
162
|
const resultVars = new Set();
|
|
117
|
-
|
|
163
|
+
walkShallow(blockBody, (node) => {
|
|
118
164
|
if (node.type === 'VariableDeclarator') {
|
|
119
165
|
trackResultVariable(node, resultVars);
|
|
120
166
|
}
|
|
@@ -203,8 +249,8 @@ const checkAllDefinitions = (ast, filePath, sourceCode) => {
|
|
|
203
249
|
const diagnostics = [];
|
|
204
250
|
const helperNames = collectResultHelperNames(ast, sourceCode);
|
|
205
251
|
for (const def of findTrailDefinitions(ast)) {
|
|
206
|
-
const info = { id: def.id, label:
|
|
207
|
-
for (const implValue of
|
|
252
|
+
const info = { id: def.id, label: 'Trail' };
|
|
253
|
+
for (const implValue of findRunBodies(def.config)) {
|
|
208
254
|
checkImplementation(implValue, info, filePath, sourceCode, helperNames, diagnostics);
|
|
209
255
|
}
|
|
210
256
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implementation-returns-result.js","sourceRoot":"","sources":["../../src/rules/implementation-returns-result.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"implementation-returns-result.js","sourceRoot":"","sources":["../../src/rules/implementation-returns-result.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { WardenRule } from './types.js';
|
|
|
2
2
|
export type { ProjectAwareWardenRule, ProjectContext, WardenDiagnostic, WardenRule, WardenSeverity, } from './types.js';
|
|
3
3
|
export { noThrowInImplementation } from './no-throw-in-implementation.js';
|
|
4
4
|
export { contextNoSurfaceTypes } from './context-no-surface-types.js';
|
|
5
|
+
export { followDeclarations } from './follow-declarations.js';
|
|
5
6
|
export { validDetourRefs } from './valid-detour-refs.js';
|
|
6
7
|
export { noDirectImplInRoute } from './no-direct-impl-in-route.js';
|
|
7
8
|
export { noDirectImplementationCall } from './no-direct-implementation-call.js';
|
|
@@ -10,13 +11,6 @@ export { implementationReturnsResult } from './implementation-returns-result.js'
|
|
|
10
11
|
export { noThrowInDetourTarget } from './no-throw-in-detour-target.js';
|
|
11
12
|
export { preferSchemaInference } from './prefer-schema-inference.js';
|
|
12
13
|
export { validDescribeRefs } from './valid-describe-refs.js';
|
|
13
|
-
/**
|
|
14
|
-
* All built-in warden rules, keyed by rule name.
|
|
15
|
-
*
|
|
16
|
-
* Rules that duplicate validateTopo checks (follows-trails-exist,
|
|
17
|
-
* no-recursive-follows, event-origins-exist, examples-match-schema,
|
|
18
|
-
* require-output-schema) and follows-matches-calls (now covered by
|
|
19
|
-
* testExamples follows coverage) have been removed.
|
|
20
|
-
*/
|
|
14
|
+
/** All built-in warden rules, keyed by rule name. */
|
|
21
15
|
export declare const wardenRules: ReadonlyMap<string, WardenRule>;
|
|
22
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qDAAqD;AACrD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAetD,CAAC"}
|
package/dist/rules/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { contextNoSurfaceTypes } from './context-no-surface-types.js';
|
|
2
|
+
import { followDeclarations } from './follow-declarations.js';
|
|
2
3
|
import { implementationReturnsResult } from './implementation-returns-result.js';
|
|
3
4
|
import { noDirectImplInRoute } from './no-direct-impl-in-route.js';
|
|
4
5
|
import { noDirectImplementationCall } from './no-direct-implementation-call.js';
|
|
@@ -10,6 +11,7 @@ import { validDescribeRefs } from './valid-describe-refs.js';
|
|
|
10
11
|
import { validDetourRefs } from './valid-detour-refs.js';
|
|
11
12
|
export { noThrowInImplementation } from './no-throw-in-implementation.js';
|
|
12
13
|
export { contextNoSurfaceTypes } from './context-no-surface-types.js';
|
|
14
|
+
export { followDeclarations } from './follow-declarations.js';
|
|
13
15
|
export { validDetourRefs } from './valid-detour-refs.js';
|
|
14
16
|
export { noDirectImplInRoute } from './no-direct-impl-in-route.js';
|
|
15
17
|
export { noDirectImplementationCall } from './no-direct-implementation-call.js';
|
|
@@ -18,17 +20,11 @@ export { implementationReturnsResult } from './implementation-returns-result.js'
|
|
|
18
20
|
export { noThrowInDetourTarget } from './no-throw-in-detour-target.js';
|
|
19
21
|
export { preferSchemaInference } from './prefer-schema-inference.js';
|
|
20
22
|
export { validDescribeRefs } from './valid-describe-refs.js';
|
|
21
|
-
/**
|
|
22
|
-
* All built-in warden rules, keyed by rule name.
|
|
23
|
-
*
|
|
24
|
-
* Rules that duplicate validateTopo checks (follows-trails-exist,
|
|
25
|
-
* no-recursive-follows, event-origins-exist, examples-match-schema,
|
|
26
|
-
* require-output-schema) and follows-matches-calls (now covered by
|
|
27
|
-
* testExamples follows coverage) have been removed.
|
|
28
|
-
*/
|
|
23
|
+
/** All built-in warden rules, keyed by rule name. */
|
|
29
24
|
export const wardenRules = new Map([
|
|
30
25
|
[noThrowInImplementation.name, noThrowInImplementation],
|
|
31
26
|
[contextNoSurfaceTypes.name, contextNoSurfaceTypes],
|
|
27
|
+
[followDeclarations.name, followDeclarations],
|
|
32
28
|
[preferSchemaInference.name, preferSchemaInference],
|
|
33
29
|
[validDescribeRefs.name, validDescribeRefs],
|
|
34
30
|
[validDetourRefs.name, validDetourRefs],
|
package/dist/rules/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAUzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAUzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAoC,IAAI,GAAG,CAGjE;IACA,CAAC,uBAAuB,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvD,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAC7C,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAC3C,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC;IACvC,CAAC,0BAA0B,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC7D,CAAC,sBAAsB,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACrD,CAAC,2BAA2B,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC/D,CAAC,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACnD,CAAC,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,CAAC;CAChD,CAAC,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Detects
|
|
2
|
+
* Detects trail implementations with `follow` that call `.run()` directly.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find
|
|
5
|
-
* `.
|
|
4
|
+
* Uses AST parsing to find trail definitions that declare `follow` and check for
|
|
5
|
+
* `.run()` call expressions in their bodies.
|
|
6
6
|
*/
|
|
7
7
|
import type { WardenRule } from './types.js';
|
|
8
8
|
/**
|
|
9
|
-
* Detects
|
|
9
|
+
* Detects trails with `follow` that call another trail's `.run()` directly.
|
|
10
10
|
*/
|
|
11
11
|
export declare const noDirectImplInRoute: WardenRule;
|
|
12
12
|
//# sourceMappingURL=no-direct-impl-in-route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-direct-impl-in-route.d.ts","sourceRoot":"","sources":["../../src/rules/no-direct-impl-in-route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"no-direct-impl-in-route.d.ts","sourceRoot":"","sources":["../../src/rules/no-direct-impl-in-route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;AAkC/D;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,UA2BjC,CAAC"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Detects
|
|
2
|
+
* Detects trail implementations with `follow` that call `.run()` directly.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find
|
|
5
|
-
* `.
|
|
4
|
+
* Uses AST parsing to find trail definitions that declare `follow` and check for
|
|
5
|
+
* `.run()` call expressions in their bodies.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
const
|
|
9
|
-
for (const body of
|
|
7
|
+
import { findConfigProperty, findRunBodies, findTrailDefinitions, isRunCall, offsetToLine, parse, walk, } from './ast.js';
|
|
8
|
+
const findImplCallsInTrailWithFollow = (def, filePath, sourceCode, diagnostics) => {
|
|
9
|
+
for (const body of findRunBodies(def.config)) {
|
|
10
10
|
walk(body, (node) => {
|
|
11
|
-
if (
|
|
11
|
+
if (isRunCall(node)) {
|
|
12
12
|
diagnostics.push({
|
|
13
13
|
filePath,
|
|
14
14
|
line: offsetToLine(sourceCode, node.start),
|
|
15
|
-
message: 'Use ctx.follow("trailId", input) instead of direct .
|
|
15
|
+
message: 'Use ctx.follow("trailId", input) instead of direct .run() calls. ctx.follow() validates input and propagates tracing.',
|
|
16
16
|
rule: 'no-direct-impl-in-route',
|
|
17
17
|
severity: 'warn',
|
|
18
18
|
});
|
|
@@ -20,12 +20,13 @@ const findImplCallsInHike = (def, filePath, sourceCode, diagnostics) => {
|
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
+
const hasFollowProperty = (config) => findConfigProperty(config, 'follow') !== null;
|
|
23
24
|
/**
|
|
24
|
-
* Detects
|
|
25
|
+
* Detects trails with `follow` that call another trail's `.run()` directly.
|
|
25
26
|
*/
|
|
26
27
|
export const noDirectImplInRoute = {
|
|
27
28
|
check(sourceCode, filePath) {
|
|
28
|
-
if (!/\
|
|
29
|
+
if (!/\btrail\s*\(/.test(sourceCode)) {
|
|
29
30
|
return [];
|
|
30
31
|
}
|
|
31
32
|
const ast = parse(filePath, sourceCode);
|
|
@@ -33,13 +34,13 @@ export const noDirectImplInRoute = {
|
|
|
33
34
|
return [];
|
|
34
35
|
}
|
|
35
36
|
const diagnostics = [];
|
|
36
|
-
const
|
|
37
|
-
for (const def of
|
|
38
|
-
|
|
37
|
+
const followDefs = findTrailDefinitions(ast).filter((d) => hasFollowProperty(d.config));
|
|
38
|
+
for (const def of followDefs) {
|
|
39
|
+
findImplCallsInTrailWithFollow(def, filePath, sourceCode, diagnostics);
|
|
39
40
|
}
|
|
40
41
|
return diagnostics;
|
|
41
42
|
},
|
|
42
|
-
description: 'Prefer ctx.follow() over direct .
|
|
43
|
+
description: 'Prefer ctx.follow() over direct .run() calls in trail bodies with follow.',
|
|
43
44
|
name: 'no-direct-impl-in-route',
|
|
44
45
|
severity: 'warn',
|
|
45
46
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-direct-impl-in-route.js","sourceRoot":"","sources":["../../src/rules/no-direct-impl-in-route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"no-direct-impl-in-route.js","sourceRoot":"","sources":["../../src/rules/no-direct-impl-in-route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,YAAY,EACZ,KAAK,EACL,IAAI,GACL,MAAM,UAAU,CAAC;AAUlB,MAAM,8BAA8B,GAAG,CACrC,GAAiC,EACjC,QAAgB,EAChB,UAAkB,EAClB,WAA+B,EACzB,EAAE;IACR,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,GAAG,CAAC,MAAiB,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;YAClB,IAAI,SAAS,CAAC,IAAe,CAAC,EAAE,CAAC;gBAC/B,WAAW,CAAC,IAAI,CAAC;oBACf,QAAQ;oBACR,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;oBAC1C,OAAO,EACL,uHAAuH;oBACzH,IAAI,EAAE,yBAAyB;oBAC/B,QAAQ,EAAE,MAAM;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,MAAe,EAAW,EAAE,CACrD,kBAAkB,CAAC,MAAiB,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,KAAK,CAAC,UAAkB,EAAE,QAAgB;QACxC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACrC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,WAAW,GAAuB,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACnE,iBAAiB,CAAC,CAAC,CAAC,MAAiB,CAAC,CACvC,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,8BAA8B,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,WAAW,EACT,2EAA2E;IAC7E,IAAI,EAAE,yBAAyB;IAE/B,QAAQ,EAAE,MAAM;CACjB,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Flags direct `.
|
|
2
|
+
* Flags direct `.run()` calls in application code.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find `.
|
|
4
|
+
* Uses AST parsing to find `.run()` call expressions,
|
|
5
5
|
* ignoring occurrences in strings and comments.
|
|
6
6
|
*/
|
|
7
7
|
import type { WardenRule } from './types.js';
|
|
8
8
|
/**
|
|
9
|
-
* Flags direct `.
|
|
9
|
+
* Flags direct `.run()` calls in application code.
|
|
10
10
|
*/
|
|
11
11
|
export declare const noDirectImplementationCall: WardenRule;
|
|
12
12
|
//# sourceMappingURL=no-direct-implementation-call.d.ts.map
|