eslint-plugin-traceability 1.6.1 → 1.6.2
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/lib/src/index.d.ts +6 -0
- package/lib/src/index.js +6 -0
- package/lib/src/rules/helpers/require-story-helpers.d.ts +7 -0
- package/lib/src/rules/helpers/require-story-helpers.js +9 -2
- package/lib/src/rules/require-branch-annotation.js +5 -1
- package/lib/src/rules/require-req-annotation.js +13 -1
- package/lib/src/rules/require-story-annotation.d.ts +4 -0
- package/lib/src/rules/require-story-annotation.js +5 -1
- package/lib/src/rules/valid-annotation-format.js +14 -2
- package/lib/src/rules/valid-req-reference.js +14 -0
- package/lib/src/rules/valid-story-reference.js +21 -0
- package/lib/src/utils/annotation-checker.js +94 -4
- package/lib/tests/cli-error-handling.test.js +1 -1
- package/lib/tests/plugin-default-export-and-configs.test.js +16 -0
- package/lib/tests/rules/error-reporting.test.js +72 -23
- package/lib/tests/rules/require-branch-annotation.test.js +5 -1
- package/lib/tests/rules/require-req-annotation.test.js +102 -17
- package/lib/tests/rules/require-story-annotation.test.js +1 -0
- package/lib/tests/rules/valid-annotation-format.test.js +5 -0
- package/lib/tests/rules/valid-req-reference.test.js +6 -0
- package/lib/tests/rules/valid-story-reference.test.js +5 -0
- package/package.json +1 -1
package/lib/src/index.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ import type { Rule } from "eslint";
|
|
|
12
12
|
declare const RULE_NAMES: readonly ["require-story-annotation", "require-req-annotation", "require-branch-annotation", "valid-annotation-format", "valid-story-reference", "valid-req-reference"];
|
|
13
13
|
type RuleName = (typeof RULE_NAMES)[number];
|
|
14
14
|
declare const rules: Record<RuleName, Rule.RuleModule>;
|
|
15
|
+
/**
|
|
16
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
17
|
+
* @req REQ-ERROR-SEVERITY - Map rule types to appropriate ESLint severity levels (errors vs warnings)
|
|
18
|
+
* The recommended and strict configs treat missing annotations and missing references as errors,
|
|
19
|
+
* while formatting issues are reported as warnings, matching the story's severity conventions.
|
|
20
|
+
*/
|
|
15
21
|
declare const configs: {
|
|
16
22
|
recommended: {
|
|
17
23
|
plugins: {
|
package/lib/src/index.js
CHANGED
|
@@ -67,6 +67,12 @@ RULE_NAMES.forEach(
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
|
+
/**
|
|
71
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
72
|
+
* @req REQ-ERROR-SEVERITY - Map rule types to appropriate ESLint severity levels (errors vs warnings)
|
|
73
|
+
* The recommended and strict configs treat missing annotations and missing references as errors,
|
|
74
|
+
* while formatting issues are reported as warnings, matching the story's severity conventions.
|
|
75
|
+
*/
|
|
70
76
|
const configs = {
|
|
71
77
|
recommended: [
|
|
72
78
|
{
|
|
@@ -100,9 +100,11 @@ declare function shouldProcessNode(node: any, scope: string[], exportPriority?:
|
|
|
100
100
|
* Report a missing @story annotation for a function-like node
|
|
101
101
|
* Provides a suggestion to add the annotation.
|
|
102
102
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
103
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
103
104
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
104
105
|
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing annotations with suggestion
|
|
105
106
|
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing annotations while preserving suggestions
|
|
107
|
+
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
106
108
|
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
107
109
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
108
110
|
* @param {any} node - AST node that is missing the annotation
|
|
@@ -112,10 +114,15 @@ declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node:
|
|
|
112
114
|
/**
|
|
113
115
|
* Report a missing @story annotation for a method-like node
|
|
114
116
|
* Provides a suggestion to update the method/interface with the annotation.
|
|
117
|
+
* The error data payload uses both name and functionName for consistent, specific error context.
|
|
115
118
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
116
119
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
120
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
117
121
|
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
118
122
|
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing method/interface annotations while preserving suggestions
|
|
123
|
+
* @req REQ-ERROR-SPECIFIC - Method error reports must include both name and functionName in the data payload for specific function context
|
|
124
|
+
* @req REQ-ERROR-LOCATION - Method error reports must use the method name node to anchor error location
|
|
125
|
+
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
119
126
|
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
120
127
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
121
128
|
* @param {any} node - AST node that is missing the annotation
|
|
@@ -238,9 +238,11 @@ function shouldProcessNode(node, scope, exportPriority = "all") {
|
|
|
238
238
|
* Report a missing @story annotation for a function-like node
|
|
239
239
|
* Provides a suggestion to add the annotation.
|
|
240
240
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
241
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
241
242
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
242
243
|
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing annotations with suggestion
|
|
243
244
|
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing annotations while preserving suggestions
|
|
245
|
+
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
244
246
|
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
245
247
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
246
248
|
* @param {any} node - AST node that is missing the annotation
|
|
@@ -260,7 +262,7 @@ function reportMissing(context, sourceCode, node, passedTarget) {
|
|
|
260
262
|
context.report({
|
|
261
263
|
node: nameNode,
|
|
262
264
|
messageId: "missingStory",
|
|
263
|
-
data: { name },
|
|
265
|
+
data: { name, functionName: name },
|
|
264
266
|
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget),
|
|
265
267
|
suggest: [
|
|
266
268
|
{
|
|
@@ -277,10 +279,15 @@ function reportMissing(context, sourceCode, node, passedTarget) {
|
|
|
277
279
|
/**
|
|
278
280
|
* Report a missing @story annotation for a method-like node
|
|
279
281
|
* Provides a suggestion to update the method/interface with the annotation.
|
|
282
|
+
* The error data payload uses both name and functionName for consistent, specific error context.
|
|
280
283
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
281
284
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
285
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
282
286
|
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
283
287
|
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing method/interface annotations while preserving suggestions
|
|
288
|
+
* @req REQ-ERROR-SPECIFIC - Method error reports must include both name and functionName in the data payload for specific function context
|
|
289
|
+
* @req REQ-ERROR-LOCATION - Method error reports must use the method name node to anchor error location
|
|
290
|
+
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
284
291
|
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
285
292
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
286
293
|
* @param {any} node - AST node that is missing the annotation
|
|
@@ -297,7 +304,7 @@ function reportMethod(context, sourceCode, node, passedTarget) {
|
|
|
297
304
|
context.report({
|
|
298
305
|
node: nameNode,
|
|
299
306
|
messageId: "missingStory",
|
|
300
|
-
data: { name },
|
|
307
|
+
data: { name, functionName: name },
|
|
301
308
|
fix: (0, require_story_core_1.createMethodFix)(resolvedTarget),
|
|
302
309
|
suggest: [
|
|
303
310
|
{
|
|
@@ -16,7 +16,11 @@ const rule = {
|
|
|
16
16
|
},
|
|
17
17
|
fixable: "code",
|
|
18
18
|
messages: {
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
21
|
+
* @req REQ-ERROR-CONSISTENCY - Use shared branch error message convention with {{missing}} placeholder
|
|
22
|
+
*/
|
|
23
|
+
missingAnnotation: "Branch is missing required annotation: {{missing}}.",
|
|
20
24
|
},
|
|
21
25
|
schema: [
|
|
22
26
|
{
|
|
@@ -11,7 +11,19 @@ const rule = {
|
|
|
11
11
|
recommended: "error",
|
|
12
12
|
},
|
|
13
13
|
messages: {
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
16
|
+
* @req REQ-ERROR-CONSISTENCY - Align missing @req function error with cross-rule conventions
|
|
17
|
+
* @req REQ-ERROR-SPECIFIC - Provide specific function name in error message
|
|
18
|
+
* @req REQ-ERROR-SUGGESTION - Suggest adding a @req annotation with an example identifier
|
|
19
|
+
* @req REQ-ERROR-CONTEXT - Include @req format guidance in the error text
|
|
20
|
+
* @req REQ-ERROR-LOCATION - Report the error at the function identifier location
|
|
21
|
+
* @req REQ-ERROR-SEVERITY - Use ESLint severity level "error" for missing @req annotations
|
|
22
|
+
*
|
|
23
|
+
* This rule uses ESLint's message data placeholders for the function name,
|
|
24
|
+
* specifically the {{name}} placeholder populated via context.report.
|
|
25
|
+
*/
|
|
26
|
+
missingReq: "Function '{{functionName}}' is missing a required @req annotation. Add a JSDoc or line comment with @req (for example, '@req REQ-EXAMPLE') referencing the appropriate requirement from the story file.",
|
|
15
27
|
},
|
|
16
28
|
schema: [
|
|
17
29
|
{
|
|
@@ -16,9 +16,13 @@ import type { Rule } from "eslint";
|
|
|
16
16
|
* ESLint rule to require @story annotations on functions/methods.
|
|
17
17
|
*
|
|
18
18
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
19
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
19
20
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
20
21
|
* @req REQ-ANNOTATION-REQUIRED
|
|
21
22
|
* @req REQ-AUTOFIX-MISSING - This rule participates in auto-fix for missing @story annotations.
|
|
23
|
+
* @req REQ-ERROR-MSG-CONTENT - Error message instructs adding an explicit @story annotation that points to the implementing story file.
|
|
24
|
+
* @req REQ-ERROR-MSG-PLACEHOLDER - Error message retains the {{name}} placeholder while also providing functionName in the data payload for cross-rule consistency.
|
|
25
|
+
* @req REQ-ERROR-MSG-ACTIONABLE - Error message text is concise, imperative, and describes the required remediation.
|
|
22
26
|
*/
|
|
23
27
|
declare const rule: Rule.RuleModule;
|
|
24
28
|
export default rule;
|
|
@@ -6,9 +6,13 @@ const require_story_helpers_1 = require("./helpers/require-story-helpers");
|
|
|
6
6
|
* ESLint rule to require @story annotations on functions/methods.
|
|
7
7
|
*
|
|
8
8
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
9
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
9
10
|
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
10
11
|
* @req REQ-ANNOTATION-REQUIRED
|
|
11
12
|
* @req REQ-AUTOFIX-MISSING - This rule participates in auto-fix for missing @story annotations.
|
|
13
|
+
* @req REQ-ERROR-MSG-CONTENT - Error message instructs adding an explicit @story annotation that points to the implementing story file.
|
|
14
|
+
* @req REQ-ERROR-MSG-PLACEHOLDER - Error message retains the {{name}} placeholder while also providing functionName in the data payload for cross-rule consistency.
|
|
15
|
+
* @req REQ-ERROR-MSG-ACTIONABLE - Error message text is concise, imperative, and describes the required remediation.
|
|
12
16
|
*/
|
|
13
17
|
const rule = {
|
|
14
18
|
meta: {
|
|
@@ -29,7 +33,7 @@ const rule = {
|
|
|
29
33
|
*/
|
|
30
34
|
fixable: "code",
|
|
31
35
|
messages: {
|
|
32
|
-
missingStory: "
|
|
36
|
+
missingStory: "Function '{{name}}' must have an explicit @story annotation. Add a JSDoc or line comment with @story that points to the implementing story file (for example, docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md).",
|
|
33
37
|
},
|
|
34
38
|
schema: [
|
|
35
39
|
{
|
|
@@ -324,8 +324,20 @@ exports.default = {
|
|
|
324
324
|
recommended: "error",
|
|
325
325
|
},
|
|
326
326
|
messages: {
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
/**
|
|
328
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
329
|
+
* @req REQ-ERROR-SPECIFIC - Provide specific details about invalid @story annotation format
|
|
330
|
+
* @req REQ-ERROR-CONTEXT - Include human-readable details about the expected @story annotation format
|
|
331
|
+
* @req REQ-ERROR-CONSISTENCY - Use shared "Invalid annotation format: {{details}}." message pattern across rules
|
|
332
|
+
*/
|
|
333
|
+
invalidStoryFormat: "Invalid annotation format: {{details}}.",
|
|
334
|
+
/**
|
|
335
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
336
|
+
* @req REQ-ERROR-SPECIFIC - Provide specific details about invalid @req annotation format
|
|
337
|
+
* @req REQ-ERROR-CONTEXT - Include human-readable details about the expected @req annotation format
|
|
338
|
+
* @req REQ-ERROR-CONSISTENCY - Use shared "Invalid annotation format: {{details}}." message pattern across rules
|
|
339
|
+
*/
|
|
340
|
+
invalidReqFormat: "Invalid annotation format: {{details}}.",
|
|
329
341
|
},
|
|
330
342
|
schema: [],
|
|
331
343
|
/**
|
|
@@ -170,7 +170,21 @@ exports.default = {
|
|
|
170
170
|
recommended: "error",
|
|
171
171
|
},
|
|
172
172
|
messages: {
|
|
173
|
+
/**
|
|
174
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
175
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
176
|
+
* @req REQ-ERROR-SPECIFIC - Provide specific diagnostics when a referenced requirement ID cannot be found in a story
|
|
177
|
+
* @req REQ-ERROR-CONTEXT - Include both the missing requirement ID and the story path in the message
|
|
178
|
+
* @req REQ-ERROR-CONSISTENCY - Use a consistent message template for requirement lookup failures
|
|
179
|
+
*/
|
|
173
180
|
reqMissing: "Requirement '{{reqId}}' not found in '{{storyPath}}'",
|
|
181
|
+
/**
|
|
182
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
183
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
184
|
+
* @req REQ-ERROR-SPECIFIC - Indicate that the story path associated with a @req annotation is invalid
|
|
185
|
+
* @req REQ-ERROR-CONTEXT - Include the problematic storyPath value so the developer can correct it
|
|
186
|
+
* @req REQ-ERROR-CONSISTENCY - Reuse the same storyPath placeholder convention used by other rules
|
|
187
|
+
*/
|
|
174
188
|
invalidPath: "Invalid story path '{{storyPath}}'",
|
|
175
189
|
},
|
|
176
190
|
schema: [],
|
|
@@ -180,8 +180,29 @@ exports.default = {
|
|
|
180
180
|
recommended: "error",
|
|
181
181
|
},
|
|
182
182
|
messages: {
|
|
183
|
+
/**
|
|
184
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
185
|
+
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
186
|
+
* @req REQ-ERROR-SPECIFIC - Provide specific diagnostics when a referenced story file cannot be found
|
|
187
|
+
* @req REQ-ERROR-CONTEXT - Include the original story path in the error message for troubleshooting
|
|
188
|
+
* @req REQ-ERROR-CONSISTENCY - Use consistent file-related error wording and placeholders across rules
|
|
189
|
+
*/
|
|
183
190
|
fileMissing: "Story file '{{path}}' not found",
|
|
191
|
+
/**
|
|
192
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
193
|
+
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
194
|
+
* @req REQ-ERROR-SPECIFIC - Indicate that the story file extension is invalid and what is expected
|
|
195
|
+
* @req REQ-ERROR-CONTEXT - Include the provided path so developers can see which reference is wrong
|
|
196
|
+
* @req REQ-ERROR-CONSISTENCY - Reuse the same pattern of "{{path}}" placeholder across file validation messages
|
|
197
|
+
*/
|
|
184
198
|
invalidExtension: "Invalid story file extension for '{{path}}', expected '.story.md'",
|
|
199
|
+
/**
|
|
200
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
201
|
+
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
202
|
+
* @req REQ-ERROR-SPECIFIC - Explain that the story path is invalid due to absolute or unsafe traversal
|
|
203
|
+
* @req REQ-ERROR-CONTEXT - Surface the offending path to assist with correcting the reference
|
|
204
|
+
* @req REQ-ERROR-CONSISTENCY - Maintain a consistent template for invalid path diagnostics across rules
|
|
205
|
+
*/
|
|
185
206
|
invalidPath: "Invalid story path '{{path}}'",
|
|
186
207
|
/**
|
|
187
208
|
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.checkReqAnnotation = checkReqAnnotation;
|
|
4
4
|
const require_story_utils_1 = require("../rules/helpers/require-story-utils");
|
|
5
|
+
const require_story_io_1 = require("../rules/helpers/require-story-io");
|
|
5
6
|
/**
|
|
6
7
|
* Helper to retrieve the JSDoc comment for a node.
|
|
7
8
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -42,12 +43,94 @@ function combineComments(leading, before) {
|
|
|
42
43
|
function commentContainsReq(c) {
|
|
43
44
|
return c && typeof c.value === "string" && c.value.includes("@req");
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Line-based helper adapted from linesBeforeHasStory to detect @req.
|
|
48
|
+
*/
|
|
49
|
+
function linesBeforeHasReq(sourceCode, node) {
|
|
50
|
+
const lines = sourceCode && sourceCode.lines;
|
|
51
|
+
const startLine = node && node.loc && typeof node.loc.start?.line === "number"
|
|
52
|
+
? node.loc.start.line
|
|
53
|
+
: null;
|
|
54
|
+
if (!Array.isArray(lines) || typeof startLine !== "number") {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const from = Math.max(0, startLine - 1 - require_story_io_1.LOOKBACK_LINES);
|
|
58
|
+
const to = Math.max(0, startLine - 1);
|
|
59
|
+
for (let i = from; i < to; i++) {
|
|
60
|
+
const text = lines[i];
|
|
61
|
+
if (typeof text === "string" && text.includes("@req")) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Parent-chain helper adapted from parentChainHasStory to detect @req.
|
|
69
|
+
*/
|
|
70
|
+
function parentChainHasReq(sourceCode, node) {
|
|
71
|
+
let p = node && node.parent;
|
|
72
|
+
while (p) {
|
|
73
|
+
const pComments = typeof sourceCode?.getCommentsBefore === "function"
|
|
74
|
+
? sourceCode.getCommentsBefore(p) || []
|
|
75
|
+
: [];
|
|
76
|
+
if (Array.isArray(pComments) &&
|
|
77
|
+
pComments.some((c) => typeof c.value === "string" && c.value.includes("@req"))) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
const pLeading = p.leadingComments || [];
|
|
81
|
+
if (Array.isArray(pLeading) &&
|
|
82
|
+
pLeading.some((c) => typeof c.value === "string" && c.value.includes("@req"))) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
p = p.parent;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Fallback text window helper adapted from fallbackTextBeforeHasStory to detect @req.
|
|
91
|
+
*/
|
|
92
|
+
function fallbackTextBeforeHasReq(sourceCode, node) {
|
|
93
|
+
if (typeof sourceCode?.getText !== "function" ||
|
|
94
|
+
!Array.isArray((node && node.range) || [])) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const range = node.range;
|
|
98
|
+
if (!Array.isArray(range) || typeof range[0] !== "number") {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const start = Math.max(0, range[0] - require_story_io_1.FALLBACK_WINDOW);
|
|
103
|
+
const textBefore = sourceCode.getText().slice(start, range[0]);
|
|
104
|
+
if (typeof textBefore === "string" && textBefore.includes("@req")) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
/* noop */
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
45
113
|
/**
|
|
46
114
|
* Helper to determine whether a JSDoc or any nearby comments contain a @req annotation.
|
|
47
115
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
48
116
|
* @req REQ-ANNOTATION-REQ-DETECTION - Determine presence of @req annotation
|
|
49
117
|
*/
|
|
50
|
-
function hasReqAnnotation(jsdoc, comments) {
|
|
118
|
+
function hasReqAnnotation(jsdoc, comments, context, node) {
|
|
119
|
+
try {
|
|
120
|
+
const sourceCode = context && typeof context.getSourceCode === "function"
|
|
121
|
+
? context.getSourceCode()
|
|
122
|
+
: undefined;
|
|
123
|
+
if (sourceCode && node) {
|
|
124
|
+
if (linesBeforeHasReq(sourceCode, node) ||
|
|
125
|
+
parentChainHasReq(sourceCode, node) ||
|
|
126
|
+
fallbackTextBeforeHasReq(sourceCode, node)) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Swallow detection errors and fall through to simple checks.
|
|
133
|
+
}
|
|
51
134
|
// BRANCH @req detection on JSDoc or comments
|
|
52
135
|
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
53
136
|
// @req REQ-ANNOTATION-REQ-DETECTION
|
|
@@ -103,14 +186,21 @@ function createMissingReqFix(node) {
|
|
|
103
186
|
* @req REQ-ANNOTATION-REPORTING - Report missing @req annotation to context
|
|
104
187
|
* @req REQ-ERROR-SPECIFIC - Provide specific error details including node name
|
|
105
188
|
* @req REQ-ERROR-LOCATION - Include contextual location information in errors
|
|
189
|
+
* @req REQ-ERROR-SUGGESTION - Provide actionable suggestions or fixes where possible
|
|
190
|
+
* @req REQ-ERROR-CONTEXT - Include contextual hints to help understand the error
|
|
106
191
|
*/
|
|
107
192
|
function reportMissing(context, node, enableFix = true) {
|
|
108
193
|
const rawName = (0, require_story_utils_1.getNodeName)(node) ?? (node && (0, require_story_utils_1.getNodeName)(node.parent));
|
|
109
194
|
const name = rawName ?? "(anonymous)";
|
|
195
|
+
const nameNode = (node && node.id && node.id.type === "Identifier"
|
|
196
|
+
? node.id
|
|
197
|
+
: node && node.key && node.key.type === "Identifier"
|
|
198
|
+
? node.key
|
|
199
|
+
: node) ?? node;
|
|
110
200
|
const reportOptions = {
|
|
111
|
-
node,
|
|
201
|
+
node: nameNode,
|
|
112
202
|
messageId: "missingReq",
|
|
113
|
-
data: { name },
|
|
203
|
+
data: { name, functionName: name },
|
|
114
204
|
};
|
|
115
205
|
if (enableFix) {
|
|
116
206
|
reportOptions.fix = createMissingReqFix(node);
|
|
@@ -133,7 +223,7 @@ function checkReqAnnotation(context, node, options) {
|
|
|
133
223
|
const leading = getLeadingComments(node);
|
|
134
224
|
const comments = getCommentsBefore(sourceCode, node);
|
|
135
225
|
const all = combineComments(leading, comments);
|
|
136
|
-
const hasReq = hasReqAnnotation(jsdoc, all);
|
|
226
|
+
const hasReq = hasReqAnnotation(jsdoc, all, context, node);
|
|
137
227
|
// BRANCH when a @req annotation is missing and must be reported
|
|
138
228
|
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
139
229
|
// @req REQ-ANNOTATION-REQ-DETECTION
|
|
@@ -39,6 +39,6 @@ describe("CLI Error Handling for Traceability Plugin (Story 001.0-DEV-PLUGIN-SET
|
|
|
39
39
|
});
|
|
40
40
|
// Expect non-zero exit and missing annotation message on stdout
|
|
41
41
|
expect(result.status).not.toBe(0);
|
|
42
|
-
expect(result.stdout).toContain("
|
|
42
|
+
expect(result.stdout).toContain("Function 'foo' must have an explicit @story annotation. Add a JSDoc or line comment with @story that points to the implementing story file (for example, docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md)");
|
|
43
43
|
});
|
|
44
44
|
});
|
|
@@ -36,7 +36,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
/**
|
|
37
37
|
* Tests for: docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
38
38
|
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
39
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
39
40
|
* @req REQ-PLUGIN-STRUCTURE - Validate plugin default export and configs in src/index.ts
|
|
41
|
+
* @req REQ-ERROR-SEVERITY - Validate error severity configuration in plugin configs
|
|
40
42
|
*/
|
|
41
43
|
const index_1 = __importStar(require("../src/index"));
|
|
42
44
|
describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
@@ -69,4 +71,18 @@ describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", ()
|
|
|
69
71
|
const strictRules = index_1.configs.strict[0].rules;
|
|
70
72
|
expect(strictRules).toEqual(index_1.configs.recommended[0].rules);
|
|
71
73
|
});
|
|
74
|
+
it("[REQ-ERROR-SEVERITY] configs.recommended maps valid-annotation-format to warn and others to error", () => {
|
|
75
|
+
const recommendedRules = index_1.configs.recommended[0].rules;
|
|
76
|
+
expect(recommendedRules).toHaveProperty("traceability/valid-annotation-format", "warn");
|
|
77
|
+
expect(recommendedRules).toHaveProperty("traceability/require-story-annotation", "error");
|
|
78
|
+
expect(recommendedRules).toHaveProperty("traceability/require-req-annotation", "error");
|
|
79
|
+
expect(recommendedRules).toHaveProperty("traceability/require-branch-annotation", "error");
|
|
80
|
+
expect(recommendedRules).toHaveProperty("traceability/valid-story-reference", "error");
|
|
81
|
+
expect(recommendedRules).toHaveProperty("traceability/valid-req-reference", "error");
|
|
82
|
+
});
|
|
83
|
+
it("[REQ-ERROR-SEVERITY] configs.strict uses same severity mapping as recommended", () => {
|
|
84
|
+
const strictRules = index_1.configs.strict[0].rules;
|
|
85
|
+
const recommendedRules = index_1.configs.recommended[0].rules;
|
|
86
|
+
expect(strictRules).toEqual(recommendedRules);
|
|
87
|
+
});
|
|
72
88
|
});
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
* @req REQ-ERROR-SPECIFIC - Specific details about what annotation is missing or invalid
|
|
10
10
|
* @req REQ-ERROR-SUGGESTION - Suggest concrete steps to fix the issue
|
|
11
11
|
* @req REQ-ERROR-CONTEXT - Include relevant context in error messages
|
|
12
|
+
* @req REQ-ERROR-LOCATION - Include precise location information in error messages
|
|
12
13
|
*/
|
|
13
14
|
const eslint_1 = require("eslint");
|
|
14
15
|
const require_story_annotation_1 = __importDefault(require("../../src/rules/require-story-annotation"));
|
|
@@ -18,31 +19,79 @@ const ruleTester = new eslint_1.RuleTester({
|
|
|
18
19
|
},
|
|
19
20
|
});
|
|
20
21
|
describe("Error Reporting Enhancements for require-story-annotation (Story 007.0-DEV-ERROR-REPORTING)", () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
describe("valid cases", () => {
|
|
23
|
+
ruleTester.run("require-story-annotation", require_story_annotation_1.default, {
|
|
24
|
+
valid: [
|
|
25
|
+
{
|
|
26
|
+
name: "[007.0-DEV-ERROR-REPORTING] valid with existing annotation",
|
|
27
|
+
code: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */ function foo() {}`,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
invalid: [],
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe("REQ-ERROR-SPECIFIC - missing @story annotation should report specific details and suggestion", () => {
|
|
34
|
+
it("reports specific message, data, and suggestions for function 'bar'", () => {
|
|
35
|
+
const code = "function bar() {}";
|
|
36
|
+
const reported = [];
|
|
37
|
+
const context = {
|
|
38
|
+
id: "require-story-annotation",
|
|
39
|
+
options: [],
|
|
40
|
+
report: (descriptor) => {
|
|
41
|
+
reported.push(descriptor);
|
|
42
|
+
},
|
|
43
|
+
getFilename: () => "test.js",
|
|
44
|
+
getSourceCode: () => ({
|
|
45
|
+
text: code,
|
|
46
|
+
getText: () => code,
|
|
47
|
+
ast: {
|
|
48
|
+
type: "Program",
|
|
49
|
+
body: [],
|
|
50
|
+
sourceType: "module",
|
|
51
|
+
},
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
const listeners = require_story_annotation_1.default.create(context);
|
|
55
|
+
// Minimal synthetic AST nodes for the visitors
|
|
56
|
+
const programNode = {
|
|
57
|
+
type: "Program",
|
|
58
|
+
body: [
|
|
34
59
|
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
],
|
|
60
|
+
type: "FunctionDeclaration",
|
|
61
|
+
id: { type: "Identifier", name: "bar" },
|
|
62
|
+
params: [],
|
|
63
|
+
body: {
|
|
64
|
+
type: "BlockStatement",
|
|
65
|
+
body: [],
|
|
66
|
+
},
|
|
43
67
|
},
|
|
44
68
|
],
|
|
45
|
-
|
|
46
|
-
|
|
69
|
+
sourceType: "module",
|
|
70
|
+
};
|
|
71
|
+
const functionNode = programNode.body[0];
|
|
72
|
+
// Invoke visitors if they exist
|
|
73
|
+
if (typeof listeners.Program === "function") {
|
|
74
|
+
listeners.Program(programNode);
|
|
75
|
+
}
|
|
76
|
+
if (typeof listeners.FunctionDeclaration === "function") {
|
|
77
|
+
listeners.FunctionDeclaration(functionNode);
|
|
78
|
+
}
|
|
79
|
+
expect(reported.length).toBe(1);
|
|
80
|
+
const error = reported[0];
|
|
81
|
+
// Message template should be defined and contain the {{name}} placeholder
|
|
82
|
+
const template = require_story_annotation_1.default.meta?.messages?.missingStory;
|
|
83
|
+
expect(typeof template).toBe("string");
|
|
84
|
+
expect(template.length).toBeGreaterThan(0);
|
|
85
|
+
expect(template.includes("{{name}}")).toBe(true);
|
|
86
|
+
// Ensure messageId and data wiring is correct
|
|
87
|
+
expect(error.messageId).toBe("missingStory");
|
|
88
|
+
expect(error.data).toEqual({ name: "bar", functionName: "bar" });
|
|
89
|
+
// Suggestions
|
|
90
|
+
expect(Array.isArray(error.suggest)).toBe(true);
|
|
91
|
+
expect(error.suggest.length).toBeGreaterThanOrEqual(1);
|
|
92
|
+
const suggestion = error.suggest[0];
|
|
93
|
+
expect(suggestion.desc).toBe("Add JSDoc @story annotation for function 'bar', e.g., /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */");
|
|
94
|
+
expect(suggestion.fix).toBeDefined();
|
|
95
|
+
});
|
|
47
96
|
});
|
|
48
97
|
});
|
|
@@ -4,9 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
/**
|
|
7
|
-
* Tests for: docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
7
|
+
* Tests for: docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md, docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
8
8
|
* @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
9
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
9
10
|
* @req REQ-BRANCH-DETECTION - Verify require-branch-annotation rule enforces branch annotations
|
|
11
|
+
* @req REQ-ERROR-SPECIFIC - Branch-level missing-annotation error messages are specific and informative
|
|
12
|
+
* @req REQ-ERROR-CONSISTENCY - Branch-level missing-annotation error messages follow shared conventions
|
|
13
|
+
* @req REQ-ERROR-SUGGESTION - Branch-level missing-annotation errors include suggestions when applicable
|
|
10
14
|
*/
|
|
11
15
|
const eslint_1 = require("eslint");
|
|
12
16
|
const require_branch_annotation_1 = __importDefault(require("../../src/rules/require-branch-annotation"));
|
|
@@ -108,17 +108,32 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
108
108
|
{
|
|
109
109
|
name: "[REQ-ANNOTATION-REQUIRED] missing @req on function without JSDoc",
|
|
110
110
|
code: `function baz() {}`,
|
|
111
|
-
errors: [
|
|
111
|
+
errors: [
|
|
112
|
+
{
|
|
113
|
+
messageId: "missingReq",
|
|
114
|
+
data: { name: "baz", functionName: "baz" },
|
|
115
|
+
},
|
|
116
|
+
],
|
|
112
117
|
},
|
|
113
118
|
{
|
|
114
119
|
name: "[REQ-ANNOTATION-REQUIRED] missing @req on function with only @story annotation",
|
|
115
120
|
code: `/**\n * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md\n */\nfunction qux() {}`,
|
|
116
|
-
errors: [
|
|
121
|
+
errors: [
|
|
122
|
+
{
|
|
123
|
+
messageId: "missingReq",
|
|
124
|
+
data: { name: "qux", functionName: "qux" },
|
|
125
|
+
},
|
|
126
|
+
],
|
|
117
127
|
},
|
|
118
128
|
{
|
|
119
129
|
name: "[REQ-TYPESCRIPT-SUPPORT] missing @req on TSDeclareFunction",
|
|
120
130
|
code: `declare function baz(): void;`,
|
|
121
|
-
errors: [
|
|
131
|
+
errors: [
|
|
132
|
+
{
|
|
133
|
+
messageId: "missingReq",
|
|
134
|
+
data: { name: "baz", functionName: "baz" },
|
|
135
|
+
},
|
|
136
|
+
],
|
|
122
137
|
languageOptions: {
|
|
123
138
|
parser: require("@typescript-eslint/parser"),
|
|
124
139
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
@@ -127,7 +142,12 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
127
142
|
{
|
|
128
143
|
name: "[REQ-TYPESCRIPT-SUPPORT] missing @req on TSMethodSignature",
|
|
129
144
|
code: `interface I { method(): void; }`,
|
|
130
|
-
errors: [
|
|
145
|
+
errors: [
|
|
146
|
+
{
|
|
147
|
+
messageId: "missingReq",
|
|
148
|
+
data: { name: "method", functionName: "method" },
|
|
149
|
+
},
|
|
150
|
+
],
|
|
131
151
|
languageOptions: {
|
|
132
152
|
parser: require("@typescript-eslint/parser"),
|
|
133
153
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
@@ -136,27 +156,52 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
136
156
|
{
|
|
137
157
|
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on FunctionExpression assigned to variable",
|
|
138
158
|
code: `const fn = function () {};`,
|
|
139
|
-
errors: [
|
|
159
|
+
errors: [
|
|
160
|
+
{
|
|
161
|
+
messageId: "missingReq",
|
|
162
|
+
data: { name: "fn", functionName: "fn" },
|
|
163
|
+
},
|
|
164
|
+
],
|
|
140
165
|
},
|
|
141
166
|
{
|
|
142
167
|
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on anonymous FunctionExpression (no variable name)",
|
|
143
168
|
code: `(function () {})();`,
|
|
144
|
-
errors: [
|
|
169
|
+
errors: [
|
|
170
|
+
{
|
|
171
|
+
messageId: "missingReq",
|
|
172
|
+
data: { name: "(anonymous)", functionName: "(anonymous)" },
|
|
173
|
+
},
|
|
174
|
+
],
|
|
145
175
|
},
|
|
146
176
|
{
|
|
147
177
|
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on MethodDefinition in class",
|
|
148
178
|
code: `class C {\n m() {}\n}`,
|
|
149
|
-
errors: [
|
|
179
|
+
errors: [
|
|
180
|
+
{
|
|
181
|
+
messageId: "missingReq",
|
|
182
|
+
data: { name: "m", functionName: "m" },
|
|
183
|
+
},
|
|
184
|
+
],
|
|
150
185
|
},
|
|
151
186
|
{
|
|
152
187
|
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on MethodDefinition in object literal",
|
|
153
188
|
code: `const o = { m() {} };`,
|
|
154
|
-
errors: [
|
|
189
|
+
errors: [
|
|
190
|
+
{
|
|
191
|
+
messageId: "missingReq",
|
|
192
|
+
data: { name: "m", functionName: "m" },
|
|
193
|
+
},
|
|
194
|
+
],
|
|
155
195
|
},
|
|
156
196
|
{
|
|
157
197
|
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] missing @req on TS FunctionExpression in variable declarator",
|
|
158
198
|
code: `const fn = function () {};`,
|
|
159
|
-
errors: [
|
|
199
|
+
errors: [
|
|
200
|
+
{
|
|
201
|
+
messageId: "missingReq",
|
|
202
|
+
data: { name: "fn", functionName: "fn" },
|
|
203
|
+
},
|
|
204
|
+
],
|
|
160
205
|
languageOptions: {
|
|
161
206
|
parser: require("@typescript-eslint/parser"),
|
|
162
207
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
@@ -165,7 +210,12 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
165
210
|
{
|
|
166
211
|
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] missing @req on exported TS FunctionExpression in variable declarator",
|
|
167
212
|
code: `export const fn = function () {};`,
|
|
168
|
-
errors: [
|
|
213
|
+
errors: [
|
|
214
|
+
{
|
|
215
|
+
messageId: "missingReq",
|
|
216
|
+
data: { name: "fn", functionName: "fn" },
|
|
217
|
+
},
|
|
218
|
+
],
|
|
169
219
|
languageOptions: {
|
|
170
220
|
parser: require("@typescript-eslint/parser"),
|
|
171
221
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
@@ -175,43 +225,78 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
175
225
|
name: "[REQ-CONFIGURABLE-SCOPE][Story 003.0] FunctionDeclaration still reported when scope only includes FunctionDeclaration",
|
|
176
226
|
code: `function scoped() {}`,
|
|
177
227
|
options: [{ scope: ["FunctionDeclaration"] }],
|
|
178
|
-
errors: [
|
|
228
|
+
errors: [
|
|
229
|
+
{
|
|
230
|
+
messageId: "missingReq",
|
|
231
|
+
data: { name: "scoped", functionName: "scoped" },
|
|
232
|
+
},
|
|
233
|
+
],
|
|
179
234
|
},
|
|
180
235
|
{
|
|
181
236
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported function reported when exportPriority is 'exported'",
|
|
182
237
|
code: `export function exportedFn() {}`,
|
|
183
238
|
options: [{ exportPriority: "exported" }],
|
|
184
|
-
errors: [
|
|
239
|
+
errors: [
|
|
240
|
+
{
|
|
241
|
+
messageId: "missingReq",
|
|
242
|
+
data: { name: "exportedFn", functionName: "exportedFn" },
|
|
243
|
+
},
|
|
244
|
+
],
|
|
185
245
|
},
|
|
186
246
|
{
|
|
187
247
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported function reported when exportPriority is 'non-exported'",
|
|
188
248
|
code: `function nonExported() {}`,
|
|
189
249
|
options: [{ exportPriority: "non-exported" }],
|
|
190
|
-
errors: [
|
|
250
|
+
errors: [
|
|
251
|
+
{
|
|
252
|
+
messageId: "missingReq",
|
|
253
|
+
data: { name: "nonExported", functionName: "nonExported" },
|
|
254
|
+
},
|
|
255
|
+
],
|
|
191
256
|
},
|
|
192
257
|
{
|
|
193
258
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported method reported when exportPriority is 'exported'",
|
|
194
259
|
code: `export class C {\n m() {}\n}`,
|
|
195
|
-
errors: [
|
|
260
|
+
errors: [
|
|
261
|
+
{
|
|
262
|
+
messageId: "missingReq",
|
|
263
|
+
data: { name: "m", functionName: "m" },
|
|
264
|
+
},
|
|
265
|
+
],
|
|
196
266
|
options: [{ exportPriority: "exported" }],
|
|
197
267
|
},
|
|
198
268
|
{
|
|
199
269
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported method reported when exportPriority is 'non-exported'",
|
|
200
270
|
code: `class C {\n m() {}\n}`,
|
|
201
|
-
errors: [
|
|
271
|
+
errors: [
|
|
272
|
+
{
|
|
273
|
+
messageId: "missingReq",
|
|
274
|
+
data: { name: "m", functionName: "m" },
|
|
275
|
+
},
|
|
276
|
+
],
|
|
202
277
|
options: [{ exportPriority: "non-exported" }],
|
|
203
278
|
},
|
|
204
279
|
{
|
|
205
280
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported FunctionExpression reported when exportPriority is 'exported'",
|
|
206
281
|
code: `export const fn = function () {};`,
|
|
207
282
|
options: [{ exportPriority: "exported" }],
|
|
208
|
-
errors: [
|
|
283
|
+
errors: [
|
|
284
|
+
{
|
|
285
|
+
messageId: "missingReq",
|
|
286
|
+
data: { name: "fn", functionName: "fn" },
|
|
287
|
+
},
|
|
288
|
+
],
|
|
209
289
|
},
|
|
210
290
|
{
|
|
211
291
|
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported FunctionExpression reported when exportPriority is 'non-exported'",
|
|
212
292
|
code: `const fn = function () {};`,
|
|
213
293
|
options: [{ exportPriority: "non-exported" }],
|
|
214
|
-
errors: [
|
|
294
|
+
errors: [
|
|
295
|
+
{
|
|
296
|
+
messageId: "missingReq",
|
|
297
|
+
data: { name: "fn", functionName: "fn" },
|
|
298
|
+
},
|
|
299
|
+
],
|
|
215
300
|
},
|
|
216
301
|
],
|
|
217
302
|
});
|
|
@@ -105,6 +105,7 @@ declare function tsDecl(): void;`,
|
|
|
105
105
|
errors: [
|
|
106
106
|
{
|
|
107
107
|
messageId: "missingStory",
|
|
108
|
+
data: { name: "method", functionName: "method" },
|
|
108
109
|
suggestions: [
|
|
109
110
|
{
|
|
110
111
|
desc: `Add JSDoc @story annotation for function 'method', e.g., /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */`,
|
|
@@ -7,6 +7,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
|
|
9
9
|
* @req REQ-FORMAT-SPECIFICATION - Verify valid-annotation-format rule enforces annotation format syntax
|
|
10
|
+
* Tests for: docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
11
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
12
|
+
* @req REQ-ERROR-MESSAGES-CONSISTENT - Verify invalid annotation errors use consistent wording and structure
|
|
13
|
+
* @req REQ-ERROR-MESSAGES-ACTIONABLE - Verify invalid annotation errors provide actionable guidance and examples
|
|
14
|
+
* @req REQ-ERROR-MESSAGES-IDENTIFIERS - Verify invalid annotation errors echo the offending identifier/path in the message
|
|
10
15
|
*/
|
|
11
16
|
const eslint_1 = require("eslint");
|
|
12
17
|
const valid_annotation_format_1 = __importDefault(require("../../src/rules/valid-annotation-format"));
|
|
@@ -7,6 +7,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
9
9
|
* @req REQ-DEEP-PARSE - Verify valid-req-reference rule enforces existing requirement content
|
|
10
|
+
*
|
|
11
|
+
* Additional coverage for error reporting behavior:
|
|
12
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
13
|
+
* @req REQ-ERROR-SPECIFIC - Verify requirement-level errors identify the exact missing requirement
|
|
14
|
+
* @req REQ-ERROR-CONTEXT - Verify requirement-level errors include relevant story path context
|
|
15
|
+
* @req REQ-ERROR-CONSISTENCY - Verify requirement-level error messages are consistent across cases
|
|
10
16
|
*/
|
|
11
17
|
const eslint_1 = require("eslint");
|
|
12
18
|
const valid_req_reference_1 = __importDefault(require("../../src/rules/valid-req-reference"));
|
|
@@ -7,6 +7,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
9
9
|
* @req REQ-FILE-EXISTENCE - Verify valid-story-reference rule enforces existing .story.md files
|
|
10
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
11
|
+
* @req REQ-ERROR-SPECIFIC - Verify file-related error messages are specific about failure causes
|
|
12
|
+
* @req REQ-ERROR-CONTEXT - Verify file-related error messages include contextual information (path, underlying error)
|
|
13
|
+
* @req REQ-ERROR-CONSISTENCY - Verify file-related error messages follow consistent formatting and identifiers
|
|
14
|
+
* @req REQ-ERROR-HANDLING - Verify file-related errors are reported via diagnostics instead of uncaught exceptions
|
|
10
15
|
*/
|
|
11
16
|
const eslint_1 = require("eslint");
|
|
12
17
|
const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-traceability",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "A customizable ESLint plugin that enforces traceability annotations in your code, ensuring each implementation is linked to its requirement or test case.",
|
|
5
5
|
"main": "lib/src/index.js",
|
|
6
6
|
"types": "lib/src/index.d.ts",
|