eslint-plugin-traceability 1.21.1 → 1.22.0
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/CHANGELOG.md +7 -2
- package/README.md +3 -4
- package/lib/src/maintenance/batch.js +0 -2
- package/lib/src/maintenance/cli.js +8 -11
- package/lib/src/maintenance/commands.d.ts +2 -2
- package/lib/src/maintenance/commands.js +2 -3
- package/lib/src/maintenance/detect.js +7 -8
- package/lib/src/maintenance/report.js +2 -3
- package/lib/src/maintenance/storyParser.d.ts +16 -0
- package/lib/src/maintenance/storyParser.js +167 -0
- package/lib/src/maintenance/update.js +0 -1
- package/lib/src/rules/helpers/pattern-validators.d.ts +42 -0
- package/lib/src/rules/helpers/pattern-validators.js +65 -0
- package/lib/src/rules/helpers/prefer-implements-inline.d.ts +16 -0
- package/lib/src/rules/helpers/prefer-implements-inline.js +146 -0
- package/lib/src/rules/helpers/require-story-comment-detection.d.ts +47 -0
- package/lib/src/rules/helpers/require-story-comment-detection.js +141 -0
- package/lib/src/rules/helpers/require-story-core.d.ts +6 -6
- package/lib/src/rules/helpers/require-story-core.js +10 -11
- package/lib/src/rules/helpers/require-story-helpers.d.ts +5 -63
- package/lib/src/rules/helpers/require-story-helpers.js +29 -337
- package/lib/src/rules/helpers/require-story-name-extraction.d.ts +35 -0
- package/lib/src/rules/helpers/require-story-name-extraction.js +107 -0
- package/lib/src/rules/helpers/require-story-node-utils.d.ts +43 -0
- package/lib/src/rules/helpers/require-story-node-utils.js +115 -0
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +11 -3
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +0 -10
- package/lib/src/rules/helpers/valid-annotation-options.js +22 -92
- package/lib/src/rules/helpers/valid-req-reference-helpers.js +0 -1
- package/lib/src/rules/no-redundant-annotation.js +4 -238
- package/lib/src/rules/prefer-implements-annotation.d.ts +12 -0
- package/lib/src/rules/prefer-implements-annotation.js +9 -164
- package/lib/src/rules/require-traceability.d.ts +8 -0
- package/lib/src/rules/require-traceability.js +8 -0
- package/lib/src/utils/annotation-checker.d.ts +3 -2
- package/lib/src/utils/annotation-checker.js +3 -2
- package/lib/src/utils/branch-annotation-catch-helpers.d.ts +22 -0
- package/lib/src/utils/branch-annotation-catch-helpers.js +70 -0
- package/lib/src/utils/branch-annotation-helpers.js +11 -187
- package/lib/src/utils/branch-annotation-if-helpers.d.ts +1 -0
- package/lib/src/utils/branch-annotation-if-helpers.js +59 -0
- package/lib/src/utils/branch-annotation-indent-helpers.d.ts +1 -1
- package/lib/src/utils/branch-annotation-switch-helpers.d.ts +8 -2
- package/lib/src/utils/branch-annotation-switch-helpers.js +10 -4
- package/lib/src/utils/branch-validation.d.ts +9 -0
- package/lib/src/utils/branch-validation.js +58 -0
- package/lib/src/utils/comment-text-helpers.d.ts +31 -0
- package/lib/src/utils/comment-text-helpers.js +54 -0
- package/lib/src/utils/redundancy-detector.d.ts +85 -0
- package/lib/src/utils/redundancy-detector.js +235 -0
- package/lib/tests/maintenance/storyParser.test.d.ts +8 -0
- package/lib/tests/maintenance/storyParser.test.js +505 -0
- package/lib/tests/rules/no-redundant-annotation.test.js +1 -0
- package/lib/tests/rules/require-story-helpers.test.js +3 -2
- package/lib/tests/rules/valid-req-reference.test.js +2 -0
- package/package.json +18 -10
- package/user-docs/api-reference.md +2 -2
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processInlineComments = processInlineComments;
|
|
4
|
+
const valid_annotation_format_internal_1 = require("../helpers/valid-annotation-format-internal");
|
|
5
|
+
const MIN_STORY_TOKENS = 2;
|
|
6
|
+
const MIN_REQ_TOKENS = 2;
|
|
7
|
+
/**
|
|
8
|
+
* Extract the leading whitespace and `//` prefix from a line comment's full
|
|
9
|
+
* source text so that new inline annotations can be inserted with matching
|
|
10
|
+
* indentation and formatting.
|
|
11
|
+
*
|
|
12
|
+
* @story docs/stories/010.3-DEV-MIGRATE-TO-SUPPORTS.story.md
|
|
13
|
+
* @req REQ-MIGRATE-INLINE
|
|
14
|
+
*/
|
|
15
|
+
function getLinePrefixFromText(fullText) {
|
|
16
|
+
const match = fullText.match(/^(\s*\/\/\s*)/);
|
|
17
|
+
return match ? match[1] : "";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Attempt to construct an inline auto-fix that replaces a contiguous
|
|
21
|
+
* sequence of `@story` and `@req` line comments with a single `@supports`
|
|
22
|
+
* annotation while preserving the original comment prefix.
|
|
23
|
+
*
|
|
24
|
+
* @story docs/stories/010.3-DEV-MIGRATE-TO-SUPPORTS.story.md
|
|
25
|
+
* @req REQ-MIGRATE-INLINE
|
|
26
|
+
*/
|
|
27
|
+
function tryBuildInlineAutoFix(context, comments, storyIndex, reqIndices) {
|
|
28
|
+
const sourceCode = context.getSourceCode();
|
|
29
|
+
const storyComment = comments[storyIndex];
|
|
30
|
+
const storyNormalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(storyComment.value || "");
|
|
31
|
+
if (!storyNormalized || !/^@story\b/.test(storyNormalized)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const storyParts = storyNormalized.split(/\s+/);
|
|
35
|
+
if (storyParts.length !== MIN_STORY_TOKENS) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const storyPath = storyParts[1];
|
|
39
|
+
const reqIds = [];
|
|
40
|
+
for (const idx of reqIndices) {
|
|
41
|
+
const reqComment = comments[idx];
|
|
42
|
+
const reqNormalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(reqComment.value || "");
|
|
43
|
+
if (!reqNormalized || !/^@req\b/.test(reqNormalized)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const reqParts = reqNormalized.split(/\s+/);
|
|
47
|
+
if (reqParts.length !== MIN_REQ_TOKENS) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
reqIds.push(reqParts[1]);
|
|
51
|
+
}
|
|
52
|
+
if (!reqIds.length) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const fullText = sourceCode.text.slice(storyComment.range[0], storyComment.range[1]);
|
|
56
|
+
const linePrefix = getLinePrefixFromText(fullText);
|
|
57
|
+
const implAnnotation = `@supports ${storyPath} ${reqIds.join(" ")}`;
|
|
58
|
+
const implLine = `${linePrefix}${implAnnotation}`;
|
|
59
|
+
const start = storyComment.range[0];
|
|
60
|
+
const end = comments[reqIndices[reqIndices.length - 1]].range[1];
|
|
61
|
+
return (fixer) => fixer.replaceTextRange([start, end], implLine);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Coordinate detection and optional migration of a single inline `@story`
|
|
65
|
+
* comment and its following `@req` comments, reporting diagnostics and
|
|
66
|
+
* scheduling auto-fixes where safe.
|
|
67
|
+
*
|
|
68
|
+
* @story docs/stories/010.3-DEV-MIGRATE-TO-SUPPORTS.story.md
|
|
69
|
+
* @req REQ-MIGRATE-INLINE
|
|
70
|
+
*/
|
|
71
|
+
function collectReqIndicesAfterStory(group, startIndex) {
|
|
72
|
+
const n = group.length;
|
|
73
|
+
const reqIndices = [];
|
|
74
|
+
let j = startIndex + 1;
|
|
75
|
+
while (j < n) {
|
|
76
|
+
const next = group[j];
|
|
77
|
+
const nextNormalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(next.value || "");
|
|
78
|
+
if (!nextNormalized || /^@supports\b/.test(nextNormalized)) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (/^@req\b/.test(nextNormalized)) {
|
|
82
|
+
reqIndices.push(j);
|
|
83
|
+
j += 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
return { reqIndices, nextIndex: j };
|
|
89
|
+
}
|
|
90
|
+
function handleInlineStorySequence(context, group, startIndex) {
|
|
91
|
+
const current = group[startIndex];
|
|
92
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(current.value || "");
|
|
93
|
+
if (!normalized || !/^@story\b/.test(normalized)) {
|
|
94
|
+
return startIndex + 1;
|
|
95
|
+
}
|
|
96
|
+
const { reqIndices, nextIndex } = collectReqIndicesAfterStory(group, startIndex);
|
|
97
|
+
if (reqIndices.length === 0) {
|
|
98
|
+
return startIndex + 1;
|
|
99
|
+
}
|
|
100
|
+
const fix = tryBuildInlineAutoFix(context, group, startIndex, reqIndices);
|
|
101
|
+
context.report({
|
|
102
|
+
node: current,
|
|
103
|
+
messageId: "preferImplements",
|
|
104
|
+
fix: fix || undefined,
|
|
105
|
+
});
|
|
106
|
+
return nextIndex;
|
|
107
|
+
}
|
|
108
|
+
function advanceInlineGroupIndex(context, group, i) {
|
|
109
|
+
if (i >= group.length) {
|
|
110
|
+
return i;
|
|
111
|
+
}
|
|
112
|
+
return handleInlineStorySequence(context, group, i);
|
|
113
|
+
}
|
|
114
|
+
function processInlineGroup(context, group) {
|
|
115
|
+
let i = 0;
|
|
116
|
+
while (i < group.length) {
|
|
117
|
+
i = advanceInlineGroupIndex(context, group, i);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Scan sequences of Line comments for inline legacy story and requirement patterns
|
|
122
|
+
* and report diagnostics with optional auto-fixes.
|
|
123
|
+
*/
|
|
124
|
+
function processInlineComments(context, lineComments) {
|
|
125
|
+
if (!lineComments.length)
|
|
126
|
+
return;
|
|
127
|
+
// Group by contiguous line numbers
|
|
128
|
+
let group = [lineComments[0]];
|
|
129
|
+
const flushGroup = () => {
|
|
130
|
+
processInlineGroup(context, group);
|
|
131
|
+
group = [];
|
|
132
|
+
};
|
|
133
|
+
for (let idx = 1; idx < lineComments.length; idx++) {
|
|
134
|
+
const prev = lineComments[idx - 1];
|
|
135
|
+
const curr = lineComments[idx];
|
|
136
|
+
if (curr.loc.start.line === prev.loc.start.line + 1 &&
|
|
137
|
+
curr.loc.start.column === prev.loc.start.column) {
|
|
138
|
+
group.push(curr);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
flushGroup();
|
|
142
|
+
group.push(curr);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
flushGroup();
|
|
146
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check whether the JSDoc associated with node contains `@story`
|
|
3
|
+
*
|
|
4
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
6
|
+
*/
|
|
7
|
+
export declare function jsdocHasStory(sourceCode: any, node: any): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Check whether comments returned by sourceCode.getCommentsBefore contain `@story`
|
|
10
|
+
*
|
|
11
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
12
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
13
|
+
*/
|
|
14
|
+
export declare function commentsBeforeHasStory(sourceCode: any, node: any): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Check whether leadingComments attached to the node contain `@story`
|
|
17
|
+
*
|
|
18
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
19
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
20
|
+
*/
|
|
21
|
+
export declare function leadingCommentsHasStory(node: any): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Check if `@story` annotation already present in JSDoc or preceding comments.
|
|
24
|
+
* Consolidates a variety of heuristics through smaller helpers.
|
|
25
|
+
*
|
|
26
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
27
|
+
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
28
|
+
*/
|
|
29
|
+
export declare function hasStoryAnnotation(sourceCode: any, node: any): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Placement-aware story detection helper used by core reporting.
|
|
32
|
+
*
|
|
33
|
+
* When annotationPlacement is "inside" and the node supports inside-brace
|
|
34
|
+
* semantics, this helper only treats annotations found on the first
|
|
35
|
+
* comment-only lines inside the function or method body as satisfying the
|
|
36
|
+
* requirement. JSDoc and before-function comments are intentionally ignored so
|
|
37
|
+
* that misplaced annotations are reported as violations under the inside
|
|
38
|
+
* standard.
|
|
39
|
+
*
|
|
40
|
+
* For nodes that do not support inside placement (such as TS declarations,
|
|
41
|
+
* signature-only nodes, or functions without block bodies), this helper
|
|
42
|
+
* delegates to the existing hasStoryAnnotation heuristics so that they
|
|
43
|
+
* continue to rely on before-function placement.
|
|
44
|
+
*
|
|
45
|
+
* @supports docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md REQ-ALL-BLOCK-TYPES REQ-INSIDE-BRACE-PLACEMENT REQ-PLACEMENT-CONFIG
|
|
46
|
+
*/
|
|
47
|
+
export declare function hasStoryAnnotationWithPlacement(sourceCode: any, node: any, annotationPlacement: "before" | "inside"): boolean;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsdocHasStory = jsdocHasStory;
|
|
4
|
+
exports.commentsBeforeHasStory = commentsBeforeHasStory;
|
|
5
|
+
exports.leadingCommentsHasStory = leadingCommentsHasStory;
|
|
6
|
+
exports.hasStoryAnnotation = hasStoryAnnotation;
|
|
7
|
+
exports.hasStoryAnnotationWithPlacement = hasStoryAnnotationWithPlacement;
|
|
8
|
+
/**
|
|
9
|
+
* Comment detection utilities for require-story rule
|
|
10
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
11
|
+
* @req REQ-ANNOTATION-REQUIRED - File-level header for comment detection utilities
|
|
12
|
+
*/
|
|
13
|
+
const require_story_io_1 = require("./require-story-io");
|
|
14
|
+
const function_annotation_helpers_1 = require("../../utils/function-annotation-helpers");
|
|
15
|
+
const require_story_node_utils_1 = require("./require-story-node-utils");
|
|
16
|
+
/**
|
|
17
|
+
* Check whether the JSDoc associated with node contains `@story`
|
|
18
|
+
*
|
|
19
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
20
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
21
|
+
*/
|
|
22
|
+
function jsdocHasStory(sourceCode, node) {
|
|
23
|
+
if (typeof sourceCode?.getJSDocComment !== "function") {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const jsdoc = sourceCode.getJSDocComment(node);
|
|
27
|
+
return !!(jsdoc &&
|
|
28
|
+
typeof jsdoc.value === "string" &&
|
|
29
|
+
jsdoc.value.includes("@story"));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check whether comments returned by sourceCode.getCommentsBefore contain `@story`
|
|
33
|
+
*
|
|
34
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
35
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
36
|
+
*/
|
|
37
|
+
function commentsBeforeHasStory(sourceCode, node) {
|
|
38
|
+
if (typeof sourceCode?.getCommentsBefore !== "function") {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const commentsBefore = sourceCode.getCommentsBefore(node) || [];
|
|
42
|
+
return (Array.isArray(commentsBefore) &&
|
|
43
|
+
commentsBefore.some((c) => typeof c.value === "string" && c.value.includes("@story")));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check whether leadingComments attached to the node contain `@story`
|
|
47
|
+
*
|
|
48
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
49
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
50
|
+
*/
|
|
51
|
+
function leadingCommentsHasStory(node) {
|
|
52
|
+
const leadingComments = (node && node.leadingComments) || [];
|
|
53
|
+
return (Array.isArray(leadingComments) &&
|
|
54
|
+
leadingComments.some((c) => typeof c.value === "string" && c.value.includes("@story")));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if `@story` annotation already present in JSDoc or preceding comments.
|
|
58
|
+
* Consolidates a variety of heuristics through smaller helpers.
|
|
59
|
+
*
|
|
60
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
61
|
+
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
62
|
+
*/
|
|
63
|
+
function hasStoryAnnotation(sourceCode, node) {
|
|
64
|
+
try {
|
|
65
|
+
// Direct, node-local checks always apply first.
|
|
66
|
+
if (jsdocHasStory(sourceCode, node)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (commentsBeforeHasStory(sourceCode, node)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (leadingCommentsHasStory(node)) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (!(0, require_story_node_utils_1.isNestedFunction)(node) && (0, require_story_io_1.linesBeforeHasStory)(sourceCode, node)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const canInherit = (0, require_story_node_utils_1.isNestedFunction)(node) && (0, require_story_node_utils_1.isEffectivelyAnonymousFunction)(node);
|
|
79
|
+
// Only nodes that are allowed to inherit annotations (e.g., nested anonymous
|
|
80
|
+
// callbacks) may treat parent-chain comments or broad fallback text as
|
|
81
|
+
// satisfying the annotation requirement.
|
|
82
|
+
if (canInherit && (0, require_story_io_1.parentChainHasStory)(sourceCode, node)) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (canInherit && (0, require_story_io_1.fallbackTextBeforeHasStory)(sourceCode, node)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
if (canInherit) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (process.env.TRACEABILITY_DEBUG === "1") {
|
|
94
|
+
console.error("[traceability] hasStoryAnnotation failed for node", error?.message ?? error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Placement-aware story detection helper used by core reporting.
|
|
101
|
+
*
|
|
102
|
+
* When annotationPlacement is "inside" and the node supports inside-brace
|
|
103
|
+
* semantics, this helper only treats annotations found on the first
|
|
104
|
+
* comment-only lines inside the function or method body as satisfying the
|
|
105
|
+
* requirement. JSDoc and before-function comments are intentionally ignored so
|
|
106
|
+
* that misplaced annotations are reported as violations under the inside
|
|
107
|
+
* standard.
|
|
108
|
+
*
|
|
109
|
+
* For nodes that do not support inside placement (such as TS declarations,
|
|
110
|
+
* signature-only nodes, or functions without block bodies), this helper
|
|
111
|
+
* delegates to the existing hasStoryAnnotation heuristics so that they
|
|
112
|
+
* continue to rely on before-function placement.
|
|
113
|
+
*
|
|
114
|
+
* @supports docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md REQ-ALL-BLOCK-TYPES REQ-INSIDE-BRACE-PLACEMENT REQ-PLACEMENT-CONFIG
|
|
115
|
+
*/
|
|
116
|
+
function hasStoryAnnotationWithPlacement(sourceCode, node, annotationPlacement) {
|
|
117
|
+
// Backward-compatible default: use existing heuristics when placement is
|
|
118
|
+
// "before" or when the function does not support inside-brace semantics.
|
|
119
|
+
if (annotationPlacement !== "inside" ||
|
|
120
|
+
!(0, function_annotation_helpers_1.supportsInsidePlacementForFunction)(node)) {
|
|
121
|
+
return hasStoryAnnotation(sourceCode, node);
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const insideText = (0, function_annotation_helpers_1.getFunctionInsideBodyCommentText)(sourceCode, node);
|
|
125
|
+
if (typeof insideText === "string" &&
|
|
126
|
+
(insideText.includes("@story") || insideText.includes("@supports"))) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (process.env.TRACEABILITY_DEBUG === "1") {
|
|
132
|
+
// Debug logging only when explicitly enabled for troubleshooting helper failures.
|
|
133
|
+
console.error("[traceability] hasStoryAnnotationWithPlacement failed for node", error?.message ?? error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// In inside-placement mode for block-bodied functions and methods we
|
|
137
|
+
// intentionally do not fall back to before-function heuristics; callers
|
|
138
|
+
// should treat this as a missing annotation so that misplaced comments are
|
|
139
|
+
// reported as violations.
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Create a fixer function that inserts a
|
|
2
|
+
* Create a fixer function that inserts a `@story` annotation before the target node.
|
|
3
3
|
* This fixer is responsible for placing the annotation immediately before the
|
|
4
4
|
* resolved target node in the source code.
|
|
5
5
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
6
|
-
* @req REQ-AUTOFIX - Provide automatic fix function for missing
|
|
6
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing `@story` annotations
|
|
7
7
|
*/
|
|
8
8
|
export declare function createAddStoryFix(target: any, annotationTemplate: string): (fixer: any) => any;
|
|
9
9
|
/**
|
|
10
10
|
* Create a fixer function for class method annotations.
|
|
11
|
-
* This helper ensures that the
|
|
11
|
+
* This helper ensures that the `@story` annotation is inserted with appropriate
|
|
12
12
|
* indentation and placement before a class method declaration.
|
|
13
13
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
14
14
|
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
15
15
|
*/
|
|
16
16
|
export declare function createMethodFix(node: any, annotationTemplate: string): (fixer: any) => any;
|
|
17
17
|
/**
|
|
18
|
-
* Default set of node types to check for missing
|
|
18
|
+
* Default set of node types to check for missing `@story` annotations.
|
|
19
19
|
* This default scope covers common function-like declarations used in typical
|
|
20
20
|
* TypeScript and JavaScript codebases.
|
|
21
21
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -57,7 +57,7 @@ type ReportDeps = {
|
|
|
57
57
|
hasStoryAnnotationWithPlacement?: (_sourceCode: any, _node: any, _placement: "before" | "inside") => boolean;
|
|
58
58
|
};
|
|
59
59
|
/**
|
|
60
|
-
* Core helper to report a missing
|
|
60
|
+
* Core helper to report a missing `@story` annotation for a function-like node.
|
|
61
61
|
* This reporting utility delegates behavior to injected dependencies so that
|
|
62
62
|
* higher-level helpers can stay small while sharing error-reporting logic.
|
|
63
63
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -73,7 +73,7 @@ export declare function coreReportMissing(deps: ReportDeps, context: Rule.RuleCo
|
|
|
73
73
|
options?: CoreReportOptions;
|
|
74
74
|
}): void;
|
|
75
75
|
/**
|
|
76
|
-
* Core helper to report a missing
|
|
76
|
+
* Core helper to report a missing `@story` annotation for a method-like node.
|
|
77
77
|
* This method-focused reporting utility uses injected dependencies while
|
|
78
78
|
* keeping this module centered on core error-reporting behavior.
|
|
79
79
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -5,7 +5,6 @@ exports.createAddStoryFix = createAddStoryFix;
|
|
|
5
5
|
exports.createMethodFix = createMethodFix;
|
|
6
6
|
exports.coreReportMissing = coreReportMissing;
|
|
7
7
|
exports.coreReportMethod = coreReportMethod;
|
|
8
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
9
8
|
/**
|
|
10
9
|
* Compute the insertion start offset for inserting annotations before a node.
|
|
11
10
|
* This helper ensures we insert before any export wrapper when present, while
|
|
@@ -33,18 +32,18 @@ function getInsertionStart(candidate) {
|
|
|
33
32
|
return 0;
|
|
34
33
|
}
|
|
35
34
|
/**
|
|
36
|
-
* Create a fixer function that inserts a
|
|
35
|
+
* Create a fixer function that inserts a `@story` annotation before the target node.
|
|
37
36
|
* This fixer is responsible for placing the annotation immediately before the
|
|
38
37
|
* resolved target node in the source code.
|
|
39
38
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
40
|
-
* @req REQ-AUTOFIX - Provide automatic fix function for missing
|
|
39
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing `@story` annotations
|
|
41
40
|
*/
|
|
42
41
|
function createAddStoryFix(target, annotationTemplate) {
|
|
43
42
|
/**
|
|
44
|
-
* Fixer that inserts a
|
|
43
|
+
* Fixer that inserts a `@story` annotation before the target node.
|
|
45
44
|
* This inner fixer is used by ESLint to apply the actual code modification.
|
|
46
45
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
47
|
-
* @req REQ-AUTOFIX - Provide automatic fix function for missing
|
|
46
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing `@story` annotations
|
|
48
47
|
*/
|
|
49
48
|
function addStoryFixer(fixer) {
|
|
50
49
|
const start = getInsertionStart(target);
|
|
@@ -54,14 +53,14 @@ function createAddStoryFix(target, annotationTemplate) {
|
|
|
54
53
|
}
|
|
55
54
|
/**
|
|
56
55
|
* Create a fixer function for class method annotations.
|
|
57
|
-
* This helper ensures that the
|
|
56
|
+
* This helper ensures that the `@story` annotation is inserted with appropriate
|
|
58
57
|
* indentation and placement before a class method declaration.
|
|
59
58
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
60
59
|
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
61
60
|
*/
|
|
62
61
|
function createMethodFix(node, annotationTemplate) {
|
|
63
62
|
/**
|
|
64
|
-
* Fixer that inserts a
|
|
63
|
+
* Fixer that inserts a `@story` annotation before a method node.
|
|
65
64
|
* This inner fixer handles inserting the annotation with method-friendly
|
|
66
65
|
* formatting and spacing.
|
|
67
66
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -74,7 +73,7 @@ function createMethodFix(node, annotationTemplate) {
|
|
|
74
73
|
return methodFixer;
|
|
75
74
|
}
|
|
76
75
|
/**
|
|
77
|
-
* Default set of node types to check for missing
|
|
76
|
+
* Default set of node types to check for missing `@story` annotations.
|
|
78
77
|
* This default scope covers common function-like declarations used in typical
|
|
79
78
|
* TypeScript and JavaScript codebases.
|
|
80
79
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -118,7 +117,7 @@ function withSafeReporting(label, fn) {
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
/**
|
|
121
|
-
* Build the shared ESLint report descriptor for a missing
|
|
120
|
+
* Build the shared ESLint report descriptor for a missing story annotation.
|
|
122
121
|
* This keeps the core helpers focused on computing names, targets, and
|
|
123
122
|
* templates while centralizing the diagnostic wiring.
|
|
124
123
|
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ERROR-SPECIFIC
|
|
@@ -145,7 +144,7 @@ function resolveAnnotationPlacement(options) {
|
|
|
145
144
|
return raw === "inside" || raw === "before" ? raw : "before";
|
|
146
145
|
}
|
|
147
146
|
/**
|
|
148
|
-
* Core helper to report a missing
|
|
147
|
+
* Core helper to report a missing `@story` annotation for a function-like node.
|
|
149
148
|
* This reporting utility delegates behavior to injected dependencies so that
|
|
150
149
|
* higher-level helpers can stay small while sharing error-reporting logic.
|
|
151
150
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -184,7 +183,7 @@ function coreReportMissing(deps, context, sourceCode, config) {
|
|
|
184
183
|
});
|
|
185
184
|
}
|
|
186
185
|
/**
|
|
187
|
-
* Core helper to report a missing
|
|
186
|
+
* Core helper to report a missing `@story` annotation for a method-like node.
|
|
188
187
|
* This method-focused reporting utility uses injected dependencies while
|
|
189
188
|
* keeping this module centered on core error-reporting behavior.
|
|
190
189
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { Rule } from "eslint";
|
|
11
11
|
import { linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory } from "./require-story-io";
|
|
12
|
-
import { getNodeName } from "./require-story-utils";
|
|
13
12
|
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, STORY_PATH } from "./require-story-core";
|
|
14
13
|
import { type CallbackExclusionOptions } from "./test-callback-exclusion";
|
|
14
|
+
import { extractName } from "./require-story-name-extraction";
|
|
15
|
+
import { isExportedNode, resolveTargetNode } from "./require-story-node-utils";
|
|
16
|
+
import { jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, hasStoryAnnotationWithPlacement } from "./require-story-comment-detection";
|
|
15
17
|
/**
|
|
16
18
|
* Shared configuration helpers
|
|
17
19
|
*/
|
|
@@ -23,67 +25,6 @@ interface ReportOptions extends CallbackExclusionOptions {
|
|
|
23
25
|
/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
|
|
24
26
|
declare function getAnnotationTemplate(override?: string, _options?: CallbackExclusionOptions): string;
|
|
25
27
|
declare function shouldApplyAutoFix(autoFix: boolean | undefined, _options?: CallbackExclusionOptions): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Determine if a node is in an export declaration
|
|
28
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
29
|
-
* @req REQ-ANNOTATION-REQUIRED - Check node ancestry to find export declarations
|
|
30
|
-
*/
|
|
31
|
-
declare function isExportedNode(node: any): boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Check whether the JSDoc associated with node contains @story
|
|
34
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
35
|
-
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
36
|
-
*/
|
|
37
|
-
declare function jsdocHasStory(sourceCode: any, node: any): boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Check whether comments returned by sourceCode.getCommentsBefore contain @story
|
|
40
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
41
|
-
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
42
|
-
*/
|
|
43
|
-
declare function commentsBeforeHasStory(sourceCode: any, node: any): boolean;
|
|
44
|
-
/**
|
|
45
|
-
* Check whether leadingComments attached to the node contain @story
|
|
46
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
47
|
-
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
48
|
-
*/
|
|
49
|
-
declare function leadingCommentsHasStory(node: any): boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Check if @story annotation already present in JSDoc or preceding comments
|
|
52
|
-
* Consolidates a variety of heuristics through smaller helpers.
|
|
53
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
54
|
-
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
55
|
-
*/
|
|
56
|
-
declare function hasStoryAnnotation(sourceCode: any, node: any): boolean;
|
|
57
|
-
/**
|
|
58
|
-
* Placement-aware story detection helper used by core reporting.
|
|
59
|
-
*
|
|
60
|
-
* When annotationPlacement is "inside" and the node supports inside-brace
|
|
61
|
-
* semantics, this helper only treats annotations found on the first
|
|
62
|
-
* comment-only lines inside the function or method body as satisfying the
|
|
63
|
-
* requirement. JSDoc and before-function comments are intentionally ignored so
|
|
64
|
-
* that misplaced annotations are reported as violations under the inside
|
|
65
|
-
* standard.
|
|
66
|
-
*
|
|
67
|
-
* For nodes that do not support inside placement (such as TS declarations,
|
|
68
|
-
* signature-only nodes, or functions without block bodies), this helper
|
|
69
|
-
* delegates to the existing hasStoryAnnotation heuristics so that they
|
|
70
|
-
* continue to rely on before-function placement.
|
|
71
|
-
*
|
|
72
|
-
* @supports docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md REQ-ALL-BLOCK-TYPES REQ-INSIDE-BRACE-PLACEMENT REQ-PLACEMENT-CONFIG
|
|
73
|
-
*/
|
|
74
|
-
declare function hasStoryAnnotationWithPlacement(sourceCode: any, node: any, annotationPlacement: "before" | "inside"): boolean;
|
|
75
|
-
/**
|
|
76
|
-
* Determine AST node where annotation should be inserted
|
|
77
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
78
|
-
* @req REQ-ANNOTATION-REQUIRED - Determine correct insertion target for annotation
|
|
79
|
-
*/
|
|
80
|
-
declare function resolveTargetNode(sourceCode: any, node: any): any;
|
|
81
|
-
/**
|
|
82
|
-
* Small utility to walk the node and its parents to extract an Identifier or key name.
|
|
83
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
84
|
-
* @req REQ-ANNOTATION-REQUIRED - Walk node and parents to find Identifier/Key name
|
|
85
|
-
*/
|
|
86
|
-
declare function extractName(node: any): string;
|
|
87
28
|
/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
|
|
88
29
|
declare function shouldProcessNode(node: any, scope: string[], exportPriority?: string, options?: CallbackExclusionOptions): boolean;
|
|
89
30
|
/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
|
|
@@ -100,7 +41,8 @@ declare function reportMethod(context: Rule.RuleContext, sourceCode: any, config
|
|
|
100
41
|
}): void;
|
|
101
42
|
/**
|
|
102
43
|
* Explicit exports for require-story-annotation helpers.
|
|
44
|
+
*
|
|
103
45
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
104
46
|
* @req REQ-ANNOTATION-REQUIRED
|
|
105
47
|
*/
|
|
106
|
-
export { STORY_PATH, getAnnotationTemplate, shouldApplyAutoFix, isExportedNode, jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, hasStoryAnnotationWithPlacement,
|
|
48
|
+
export { STORY_PATH, getAnnotationTemplate, shouldApplyAutoFix, isExportedNode, jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, hasStoryAnnotationWithPlacement, extractName, resolveTargetNode, shouldProcessNode, DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory, reportMissing, reportMethod, };
|