eslint-plugin-traceability 1.11.0 → 1.11.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/CHANGELOG.md +3 -4
- package/README.md +1 -1
- package/lib/src/index.d.ts +12 -1
- package/lib/src/index.js +43 -6
- package/lib/src/maintenance/commands.js +2 -3
- package/lib/src/maintenance/flags.js +111 -25
- package/lib/src/maintenance/update.js +1 -14
- package/lib/src/rules/helpers/require-story-core.d.ts +67 -0
- package/lib/src/rules/helpers/require-story-core.js +142 -23
- package/lib/src/rules/helpers/require-story-helpers.d.ts +9 -88
- package/lib/src/rules/helpers/require-story-helpers.js +118 -166
- package/lib/src/rules/helpers/require-story-io.js +51 -31
- package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +12 -13
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +21 -16
- package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +29 -3
- package/lib/src/rules/helpers/valid-annotation-format-validators.js +29 -3
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +3 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +64 -21
- package/lib/src/rules/helpers/valid-annotation-utils.d.ts +3 -3
- package/lib/src/rules/helpers/valid-annotation-utils.js +10 -10
- package/lib/src/rules/helpers/valid-req-reference-helpers.d.ts +11 -0
- package/lib/src/rules/helpers/valid-req-reference-helpers.js +362 -0
- package/lib/src/rules/prefer-implements-annotation.js +7 -7
- package/lib/src/rules/require-story-annotation.d.ts +2 -0
- package/lib/src/rules/require-story-annotation.js +1 -1
- package/lib/src/rules/valid-req-reference.d.ts +4 -0
- package/lib/src/rules/valid-req-reference.js +5 -349
- package/lib/src/rules/valid-story-reference.d.ts +1 -1
- package/lib/src/rules/valid-story-reference.js +17 -10
- package/lib/src/utils/annotation-checker.js +31 -7
- package/lib/src/utils/branch-annotation-helpers.d.ts +2 -2
- package/lib/src/utils/branch-annotation-helpers.js +4 -4
- package/lib/src/utils/reqAnnotationDetection.js +36 -22
- package/lib/tests/cli-error-handling.test.js +2 -1
- package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
- package/lib/tests/config/eslint-config-validation.test.js +81 -0
- package/lib/tests/config/flat-config-presets-integration.test.js +1 -3
- package/lib/tests/config/require-story-annotation-config.test.d.ts +9 -0
- package/lib/tests/config/require-story-annotation-config.test.js +9 -0
- package/lib/tests/fixtures/stale/example.js +1 -1
- package/lib/tests/fixtures/update/example.js +1 -1
- package/lib/tests/integration/cli-integration.test.js +9 -1
- package/lib/tests/integration/dogfooding-validation.test.d.ts +1 -0
- package/lib/tests/integration/dogfooding-validation.test.js +94 -0
- package/lib/tests/maintenance/batch.test.js +1 -0
- package/lib/tests/maintenance/cli.test.js +38 -0
- package/lib/tests/maintenance/detect-isolated.test.js +6 -5
- package/lib/tests/maintenance/detect.test.js +1 -0
- package/lib/tests/maintenance/index.test.js +1 -0
- package/lib/tests/maintenance/report.test.js +1 -0
- package/lib/tests/maintenance/update-isolated.test.js +1 -0
- package/lib/tests/maintenance/update.test.js +1 -0
- package/lib/tests/perf/maintenance-cli-large-workspace.test.js +18 -0
- package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +1 -0
- package/lib/tests/perf/require-branch-annotation-large-file.test.js +67 -0
- package/lib/tests/plugin-default-export-and-configs.test.js +2 -0
- package/lib/tests/plugin-setup-error.test.d.ts +1 -0
- package/lib/tests/plugin-setup-error.test.js +1 -0
- package/lib/tests/plugin-setup.test.js +12 -1
- package/lib/tests/rules/auto-fix-behavior-008.test.js +16 -0
- package/lib/tests/rules/error-reporting.test.js +1 -0
- package/lib/tests/rules/prefer-implements-annotation.test.js +8 -0
- package/lib/tests/rules/require-branch-annotation.test.js +34 -0
- package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-core.autofix.test.js +1 -0
- package/lib/tests/rules/require-story-core.test.js +1 -0
- package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-helpers-edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-helpers.test.js +4 -3
- package/lib/tests/rules/require-story-io-behavior.test.d.ts +1 -0
- package/lib/tests/rules/require-story-io-behavior.test.js +1 -0
- package/lib/tests/rules/require-story-io.edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-io.edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-visitors-edgecases.test.js +1 -0
- package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +8 -0
- package/lib/tests/rules/valid-annotation-format-internal.test.js +47 -0
- package/lib/tests/rules/valid-story-reference.test.js +2 -0
- package/lib/tests/utils/annotation-checker.test.js +2 -1
- package/lib/tests/utils/branch-annotation-helpers.test.js +2 -1
- package/package.json +2 -2
- package/user-docs/api-reference.md +115 -8
- package/user-docs/examples.md +1 -1
- package/user-docs/migration-guide.md +35 -2
|
@@ -10,66 +10,38 @@
|
|
|
10
10
|
import type { Rule } from "eslint";
|
|
11
11
|
import { linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory } from "./require-story-io";
|
|
12
12
|
import { getNodeName } from "./require-story-utils";
|
|
13
|
-
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES } from "./require-story-core";
|
|
13
|
+
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, STORY_PATH } from "./require-story-core";
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*/
|
|
17
|
-
declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
18
|
-
/**
|
|
19
|
-
* Derive the annotation template, optionally using an override.
|
|
20
|
-
* When override is a non-empty string, its trimmed value is used.
|
|
21
|
-
* Otherwise, the default template is returned.
|
|
15
|
+
* Shared configuration helpers
|
|
22
16
|
*/
|
|
17
|
+
interface ReportOptions {
|
|
18
|
+
annotationTemplateOverride?: string;
|
|
19
|
+
autoFixToggle?: boolean;
|
|
20
|
+
}
|
|
23
21
|
declare function getAnnotationTemplate(override?: string): string;
|
|
24
|
-
/**
|
|
25
|
-
* Determine whether auto-fix should be applied.
|
|
26
|
-
* Explicit false disables auto-fix; all other values enable it.
|
|
27
|
-
*/
|
|
28
22
|
declare function shouldApplyAutoFix(autoFix: boolean | undefined): boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Number of physical source lines to inspect before a node when searching for @story text
|
|
31
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
32
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for lookback lines with named constant
|
|
33
|
-
*/
|
|
34
|
-
declare const LOOKBACK_LINES = 4;
|
|
35
|
-
/**
|
|
36
|
-
* Window (in characters) to inspect before a node as a fallback when searching for @story text
|
|
37
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
38
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for fallback text window with named constant
|
|
39
|
-
*/
|
|
40
|
-
declare const FALLBACK_WINDOW = 800;
|
|
41
23
|
/**
|
|
42
24
|
* Determine if a node is in an export declaration
|
|
43
25
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
44
26
|
* @req REQ-ANNOTATION-REQUIRED - Check node ancestry to find export declarations
|
|
45
|
-
* @param {any} node - AST node to check for export ancestry
|
|
46
|
-
* @returns {boolean} true if node is within an export declaration
|
|
47
27
|
*/
|
|
48
28
|
declare function isExportedNode(node: any): boolean;
|
|
49
29
|
/**
|
|
50
30
|
* Check whether the JSDoc associated with node contains @story
|
|
51
31
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
52
32
|
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
53
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
54
|
-
* @param {any} node - AST node to inspect
|
|
55
|
-
* @returns {boolean} true if JSDoc contains @story
|
|
56
33
|
*/
|
|
57
34
|
declare function jsdocHasStory(sourceCode: any, node: any): boolean;
|
|
58
35
|
/**
|
|
59
36
|
* Check whether comments returned by sourceCode.getCommentsBefore contain @story
|
|
60
37
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
61
38
|
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
62
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
63
|
-
* @param {any} node - AST node to inspect
|
|
64
|
-
* @returns {boolean} true if any preceding comment contains @story
|
|
65
39
|
*/
|
|
66
40
|
declare function commentsBeforeHasStory(sourceCode: any, node: any): boolean;
|
|
67
41
|
/**
|
|
68
42
|
* Check whether leadingComments attached to the node contain @story
|
|
69
43
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
70
44
|
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
71
|
-
* @param {any} node - AST node to inspect
|
|
72
|
-
* @returns {boolean} true if any leading comment contains @story
|
|
73
45
|
*/
|
|
74
46
|
declare function leadingCommentsHasStory(node: any): boolean;
|
|
75
47
|
/**
|
|
@@ -77,85 +49,34 @@ declare function leadingCommentsHasStory(node: any): boolean;
|
|
|
77
49
|
* Consolidates a variety of heuristics through smaller helpers.
|
|
78
50
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
79
51
|
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
80
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
81
|
-
* @param {any} node - AST node to inspect for existing annotations
|
|
82
|
-
* @returns {boolean} true if @story annotation already present
|
|
83
52
|
*/
|
|
84
53
|
declare function hasStoryAnnotation(sourceCode: any, node: any): boolean;
|
|
85
54
|
/**
|
|
86
55
|
* Determine AST node where annotation should be inserted
|
|
87
56
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
88
57
|
* @req REQ-ANNOTATION-REQUIRED - Determine correct insertion target for annotation
|
|
89
|
-
* @param {any} sourceCode - ESLint sourceCode object (unused but kept for parity)
|
|
90
|
-
* @param {any} node - function-like AST node to resolve target for
|
|
91
|
-
* @returns {any} AST node that should receive the annotation
|
|
92
58
|
*/
|
|
93
59
|
declare function resolveTargetNode(sourceCode: any, node: any): any;
|
|
94
60
|
/**
|
|
95
61
|
* Small utility to walk the node and its parents to extract an Identifier or key name.
|
|
96
|
-
* Walks up the parent chain and inspects common properties (id, key, name, Identifier nodes).
|
|
97
62
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
98
63
|
* @req REQ-ANNOTATION-REQUIRED - Walk node and parents to find Identifier/Key name
|
|
99
|
-
* @param {any} node - AST node to extract a name from
|
|
100
|
-
* @returns {string} extracted name or "(anonymous)" when no name found
|
|
101
64
|
*/
|
|
102
65
|
declare function extractName(node: any): string;
|
|
103
|
-
/**
|
|
104
|
-
* Check if this node is within scope and matches exportPriority
|
|
105
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
106
|
-
* @req REQ-ANNOTATION-REQUIRED - Determine whether a node should be processed by rule
|
|
107
|
-
* @param {any} node - AST node to evaluate
|
|
108
|
-
* @param {string[]} scope - allowed node types
|
|
109
|
-
* @param {string} [exportPriority='all'] - 'all' | 'exported' | 'non-exported' (default: 'all')
|
|
110
|
-
* @returns {boolean} whether node should be processed
|
|
111
|
-
*/
|
|
112
66
|
declare function shouldProcessNode(node: any, scope: string[], exportPriority?: string): boolean;
|
|
113
|
-
interface ReportOptions {
|
|
114
|
-
annotationTemplateOverride?: string;
|
|
115
|
-
autoFixToggle?: boolean;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Report a missing @story annotation for a function-like node
|
|
119
|
-
* Provides a suggestion to add the annotation.
|
|
120
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
121
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
122
|
-
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
123
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing annotations with suggestion
|
|
124
|
-
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing annotations while preserving suggestions
|
|
125
|
-
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
126
|
-
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
127
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
128
|
-
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
129
|
-
*/
|
|
130
67
|
declare function reportMissing(context: Rule.RuleContext, sourceCode: any, config: {
|
|
131
68
|
node: any;
|
|
132
69
|
target?: any;
|
|
133
70
|
options?: ReportOptions;
|
|
134
71
|
}): void;
|
|
135
|
-
/**
|
|
136
|
-
* Report a missing @story annotation for a method-like node
|
|
137
|
-
* Provides a suggestion to update the method/interface with the annotation.
|
|
138
|
-
* The error data payload uses both name and functionName for consistent, specific error context.
|
|
139
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
140
|
-
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
141
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
142
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
143
|
-
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing method/interface annotations while preserving suggestions
|
|
144
|
-
* @req REQ-ERROR-SPECIFIC - Method error reports must include both name and functionName in the data payload for specific function context
|
|
145
|
-
* @req REQ-ERROR-LOCATION - Method error reports must use the method name node to anchor error location
|
|
146
|
-
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
147
|
-
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
148
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
149
|
-
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
150
|
-
*/
|
|
151
72
|
declare function reportMethod(context: Rule.RuleContext, sourceCode: any, config: {
|
|
152
73
|
node: any;
|
|
153
74
|
target?: any;
|
|
154
75
|
options?: ReportOptions;
|
|
155
76
|
}): void;
|
|
156
77
|
/**
|
|
157
|
-
* Explicit exports for require-story-annotation
|
|
78
|
+
* Explicit exports for require-story-annotation helpers.
|
|
158
79
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
159
|
-
* @req REQ-ANNOTATION-REQUIRED
|
|
80
|
+
* @req REQ-ANNOTATION-REQUIRED
|
|
160
81
|
*/
|
|
161
|
-
export { STORY_PATH, getAnnotationTemplate, shouldApplyAutoFix,
|
|
82
|
+
export { STORY_PATH, getAnnotationTemplate, shouldApplyAutoFix, isExportedNode, jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, getNodeName, extractName, resolveTargetNode, shouldProcessNode, DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory, reportMissing, reportMethod, };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fallbackTextBeforeHasStory = exports.parentChainHasStory = exports.linesBeforeHasStory = exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = exports.getNodeName = exports.
|
|
3
|
+
exports.fallbackTextBeforeHasStory = exports.parentChainHasStory = exports.linesBeforeHasStory = exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = exports.getNodeName = exports.STORY_PATH = void 0;
|
|
4
4
|
exports.getAnnotationTemplate = getAnnotationTemplate;
|
|
5
5
|
exports.shouldApplyAutoFix = shouldApplyAutoFix;
|
|
6
6
|
exports.isExportedNode = isExportedNode;
|
|
@@ -22,26 +22,13 @@ Object.defineProperty(exports, "getNodeName", { enumerable: true, get: function
|
|
|
22
22
|
const require_story_core_1 = require("./require-story-core");
|
|
23
23
|
Object.defineProperty(exports, "DEFAULT_SCOPE", { enumerable: true, get: function () { return require_story_core_1.DEFAULT_SCOPE; } });
|
|
24
24
|
Object.defineProperty(exports, "EXPORT_PRIORITY_VALUES", { enumerable: true, get: function () { return require_story_core_1.EXPORT_PRIORITY_VALUES; } });
|
|
25
|
-
|
|
26
|
-
* Path to the story file for annotations
|
|
27
|
-
*/
|
|
28
|
-
const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
29
|
-
exports.STORY_PATH = STORY_PATH;
|
|
30
|
-
/**
|
|
31
|
-
* Derive the annotation template, optionally using an override.
|
|
32
|
-
* When override is a non-empty string, its trimmed value is used.
|
|
33
|
-
* Otherwise, the default template is returned.
|
|
34
|
-
*/
|
|
25
|
+
Object.defineProperty(exports, "STORY_PATH", { enumerable: true, get: function () { return require_story_core_1.STORY_PATH; } });
|
|
35
26
|
function getAnnotationTemplate(override) {
|
|
36
27
|
if (typeof override === "string" && override.trim().length > 0) {
|
|
37
28
|
return override.trim();
|
|
38
29
|
}
|
|
39
|
-
return `/** @story ${STORY_PATH} */`;
|
|
30
|
+
return `/** @story ${require_story_core_1.STORY_PATH} */`;
|
|
40
31
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Determine whether auto-fix should be applied.
|
|
43
|
-
* Explicit false disables auto-fix; all other values enable it.
|
|
44
|
-
*/
|
|
45
32
|
function shouldApplyAutoFix(autoFix) {
|
|
46
33
|
if (autoFix === false) {
|
|
47
34
|
return false;
|
|
@@ -49,30 +36,21 @@ function shouldApplyAutoFix(autoFix) {
|
|
|
49
36
|
return true;
|
|
50
37
|
}
|
|
51
38
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for lookback lines with named constant
|
|
55
|
-
*/
|
|
56
|
-
const LOOKBACK_LINES = 4;
|
|
57
|
-
exports.LOOKBACK_LINES = LOOKBACK_LINES;
|
|
58
|
-
/**
|
|
59
|
-
* Window (in characters) to inspect before a node as a fallback when searching for @story text
|
|
60
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
61
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for fallback text window with named constant
|
|
39
|
+
* Build the effective annotation template and autofix toggle
|
|
40
|
+
* from the provided report options.
|
|
62
41
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
42
|
+
function buildTemplateConfig(options) {
|
|
43
|
+
const effectiveTemplate = getAnnotationTemplate(options?.annotationTemplateOverride);
|
|
44
|
+
const allowFix = shouldApplyAutoFix(options?.autoFixToggle);
|
|
45
|
+
return { effectiveTemplate, allowFix };
|
|
46
|
+
}
|
|
65
47
|
/**
|
|
66
48
|
* Determine if a node is in an export declaration
|
|
67
49
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
68
50
|
* @req REQ-ANNOTATION-REQUIRED - Check node ancestry to find export declarations
|
|
69
|
-
* @param {any} node - AST node to check for export ancestry
|
|
70
|
-
* @returns {boolean} true if node is within an export declaration
|
|
71
51
|
*/
|
|
72
52
|
function isExportedNode(node) {
|
|
73
53
|
let p = node.parent;
|
|
74
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
75
|
-
// @req REQ-ANNOTATION-REQUIRED - Walk parent chain to find Export declarations
|
|
76
54
|
while (p) {
|
|
77
55
|
if (p.type === "ExportNamedDeclaration" ||
|
|
78
56
|
p.type === "ExportDefaultDeclaration") {
|
|
@@ -86,9 +64,6 @@ function isExportedNode(node) {
|
|
|
86
64
|
* Check whether the JSDoc associated with node contains @story
|
|
87
65
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
88
66
|
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
89
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
90
|
-
* @param {any} node - AST node to inspect
|
|
91
|
-
* @returns {boolean} true if JSDoc contains @story
|
|
92
67
|
*/
|
|
93
68
|
function jsdocHasStory(sourceCode, node) {
|
|
94
69
|
if (typeof sourceCode?.getJSDocComment !== "function") {
|
|
@@ -103,9 +78,6 @@ function jsdocHasStory(sourceCode, node) {
|
|
|
103
78
|
* Check whether comments returned by sourceCode.getCommentsBefore contain @story
|
|
104
79
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
105
80
|
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
106
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
107
|
-
* @param {any} node - AST node to inspect
|
|
108
|
-
* @returns {boolean} true if any preceding comment contains @story
|
|
109
81
|
*/
|
|
110
82
|
function commentsBeforeHasStory(sourceCode, node) {
|
|
111
83
|
if (typeof sourceCode?.getCommentsBefore !== "function") {
|
|
@@ -119,8 +91,6 @@ function commentsBeforeHasStory(sourceCode, node) {
|
|
|
119
91
|
* Check whether leadingComments attached to the node contain @story
|
|
120
92
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
121
93
|
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
122
|
-
* @param {any} node - AST node to inspect
|
|
123
|
-
* @returns {boolean} true if any leading comment contains @story
|
|
124
94
|
*/
|
|
125
95
|
function leadingCommentsHasStory(node) {
|
|
126
96
|
const leadingComments = (node && node.leadingComments) || [];
|
|
@@ -132,9 +102,6 @@ function leadingCommentsHasStory(node) {
|
|
|
132
102
|
* Consolidates a variety of heuristics through smaller helpers.
|
|
133
103
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
134
104
|
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
135
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
136
|
-
* @param {any} node - AST node to inspect for existing annotations
|
|
137
|
-
* @returns {boolean} true if @story annotation already present
|
|
138
105
|
*/
|
|
139
106
|
function hasStoryAnnotation(sourceCode, node) {
|
|
140
107
|
try {
|
|
@@ -147,7 +114,7 @@ function hasStoryAnnotation(sourceCode, node) {
|
|
|
147
114
|
if (leadingCommentsHasStory(node)) {
|
|
148
115
|
return true;
|
|
149
116
|
}
|
|
150
|
-
if ((0, require_story_io_1.linesBeforeHasStory)(sourceCode, node
|
|
117
|
+
if ((0, require_story_io_1.linesBeforeHasStory)(sourceCode, node)) {
|
|
151
118
|
return true;
|
|
152
119
|
}
|
|
153
120
|
if ((0, require_story_io_1.parentChainHasStory)(sourceCode, node)) {
|
|
@@ -157,8 +124,10 @@ function hasStoryAnnotation(sourceCode, node) {
|
|
|
157
124
|
return true;
|
|
158
125
|
}
|
|
159
126
|
}
|
|
160
|
-
catch {
|
|
161
|
-
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (process.env.TRACEABILITY_DEBUG === "1") {
|
|
129
|
+
console.error("[traceability] hasStoryAnnotation failed for node", error?.message ?? error);
|
|
130
|
+
}
|
|
162
131
|
}
|
|
163
132
|
return false;
|
|
164
133
|
}
|
|
@@ -166,9 +135,6 @@ function hasStoryAnnotation(sourceCode, node) {
|
|
|
166
135
|
* Determine AST node where annotation should be inserted
|
|
167
136
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
168
137
|
* @req REQ-ANNOTATION-REQUIRED - Determine correct insertion target for annotation
|
|
169
|
-
* @param {any} sourceCode - ESLint sourceCode object (unused but kept for parity)
|
|
170
|
-
* @param {any} node - function-like AST node to resolve target for
|
|
171
|
-
* @returns {any} AST node that should receive the annotation
|
|
172
138
|
*/
|
|
173
139
|
function resolveTargetNode(sourceCode, node) {
|
|
174
140
|
if (node.type === "TSMethodSignature") {
|
|
@@ -194,54 +160,72 @@ function resolveTargetNode(sourceCode, node) {
|
|
|
194
160
|
}
|
|
195
161
|
return node;
|
|
196
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Extract a direct Identifier name when available on the given node.
|
|
165
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
166
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract direct Identifier-based names from nodes
|
|
167
|
+
*/
|
|
168
|
+
function getDirectIdentifierName(node) {
|
|
169
|
+
if (node &&
|
|
170
|
+
node.type === "Identifier" &&
|
|
171
|
+
typeof node.name === "string" &&
|
|
172
|
+
node.name.length > 0) {
|
|
173
|
+
return node.name;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Normalize container nodes that expose names via id/key properties.
|
|
179
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
180
|
+
* @req REQ-ANNOTATION-REQUIRED - Normalize container id/key-based names into a single helper
|
|
181
|
+
*/
|
|
182
|
+
function getContainerKeyOrIdName(node) {
|
|
183
|
+
if (!node) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
if (node.id) {
|
|
187
|
+
const idName = (0, require_story_utils_1.getNodeName)(node.id);
|
|
188
|
+
if (typeof idName === "string" && idName.length > 0) {
|
|
189
|
+
return idName;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (node.key) {
|
|
193
|
+
const keyName = (0, require_story_utils_1.getNodeName)(node.key);
|
|
194
|
+
if (typeof keyName === "string" && keyName.length > 0) {
|
|
195
|
+
return keyName;
|
|
196
|
+
}
|
|
197
|
+
if (node.key.type === "Literal" &&
|
|
198
|
+
typeof node.key.value === "string" &&
|
|
199
|
+
node.key.value.length > 0) {
|
|
200
|
+
return node.key.value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
197
205
|
/**
|
|
198
206
|
* Small utility to walk the node and its parents to extract an Identifier or key name.
|
|
199
|
-
* Walks up the parent chain and inspects common properties (id, key, name, Identifier nodes).
|
|
200
207
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
201
208
|
* @req REQ-ANNOTATION-REQUIRED - Walk node and parents to find Identifier/Key name
|
|
202
|
-
* @param {any} node - AST node to extract a name from
|
|
203
|
-
* @returns {string} extracted name or "(anonymous)" when no name found
|
|
204
209
|
*/
|
|
205
210
|
function extractName(node) {
|
|
206
|
-
let
|
|
207
|
-
while (
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
return
|
|
211
|
+
let current = node;
|
|
212
|
+
while (current) {
|
|
213
|
+
const directIdentifierName = getDirectIdentifierName(current);
|
|
214
|
+
if (directIdentifierName) {
|
|
215
|
+
return directIdentifierName;
|
|
211
216
|
}
|
|
212
|
-
|
|
213
|
-
if (
|
|
214
|
-
return
|
|
217
|
+
const containerName = getContainerKeyOrIdName(current);
|
|
218
|
+
if (containerName) {
|
|
219
|
+
return containerName;
|
|
215
220
|
}
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
typeof n.key.name === "string") {
|
|
220
|
-
return n.key.name;
|
|
221
|
+
const directName = current.name;
|
|
222
|
+
if (typeof directName === "string" && directName.length > 0) {
|
|
223
|
+
return directName;
|
|
221
224
|
}
|
|
222
|
-
|
|
223
|
-
if (typeof n.name === "string" && n.name.length > 0) {
|
|
224
|
-
return n.name;
|
|
225
|
-
}
|
|
226
|
-
// computed keys may have an Identifier inside
|
|
227
|
-
if (n.key &&
|
|
228
|
-
n.key.type === "Literal" &&
|
|
229
|
-
typeof n.key.value === "string") {
|
|
230
|
-
return n.key.value;
|
|
231
|
-
}
|
|
232
|
-
n = n.parent;
|
|
225
|
+
current = current.parent;
|
|
233
226
|
}
|
|
234
227
|
return "(anonymous)";
|
|
235
228
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Check if this node is within scope and matches exportPriority
|
|
238
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
239
|
-
* @req REQ-ANNOTATION-REQUIRED - Determine whether a node should be processed by rule
|
|
240
|
-
* @param {any} node - AST node to evaluate
|
|
241
|
-
* @param {string[]} scope - allowed node types
|
|
242
|
-
* @param {string} [exportPriority='all'] - 'all' | 'exported' | 'non-exported' (default: 'all')
|
|
243
|
-
* @returns {boolean} whether node should be processed
|
|
244
|
-
*/
|
|
245
229
|
function shouldProcessNode(node, scope, exportPriority = "all") {
|
|
246
230
|
if (!scope.includes(node.type)) {
|
|
247
231
|
return false;
|
|
@@ -256,94 +240,62 @@ function shouldProcessNode(node, scope, exportPriority = "all") {
|
|
|
256
240
|
return true;
|
|
257
241
|
}
|
|
258
242
|
/**
|
|
259
|
-
*
|
|
260
|
-
* Provides a suggestion to add the annotation.
|
|
243
|
+
* Resolve the effective function name to report for a node.
|
|
261
244
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
262
|
-
* @
|
|
263
|
-
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
264
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing annotations with suggestion
|
|
265
|
-
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing annotations while preserving suggestions
|
|
266
|
-
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
267
|
-
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
268
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
269
|
-
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
245
|
+
* @req REQ-ANNOTATION-REQUIRED - Centralize reported function name resolution
|
|
270
246
|
*/
|
|
271
|
-
function
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const effectiveTemplate = getAnnotationTemplate(options.annotationTemplateOverride);
|
|
284
|
-
const allowFix = shouldApplyAutoFix(options.autoFixToggle);
|
|
285
|
-
context.report({
|
|
286
|
-
node: nameNode,
|
|
287
|
-
messageId: "missingStory",
|
|
288
|
-
data: { name, functionName: name },
|
|
289
|
-
fix: allowFix
|
|
290
|
-
? (0, require_story_core_1.createAddStoryFix)(resolvedTarget, effectiveTemplate)
|
|
291
|
-
: undefined,
|
|
292
|
-
suggest: [
|
|
293
|
-
{
|
|
294
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
295
|
-
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget, effectiveTemplate),
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
});
|
|
247
|
+
function getReportedFunctionName(node) {
|
|
248
|
+
const candidate = node && (node.id || node.key) ? node.id || node.key : node;
|
|
249
|
+
return extractName(candidate);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Determine the most appropriate AST node to anchor error location for a report.
|
|
253
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
254
|
+
* @req REQ-ANNOTATION-REQUIRED - Normalize name node selection for error reporting
|
|
255
|
+
*/
|
|
256
|
+
function getNameNodeForReport(node) {
|
|
257
|
+
if (node?.id?.type === "Identifier") {
|
|
258
|
+
return node.id;
|
|
299
259
|
}
|
|
300
|
-
|
|
301
|
-
|
|
260
|
+
if (node?.key?.type === "Identifier") {
|
|
261
|
+
return node.key;
|
|
302
262
|
}
|
|
263
|
+
return node;
|
|
303
264
|
}
|
|
304
265
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
* The error data payload uses both name and functionName for consistent, specific error context.
|
|
266
|
+
* Resolve the node that should receive the @story annotation,
|
|
267
|
+
* respecting an explicitly passed target when provided.
|
|
308
268
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
309
|
-
* @
|
|
310
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
311
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
312
|
-
* @req REQ-AUTOFIX-MISSING - Provide autofix for missing method/interface annotations while preserving suggestions
|
|
313
|
-
* @req REQ-ERROR-SPECIFIC - Method error reports must include both name and functionName in the data payload for specific function context
|
|
314
|
-
* @req REQ-ERROR-LOCATION - Method error reports must use the method name node to anchor error location
|
|
315
|
-
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
316
|
-
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
317
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
318
|
-
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
269
|
+
* @req REQ-ANNOTATION-REQUIRED - Centralize annotation target node resolution
|
|
319
270
|
*/
|
|
271
|
+
function resolveAnnotationTargetNode(sourceCode, node, passedTarget) {
|
|
272
|
+
return passedTarget ?? resolveTargetNode(sourceCode, node);
|
|
273
|
+
}
|
|
274
|
+
function reportMissing(context, sourceCode, config) {
|
|
275
|
+
(0, require_story_core_1.coreReportMissing)({
|
|
276
|
+
hasStoryAnnotation,
|
|
277
|
+
getReportedFunctionName,
|
|
278
|
+
resolveAnnotationTargetNode,
|
|
279
|
+
getNameNodeForReport,
|
|
280
|
+
buildTemplateConfig,
|
|
281
|
+
extractName,
|
|
282
|
+
getAnnotationTemplate,
|
|
283
|
+
shouldApplyAutoFix,
|
|
284
|
+
createAddStoryFix: require_story_core_1.createAddStoryFix,
|
|
285
|
+
createMethodFix: require_story_core_1.createMethodFix,
|
|
286
|
+
}, context, sourceCode, config);
|
|
287
|
+
}
|
|
320
288
|
function reportMethod(context, sourceCode, config) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
messageId: "missingStory",
|
|
334
|
-
data: { name, functionName: name },
|
|
335
|
-
fix: allowFix
|
|
336
|
-
? (0, require_story_core_1.createMethodFix)(resolvedTarget, effectiveTemplate)
|
|
337
|
-
: undefined,
|
|
338
|
-
suggest: [
|
|
339
|
-
{
|
|
340
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
341
|
-
fix: (0, require_story_core_1.createMethodFix)(resolvedTarget, effectiveTemplate),
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
catch {
|
|
347
|
-
/* noop */
|
|
348
|
-
}
|
|
289
|
+
(0, require_story_core_1.coreReportMethod)({
|
|
290
|
+
hasStoryAnnotation,
|
|
291
|
+
getReportedFunctionName,
|
|
292
|
+
resolveAnnotationTargetNode,
|
|
293
|
+
getNameNodeForReport,
|
|
294
|
+
buildTemplateConfig,
|
|
295
|
+
extractName,
|
|
296
|
+
getAnnotationTemplate,
|
|
297
|
+
shouldApplyAutoFix,
|
|
298
|
+
createAddStoryFix: require_story_core_1.createAddStoryFix,
|
|
299
|
+
createMethodFix: require_story_core_1.createMethodFix,
|
|
300
|
+
}, context, sourceCode, config);
|
|
349
301
|
}
|
|
@@ -133,42 +133,32 @@ function parentChainHasStory(sourceCode, node) {
|
|
|
133
133
|
return false;
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
136
|
+
* Safely compute the starting range index for fallback text scanning.
|
|
137
|
+
* Centralizes guards around sourceCode.getText and node.range structure.
|
|
138
138
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
139
|
-
* @
|
|
140
|
-
* @req REQ-ANNOTATION-REQUIRED - Provide fallback textual inspection when other heuristics fail
|
|
141
|
-
* @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @supports annotations as satisfying story presence in fallback checks
|
|
139
|
+
* @req REQ-ANNOTATION-REQUIRED - Centralize guards for fallback range computation
|
|
142
140
|
*/
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// @req REQ-ANNOTATION-REQUIRED - Avoid throwing when source text or range metadata cannot be read
|
|
147
|
-
if (typeof sourceCode?.getText !== "function" ||
|
|
148
|
-
!Array.isArray((node && node.range) || [])) {
|
|
149
|
-
return false;
|
|
141
|
+
function getFallbackRangeStart(sourceCode, node) {
|
|
142
|
+
if (typeof sourceCode?.getText !== "function") {
|
|
143
|
+
return null;
|
|
150
144
|
}
|
|
151
|
-
const range = node.range;
|
|
152
|
-
// Guard against malformed range values that cannot provide a numeric start index for slicing.
|
|
153
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
154
|
-
// @req REQ-ANNOTATION-REQUIRED - Validate node range structure before computing fallback window
|
|
145
|
+
const range = (node && node.range) || null;
|
|
155
146
|
if (!Array.isArray(range) || typeof range[0] !== "number") {
|
|
156
|
-
return
|
|
147
|
+
return null;
|
|
157
148
|
}
|
|
149
|
+
return range[0];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Safely slice a bounded fallback text window immediately preceding the node start index.
|
|
153
|
+
* Restricts scanning to a fixed-size window and treats IO/slicing failures as non-fatal.
|
|
154
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
155
|
+
* @req REQ-ANNOTATION-REQUIRED - Restrict fallback text scanning to a safe, fixed-size window and handle failures gracefully
|
|
156
|
+
*/
|
|
157
|
+
function getFallbackTextWindow(sourceCode, nodeStartIndex) {
|
|
158
|
+
const start = Math.max(0, nodeStartIndex - exports.FALLBACK_WINDOW);
|
|
158
159
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// @req REQ-ANNOTATION-REQUIRED - Restrict fallback text scanning to a safe, fixed-size window
|
|
162
|
-
const start = Math.max(0, range[0] - exports.FALLBACK_WINDOW);
|
|
163
|
-
const textBefore = sourceCode.getText().slice(start, range[0]);
|
|
164
|
-
// Detect any @story or @supports marker that appears within the bounded fallback window.
|
|
165
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
166
|
-
// @req REQ-ANNOTATION-REQUIRED - Recognize story annotations discovered via fallback text scanning
|
|
167
|
-
// @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Recognize @supports annotations discovered via fallback text scanning
|
|
168
|
-
if (typeof textBefore === "string" &&
|
|
169
|
-
(textBefore.includes("@story") || textBefore.includes("@supports"))) {
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
160
|
+
const textBefore = sourceCode.getText().slice(start, nodeStartIndex);
|
|
161
|
+
return typeof textBefore === "string" ? textBefore : null;
|
|
172
162
|
}
|
|
173
163
|
catch {
|
|
174
164
|
/*
|
|
@@ -176,6 +166,36 @@ function fallbackTextBeforeHasStory(sourceCode, node) {
|
|
|
176
166
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
177
167
|
* @req REQ-ANNOTATION-REQUIRED - Treat fallback text inspection failures as "no annotation" instead of raising
|
|
178
168
|
*/
|
|
169
|
+
return null;
|
|
179
170
|
}
|
|
180
|
-
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Detect whether the provided fallback text window contains a story marker.
|
|
174
|
+
* Recognizes both @story and @supports annotations in the inspected text.
|
|
175
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
176
|
+
* @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
|
|
177
|
+
* @req REQ-ANNOTATION-REQUIRED - Recognize story annotations discovered via fallback text scanning
|
|
178
|
+
* @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Recognize @supports annotations discovered via fallback text scanning
|
|
179
|
+
*/
|
|
180
|
+
function fallbackTextHasMarker(textBefore) {
|
|
181
|
+
if (typeof textBefore !== "string") {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return textBefore.includes("@story") || textBefore.includes("@supports");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Fallback: inspect text immediately preceding the node in sourceCode.getText to find @story
|
|
188
|
+
* Also accepts @supports annotations as satisfying story presence for this rule.
|
|
189
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
190
|
+
* @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
|
|
191
|
+
* @req REQ-ANNOTATION-REQUIRED - Provide fallback textual inspection when other heuristics fail
|
|
192
|
+
* @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @supports annotations as satisfying story presence in fallback checks
|
|
193
|
+
*/
|
|
194
|
+
function fallbackTextBeforeHasStory(sourceCode, node) {
|
|
195
|
+
const nodeStartIndex = getFallbackRangeStart(sourceCode, node);
|
|
196
|
+
if (nodeStartIndex === null) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
const textBefore = getFallbackTextWindow(sourceCode, nodeStartIndex);
|
|
200
|
+
return fallbackTextHasMarker(textBefore);
|
|
181
201
|
}
|