eslint-plugin-traceability 1.10.1 → 1.11.1
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 +2 -2
- package/README.md +3 -2
- package/lib/src/maintenance/cli.js +12 -12
- package/lib/src/maintenance/detect.js +19 -19
- package/lib/src/maintenance/flags.js +111 -25
- package/lib/src/rules/helpers/require-story-core.d.ts +55 -9
- package/lib/src/rules/helpers/require-story-core.js +85 -62
- package/lib/src/rules/helpers/require-story-helpers.d.ts +27 -48
- package/lib/src/rules/helpers/require-story-helpers.js +154 -116
- package/lib/src/rules/helpers/require-story-io.js +51 -31
- package/lib/src/rules/helpers/require-story-visitors.js +47 -6
- package/lib/src/rules/helpers/valid-annotation-format-validators.js +5 -1
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +9 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +67 -20
- package/lib/src/rules/helpers/valid-annotation-utils.js +31 -31
- package/lib/src/rules/helpers/valid-story-reference-helpers.js +19 -19
- package/lib/src/rules/prefer-implements-annotation.js +29 -1
- package/lib/src/rules/require-story-annotation.js +15 -0
- package/lib/src/rules/require-test-traceability.js +1 -6
- package/lib/src/utils/annotation-checker.js +32 -8
- package/lib/src/utils/reqAnnotationDetection.js +36 -22
- package/lib/tests/cli-error-handling.test.js +1 -0
- package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
- package/lib/tests/config/eslint-config-validation.test.js +8 -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/integration/cli-integration.test.js +9 -1
- package/lib/tests/maintenance/batch.test.js +1 -0
- package/lib/tests/maintenance/cli.test.js +1 -0
- package/lib/tests/maintenance/detect-isolated.test.js +1 -0
- 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.d.ts +1 -0
- package/lib/tests/perf/maintenance-cli-large-workspace.test.js +130 -0
- package/lib/tests/perf/maintenance-large-workspace.test.d.ts +1 -0
- package/lib/tests/perf/maintenance-large-workspace.test.js +149 -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 +1 -1
- package/lib/tests/rules/auto-fix-behavior-008.test.js +39 -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 +2 -0
- package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-core.autofix.test.js +10 -3
- package/lib/tests/rules/require-story-core.test.js +14 -7
- package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-helpers-edgecases.test.js +2 -1
- package/lib/tests/rules/require-story-helpers.test.js +18 -11
- 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-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/lib/tests/utils/require-story-core-test-helpers.d.ts +1 -1
- package/lib/tests/utils/require-story-core-test-helpers.js +16 -16
- package/lib/tests/utils/temp-dir-helpers.js +1 -1
- package/package.json +9 -2
- package/user-docs/api-reference.md +123 -12
- package/user-docs/examples.md +41 -0
- package/user-docs/migration-guide.md +36 -3
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = void 0;
|
|
3
|
+
exports.EXPORT_PRIORITY_VALUES = exports.STORY_PATH = exports.DEFAULT_SCOPE = void 0;
|
|
4
4
|
exports.createAddStoryFix = createAddStoryFix;
|
|
5
5
|
exports.createMethodFix = createMethodFix;
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
8
|
-
const require_story_helpers_1 = require("./require-story-helpers");
|
|
6
|
+
exports.coreReportMissing = coreReportMissing;
|
|
7
|
+
exports.coreReportMethod = coreReportMethod;
|
|
9
8
|
/**
|
|
10
9
|
* Create a fixer function that inserts a @story annotation before the target node.
|
|
11
10
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
12
11
|
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
13
12
|
*/
|
|
14
|
-
function createAddStoryFix(target) {
|
|
13
|
+
function createAddStoryFix(target, annotationTemplate) {
|
|
15
14
|
/**
|
|
16
15
|
* Fixer that inserts a @story annotation before the target node.
|
|
17
16
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -29,7 +28,7 @@ function createAddStoryFix(target) {
|
|
|
29
28
|
? target.range[0]
|
|
30
29
|
: 0
|
|
31
30
|
: 0;
|
|
32
|
-
return fixer.insertTextBeforeRange([start, start], `${
|
|
31
|
+
return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n`);
|
|
33
32
|
}
|
|
34
33
|
return addStoryFixer;
|
|
35
34
|
}
|
|
@@ -38,7 +37,7 @@ function createAddStoryFix(target) {
|
|
|
38
37
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
39
38
|
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
40
39
|
*/
|
|
41
|
-
function createMethodFix(node) {
|
|
40
|
+
function createMethodFix(node, annotationTemplate) {
|
|
42
41
|
/**
|
|
43
42
|
* Fixer that inserts a @story annotation before a method node.
|
|
44
43
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -56,7 +55,7 @@ function createMethodFix(node) {
|
|
|
56
55
|
? node.range[0]
|
|
57
56
|
: 0
|
|
58
57
|
: 0;
|
|
59
|
-
return fixer.insertTextBeforeRange([start, start], `${
|
|
58
|
+
return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n `);
|
|
60
59
|
}
|
|
61
60
|
return methodFixer;
|
|
62
61
|
}
|
|
@@ -72,71 +71,95 @@ exports.DEFAULT_SCOPE = [
|
|
|
72
71
|
"TSMethodSignature",
|
|
73
72
|
"TSDeclareFunction",
|
|
74
73
|
];
|
|
74
|
+
/**
|
|
75
|
+
* Path to the story file for function-annotation helpers.
|
|
76
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
77
|
+
* @req REQ-ANNOTATION-REQUIRED - Provide a single source of truth for the canonical story path used by helper modules
|
|
78
|
+
*/
|
|
79
|
+
exports.STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
75
80
|
/**
|
|
76
81
|
* Allowed values for export priority option.
|
|
77
82
|
*/
|
|
78
83
|
exports.EXPORT_PRIORITY_VALUES = ["all", "exported", "non-exported"];
|
|
79
84
|
/**
|
|
80
|
-
*
|
|
85
|
+
* Core helper to report a missing @story annotation for a function-like node.
|
|
86
|
+
* Delegates actual behavior to injected dependencies so higher-level helpers
|
|
87
|
+
* can remain small while sharing error-reporting behavior.
|
|
81
88
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
82
|
-
* @
|
|
89
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
90
|
+
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
91
|
+
* @req REQ-ANNOTATION-REQUIRED
|
|
92
|
+
* @req REQ-AUTOFIX-MISSING
|
|
93
|
+
* @req REQ-ERROR-SPECIFIC
|
|
83
94
|
*/
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
90
|
-
* @req REQ-AUTOFIX - Only attempt to read JSDoc comment if source supports it
|
|
91
|
-
*/
|
|
92
|
-
if (typeof sc?.getJSDocComment === "function") {
|
|
93
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
94
|
-
// @req REQ-ANNOTATION-REQUIRED - Skip reporting when JSDoc already contains @story
|
|
95
|
-
const js = sc.getJSDocComment(node);
|
|
96
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
97
|
-
// @req REQ-ANNOTATION-REQUIRED - If @story present in JSDoc, do not report
|
|
98
|
-
if (js && typeof js.value === "string" && js.value.includes("@story"))
|
|
95
|
+
function coreReportMissing(deps, context, sourceCode, config) {
|
|
96
|
+
const { node, target: passedTarget, options = {} } = config;
|
|
97
|
+
try {
|
|
98
|
+
if (deps.hasStoryAnnotation(sourceCode, node)) {
|
|
99
99
|
return;
|
|
100
|
+
}
|
|
101
|
+
const functionName = deps.getReportedFunctionName(node);
|
|
102
|
+
const resolvedTarget = deps.resolveAnnotationTargetNode(sourceCode, node, passedTarget);
|
|
103
|
+
const nameNode = deps.getNameNodeForReport(node);
|
|
104
|
+
const { effectiveTemplate, allowFix } = deps.buildTemplateConfig(options);
|
|
105
|
+
const name = functionName;
|
|
106
|
+
context.report({
|
|
107
|
+
node: nameNode,
|
|
108
|
+
messageId: "missingStory",
|
|
109
|
+
data: { name, functionName: name },
|
|
110
|
+
fix: allowFix
|
|
111
|
+
? deps.createAddStoryFix(resolvedTarget, effectiveTemplate)
|
|
112
|
+
: undefined,
|
|
113
|
+
suggest: [
|
|
114
|
+
{
|
|
115
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
116
|
+
fix: deps.createAddStoryFix(resolvedTarget, effectiveTemplate),
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
/* noop */
|
|
100
123
|
}
|
|
101
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
102
|
-
// @req REQ-ANNOTATION-REQUIRED - Resolve function name for reporting, default to <unknown>
|
|
103
|
-
const name = node && node.id && node.id.name ? node.id.name : "<unknown>";
|
|
104
|
-
const resolvedTarget = target ?? node;
|
|
105
|
-
const nameNode = node && node.id && node.id.type === "Identifier"
|
|
106
|
-
? node.id
|
|
107
|
-
: node && node.key && node.key.type === "Identifier"
|
|
108
|
-
? node.key
|
|
109
|
-
: node;
|
|
110
|
-
context.report({
|
|
111
|
-
node: nameNode,
|
|
112
|
-
messageId: "missingStory",
|
|
113
|
-
data: { name },
|
|
114
|
-
suggest: [
|
|
115
|
-
{
|
|
116
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${require_story_helpers_1.ANNOTATION}`,
|
|
117
|
-
fix: createAddStoryFix(resolvedTarget),
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
});
|
|
121
124
|
}
|
|
122
125
|
/**
|
|
123
|
-
*
|
|
126
|
+
* Core helper to report a missing @story annotation for a method-like node.
|
|
127
|
+
* Delegates actual behavior to injected dependencies while keeping this
|
|
128
|
+
* module focused on core error-reporting behavior.
|
|
124
129
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
125
|
-
* @
|
|
130
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
131
|
+
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
132
|
+
* @req REQ-ANNOTATION-REQUIRED
|
|
133
|
+
* @req REQ-AUTOFIX-MISSING
|
|
134
|
+
* @req REQ-ERROR-SPECIFIC
|
|
126
135
|
*/
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
function coreReportMethod(deps, context, sourceCode, config) {
|
|
137
|
+
const { node, target: passedTarget, options = {} } = config;
|
|
138
|
+
try {
|
|
139
|
+
if (deps.hasStoryAnnotation(sourceCode, node)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const resolvedTarget = passedTarget ?? deps.resolveAnnotationTargetNode(sourceCode, node, null);
|
|
143
|
+
const name = deps.extractName(node);
|
|
144
|
+
const nameNode = (node.key && node.key.type === "Identifier" && node.key) || node;
|
|
145
|
+
const effectiveTemplate = deps.getAnnotationTemplate(options.annotationTemplateOverride);
|
|
146
|
+
const allowFix = deps.shouldApplyAutoFix(options.autoFixToggle);
|
|
147
|
+
context.report({
|
|
148
|
+
node: nameNode,
|
|
149
|
+
messageId: "missingStory",
|
|
150
|
+
data: { name, functionName: name },
|
|
151
|
+
fix: allowFix
|
|
152
|
+
? deps.createMethodFix(resolvedTarget, effectiveTemplate)
|
|
153
|
+
: undefined,
|
|
154
|
+
suggest: [
|
|
155
|
+
{
|
|
156
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
157
|
+
fix: deps.createMethodFix(resolvedTarget, effectiveTemplate),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
/* noop */
|
|
164
|
+
}
|
|
142
165
|
}
|
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helpers for the "require-story" rule
|
|
3
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
|
+
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
4
5
|
* @req REQ-ANNOTATION-REQUIRED - File-level header for rule helper utilities
|
|
6
|
+
* @req REQ-AUTOFIX-MISSING
|
|
7
|
+
* @req REQ-AUTOFIX-TEMPLATE
|
|
8
|
+
* @req REQ-AUTOFIX-SELECTIVE
|
|
5
9
|
*/
|
|
6
10
|
import type { Rule } from "eslint";
|
|
7
11
|
import { linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory } from "./require-story-io";
|
|
8
12
|
import { getNodeName } from "./require-story-utils";
|
|
9
|
-
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES } from "./require-story-core";
|
|
10
|
-
/**
|
|
11
|
-
* Path to the story file for annotations
|
|
12
|
-
*/
|
|
13
|
-
declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
14
|
-
declare const ANNOTATION = "/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */";
|
|
13
|
+
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, STORY_PATH } from "./require-story-core";
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* Derive the annotation template, optionally using an override.
|
|
16
|
+
* When override is a non-empty string, its trimmed value is used.
|
|
17
|
+
* Otherwise, the default template is returned.
|
|
19
18
|
*/
|
|
20
|
-
declare
|
|
19
|
+
declare function getAnnotationTemplate(override?: string): string;
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for fallback text window with named constant
|
|
21
|
+
* Determine whether auto-fix should be applied.
|
|
22
|
+
* Explicit false disables auto-fix; all other values enable it.
|
|
25
23
|
*/
|
|
26
|
-
declare
|
|
24
|
+
declare function shouldApplyAutoFix(autoFix: boolean | undefined): boolean;
|
|
27
25
|
/**
|
|
28
26
|
* Determine if a node is in an export declaration
|
|
29
27
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -96,42 +94,23 @@ declare function extractName(node: any): string;
|
|
|
96
94
|
* @returns {boolean} whether node should be processed
|
|
97
95
|
*/
|
|
98
96
|
declare function shouldProcessNode(node: any, scope: string[], exportPriority?: string): boolean;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node: any, passedTarget?: any): void;
|
|
114
|
-
/**
|
|
115
|
-
* Report a missing @story annotation for a method-like node
|
|
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.
|
|
118
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
119
|
-
* @story docs/stories/008.0-DEV-AUTO-FIX.story.md
|
|
120
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
121
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
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
|
|
126
|
-
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
127
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
128
|
-
* @param {any} node - AST node that is missing the annotation
|
|
129
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
130
|
-
*/
|
|
131
|
-
declare function reportMethod(context: Rule.RuleContext, sourceCode: any, node: any, passedTarget?: any): void;
|
|
97
|
+
interface ReportOptions {
|
|
98
|
+
annotationTemplateOverride?: string;
|
|
99
|
+
autoFixToggle?: boolean;
|
|
100
|
+
}
|
|
101
|
+
declare function reportMissing(context: Rule.RuleContext, sourceCode: any, config: {
|
|
102
|
+
node: any;
|
|
103
|
+
target?: any;
|
|
104
|
+
options?: ReportOptions;
|
|
105
|
+
}): void;
|
|
106
|
+
declare function reportMethod(context: Rule.RuleContext, sourceCode: any, config: {
|
|
107
|
+
node: any;
|
|
108
|
+
target?: any;
|
|
109
|
+
options?: ReportOptions;
|
|
110
|
+
}): void;
|
|
132
111
|
/**
|
|
133
112
|
* Explicit exports for require-story-annotation consumers
|
|
134
113
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
135
114
|
* @req REQ-ANNOTATION-REQUIRED - Explicitly export helper functions and constants used by requiring modules
|
|
136
115
|
*/
|
|
137
|
-
export { STORY_PATH,
|
|
116
|
+
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,8 @@
|
|
|
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
|
+
exports.getAnnotationTemplate = getAnnotationTemplate;
|
|
5
|
+
exports.shouldApplyAutoFix = shouldApplyAutoFix;
|
|
4
6
|
exports.isExportedNode = isExportedNode;
|
|
5
7
|
exports.jsdocHasStory = jsdocHasStory;
|
|
6
8
|
exports.commentsBeforeHasStory = commentsBeforeHasStory;
|
|
@@ -20,27 +22,28 @@ Object.defineProperty(exports, "getNodeName", { enumerable: true, get: function
|
|
|
20
22
|
const require_story_core_1 = require("./require-story-core");
|
|
21
23
|
Object.defineProperty(exports, "DEFAULT_SCOPE", { enumerable: true, get: function () { return require_story_core_1.DEFAULT_SCOPE; } });
|
|
22
24
|
Object.defineProperty(exports, "EXPORT_PRIORITY_VALUES", { enumerable: true, get: function () { return require_story_core_1.EXPORT_PRIORITY_VALUES; } });
|
|
25
|
+
Object.defineProperty(exports, "STORY_PATH", { enumerable: true, get: function () { return require_story_core_1.STORY_PATH; } });
|
|
23
26
|
/**
|
|
24
|
-
*
|
|
27
|
+
* Derive the annotation template, optionally using an override.
|
|
28
|
+
* When override is a non-empty string, its trimmed value is used.
|
|
29
|
+
* Otherwise, the default template is returned.
|
|
25
30
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
33
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for lookback lines with named constant
|
|
34
|
-
*/
|
|
35
|
-
const LOOKBACK_LINES = 4;
|
|
36
|
-
exports.LOOKBACK_LINES = LOOKBACK_LINES;
|
|
31
|
+
function getAnnotationTemplate(override) {
|
|
32
|
+
if (typeof override === "string" && override.trim().length > 0) {
|
|
33
|
+
return override.trim();
|
|
34
|
+
}
|
|
35
|
+
return `/** @story ${require_story_core_1.STORY_PATH} */`;
|
|
36
|
+
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for fallback text window with named constant
|
|
38
|
+
* Determine whether auto-fix should be applied.
|
|
39
|
+
* Explicit false disables auto-fix; all other values enable it.
|
|
41
40
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
function shouldApplyAutoFix(autoFix) {
|
|
42
|
+
if (autoFix === false) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
44
47
|
/**
|
|
45
48
|
* Determine if a node is in an export declaration
|
|
46
49
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -126,7 +129,7 @@ function hasStoryAnnotation(sourceCode, node) {
|
|
|
126
129
|
if (leadingCommentsHasStory(node)) {
|
|
127
130
|
return true;
|
|
128
131
|
}
|
|
129
|
-
if ((0, require_story_io_1.linesBeforeHasStory)(sourceCode, node
|
|
132
|
+
if ((0, require_story_io_1.linesBeforeHasStory)(sourceCode, node)) {
|
|
130
133
|
return true;
|
|
131
134
|
}
|
|
132
135
|
if ((0, require_story_io_1.parentChainHasStory)(sourceCode, node)) {
|
|
@@ -173,6 +176,54 @@ function resolveTargetNode(sourceCode, node) {
|
|
|
173
176
|
}
|
|
174
177
|
return node;
|
|
175
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Extract a direct Identifier name when available on the given node.
|
|
181
|
+
* This focuses only on plain Identifier nodes and ignores container shapes.
|
|
182
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
183
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract direct Identifier-based names from nodes
|
|
184
|
+
* @param {any} node - AST node to inspect
|
|
185
|
+
* @returns {string | null} identifier name or null when not applicable
|
|
186
|
+
*/
|
|
187
|
+
function getDirectIdentifierName(node) {
|
|
188
|
+
if (node &&
|
|
189
|
+
node.type === "Identifier" &&
|
|
190
|
+
typeof node.name === "string" &&
|
|
191
|
+
node.name.length > 0) {
|
|
192
|
+
return node.name;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Normalize container nodes that expose names via id/key properties.
|
|
198
|
+
* Supports common function and method containers, including literal keys.
|
|
199
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
200
|
+
* @req REQ-ANNOTATION-REQUIRED - Normalize container id/key-based names into a single helper
|
|
201
|
+
* @param {any} node - AST node that may contain id/key name information
|
|
202
|
+
* @returns {string | null} resolved container name or null when unavailable
|
|
203
|
+
*/
|
|
204
|
+
function getContainerKeyOrIdName(node) {
|
|
205
|
+
if (!node) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
if (node.id) {
|
|
209
|
+
const idName = (0, require_story_utils_1.getNodeName)(node.id);
|
|
210
|
+
if (typeof idName === "string" && idName.length > 0) {
|
|
211
|
+
return idName;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (node.key) {
|
|
215
|
+
const keyName = (0, require_story_utils_1.getNodeName)(node.key);
|
|
216
|
+
if (typeof keyName === "string" && keyName.length > 0) {
|
|
217
|
+
return keyName;
|
|
218
|
+
}
|
|
219
|
+
if (node.key.type === "Literal" &&
|
|
220
|
+
typeof node.key.value === "string" &&
|
|
221
|
+
node.key.value.length > 0) {
|
|
222
|
+
return node.key.value;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
176
227
|
/**
|
|
177
228
|
* Small utility to walk the node and its parents to extract an Identifier or key name.
|
|
178
229
|
* Walks up the parent chain and inspects common properties (id, key, name, Identifier nodes).
|
|
@@ -182,33 +233,21 @@ function resolveTargetNode(sourceCode, node) {
|
|
|
182
233
|
* @returns {string} extracted name or "(anonymous)" when no name found
|
|
183
234
|
*/
|
|
184
235
|
function extractName(node) {
|
|
185
|
-
let
|
|
186
|
-
while (
|
|
187
|
-
|
|
188
|
-
if (
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
// id property (FunctionDeclaration, etc.)
|
|
192
|
-
if (n.id && n.id.type === "Identifier" && typeof n.id.name === "string") {
|
|
193
|
-
return n.id.name;
|
|
236
|
+
let current = node;
|
|
237
|
+
while (current) {
|
|
238
|
+
const directIdentifierName = getDirectIdentifierName(current);
|
|
239
|
+
if (directIdentifierName) {
|
|
240
|
+
return directIdentifierName;
|
|
194
241
|
}
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
typeof n.key.name === "string") {
|
|
199
|
-
return n.key.name;
|
|
242
|
+
const containerName = getContainerKeyOrIdName(current);
|
|
243
|
+
if (containerName) {
|
|
244
|
+
return containerName;
|
|
200
245
|
}
|
|
201
|
-
|
|
202
|
-
if (typeof
|
|
203
|
-
return
|
|
246
|
+
const directName = current.name;
|
|
247
|
+
if (typeof directName === "string" && directName.length > 0) {
|
|
248
|
+
return directName;
|
|
204
249
|
}
|
|
205
|
-
|
|
206
|
-
if (n.key &&
|
|
207
|
-
n.key.type === "Literal" &&
|
|
208
|
-
typeof n.key.value === "string") {
|
|
209
|
-
return n.key.value;
|
|
210
|
-
}
|
|
211
|
-
n = n.parent;
|
|
250
|
+
current = current.parent;
|
|
212
251
|
}
|
|
213
252
|
return "(anonymous)";
|
|
214
253
|
}
|
|
@@ -235,86 +274,85 @@ function shouldProcessNode(node, scope, exportPriority = "all") {
|
|
|
235
274
|
return true;
|
|
236
275
|
}
|
|
237
276
|
/**
|
|
238
|
-
*
|
|
239
|
-
*
|
|
277
|
+
* Resolve the effective function name to report for a node.
|
|
278
|
+
* Normalizes id/key handling before delegating to extractName.
|
|
240
279
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
241
|
-
* @
|
|
242
|
-
* @
|
|
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
|
|
246
|
-
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
247
|
-
* @param {any} sourceCode - ESLint sourceCode object
|
|
248
|
-
* @param {any} node - AST node that is missing the annotation
|
|
249
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
280
|
+
* @req REQ-ANNOTATION-REQUIRED - Centralize reported function name resolution
|
|
281
|
+
* @param {any} node - AST node used to derive the function name
|
|
282
|
+
* @returns {string} resolved function name
|
|
250
283
|
*/
|
|
251
|
-
function
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget),
|
|
267
|
-
suggest: [
|
|
268
|
-
{
|
|
269
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${ANNOTATION}`,
|
|
270
|
-
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget),
|
|
271
|
-
},
|
|
272
|
-
],
|
|
273
|
-
});
|
|
284
|
+
function getReportedFunctionName(node) {
|
|
285
|
+
const candidate = node && (node.id || node.key) ? node.id || node.key : node;
|
|
286
|
+
return extractName(candidate);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Determine the most appropriate AST node to anchor error location for a report.
|
|
290
|
+
* Prefers Identifier nodes from id/key properties when available.
|
|
291
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
292
|
+
* @req REQ-ANNOTATION-REQUIRED - Normalize name node selection for error reporting
|
|
293
|
+
* @param {any} node - AST node used for error anchoring
|
|
294
|
+
* @returns {any} node to use as the report location
|
|
295
|
+
*/
|
|
296
|
+
function getNameNodeForReport(node) {
|
|
297
|
+
if (node?.id?.type === "Identifier") {
|
|
298
|
+
return node.id;
|
|
274
299
|
}
|
|
275
|
-
|
|
276
|
-
|
|
300
|
+
if (node?.key?.type === "Identifier") {
|
|
301
|
+
return node.key;
|
|
277
302
|
}
|
|
303
|
+
return node;
|
|
278
304
|
}
|
|
279
305
|
/**
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* The error data payload uses both name and functionName for consistent, specific error context.
|
|
306
|
+
* Resolve the node that should receive the @story annotation,
|
|
307
|
+
* respecting an explicitly passed target when provided.
|
|
283
308
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
284
|
-
* @
|
|
285
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
286
|
-
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
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
|
|
291
|
-
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
309
|
+
* @req REQ-ANNOTATION-REQUIRED - Centralize annotation target node resolution
|
|
292
310
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
293
|
-
* @param {any} node - AST node
|
|
294
|
-
* @param {any}
|
|
311
|
+
* @param {any} node - original function-like AST node
|
|
312
|
+
* @param {any} passedTarget - optional explicit annotation target
|
|
313
|
+
* @returns {any} node that should receive the annotation
|
|
295
314
|
*/
|
|
296
|
-
function
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
315
|
+
function resolveAnnotationTargetNode(sourceCode, node, passedTarget) {
|
|
316
|
+
return passedTarget ?? resolveTargetNode(sourceCode, node);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Build the effective annotation template and autofix toggle
|
|
320
|
+
* from the provided report options.
|
|
321
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
322
|
+
* @req REQ-ANNOTATION-REQUIRED - Normalize template and autofix configuration
|
|
323
|
+
* @param {ReportOptions} [options] - optional report configuration
|
|
324
|
+
* @returns {{ effectiveTemplate: string; allowFix: boolean }} template and autofix flags
|
|
325
|
+
*/
|
|
326
|
+
function buildTemplateConfig(options) {
|
|
327
|
+
const effectiveTemplate = getAnnotationTemplate(options?.annotationTemplateOverride);
|
|
328
|
+
const allowFix = shouldApplyAutoFix(options?.autoFixToggle);
|
|
329
|
+
return { effectiveTemplate, allowFix };
|
|
330
|
+
}
|
|
331
|
+
function reportMissing(context, sourceCode, config) {
|
|
332
|
+
(0, require_story_core_1.coreReportMissing)({
|
|
333
|
+
hasStoryAnnotation,
|
|
334
|
+
getReportedFunctionName,
|
|
335
|
+
resolveAnnotationTargetNode,
|
|
336
|
+
getNameNodeForReport,
|
|
337
|
+
buildTemplateConfig,
|
|
338
|
+
extractName,
|
|
339
|
+
getAnnotationTemplate,
|
|
340
|
+
shouldApplyAutoFix,
|
|
341
|
+
createAddStoryFix: require_story_core_1.createAddStoryFix,
|
|
342
|
+
createMethodFix: require_story_core_1.createMethodFix,
|
|
343
|
+
}, context, sourceCode, config);
|
|
344
|
+
}
|
|
345
|
+
function reportMethod(context, sourceCode, config) {
|
|
346
|
+
(0, require_story_core_1.coreReportMethod)({
|
|
347
|
+
hasStoryAnnotation,
|
|
348
|
+
getReportedFunctionName,
|
|
349
|
+
resolveAnnotationTargetNode,
|
|
350
|
+
getNameNodeForReport,
|
|
351
|
+
buildTemplateConfig,
|
|
352
|
+
extractName,
|
|
353
|
+
getAnnotationTemplate,
|
|
354
|
+
shouldApplyAutoFix,
|
|
355
|
+
createAddStoryFix: require_story_core_1.createAddStoryFix,
|
|
356
|
+
createMethodFix: require_story_core_1.createMethodFix,
|
|
357
|
+
}, context, sourceCode, config);
|
|
320
358
|
}
|