eslint-plugin-traceability 1.4.2 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/src/maintenance/batch.js +1 -0
- package/lib/src/maintenance/detect.js +4 -0
- package/lib/src/maintenance/report.js +2 -0
- package/lib/src/maintenance/update.js +40 -1
- package/lib/src/maintenance/utils.js +33 -2
- package/lib/src/rules/helpers/require-story-core.d.ts +35 -0
- package/lib/src/rules/helpers/require-story-core.js +139 -0
- package/lib/src/rules/helpers/require-story-helpers.d.ts +124 -0
- package/lib/src/rules/helpers/require-story-helpers.js +293 -0
- package/lib/src/rules/helpers/require-story-io.d.ts +35 -0
- package/lib/src/rules/helpers/require-story-io.js +97 -0
- package/lib/src/rules/helpers/require-story-visitors.d.ts +13 -0
- package/lib/src/rules/helpers/require-story-visitors.js +163 -0
- package/lib/src/rules/require-story-annotation.d.ts +15 -0
- package/lib/src/rules/require-story-annotation.js +27 -238
- package/lib/src/utils/branch-annotation-helpers.js +98 -14
- package/lib/tests/maintenance/detect-isolated.test.js +19 -6
- package/lib/tests/rules/require-story-helpers.test.d.ts +1 -0
- package/lib/tests/rules/require-story-helpers.test.js +173 -0
- package/lib/tests/rules/require-story-io.edgecases.test.d.ts +6 -0
- package/lib/tests/rules/require-story-io.edgecases.test.js +50 -0
- package/package.json +3 -1
|
@@ -12,6 +12,7 @@ const detect_1 = require("./detect");
|
|
|
12
12
|
*/
|
|
13
13
|
function batchUpdateAnnotations(codebasePath, mappings) {
|
|
14
14
|
let totalUpdated = 0;
|
|
15
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-BATCH - Perform batch updates
|
|
15
16
|
for (const { oldPath, newPath } of mappings) {
|
|
16
17
|
totalUpdated += (0, update_1.updateAnnotationReferences)(codebasePath, oldPath, newPath);
|
|
17
18
|
}
|
|
@@ -43,6 +43,7 @@ const utils_1 = require("./utils");
|
|
|
43
43
|
* @req REQ-MAINT-DETECT - Detect stale annotation references
|
|
44
44
|
*/
|
|
45
45
|
function detectStaleAnnotations(codebasePath) {
|
|
46
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-DETECT - Ensure codebase path exists and is a directory
|
|
46
47
|
if (!fs.existsSync(codebasePath) ||
|
|
47
48
|
!fs.statSync(codebasePath).isDirectory()) {
|
|
48
49
|
return [];
|
|
@@ -51,14 +52,17 @@ function detectStaleAnnotations(codebasePath) {
|
|
|
51
52
|
const baseDir = path.resolve(cwd, codebasePath);
|
|
52
53
|
const stale = new Set();
|
|
53
54
|
const files = (0, utils_1.getAllFiles)(codebasePath);
|
|
55
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-DETECT - Iterate over all files in the codebase
|
|
54
56
|
for (const file of files) {
|
|
55
57
|
const content = fs.readFileSync(file, "utf8");
|
|
56
58
|
const regex = /@story\s+([^\s]+)/g;
|
|
57
59
|
let match;
|
|
60
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-DETECT - Iterate over regex matches for @story annotations
|
|
58
61
|
while ((match = regex.exec(content)) !== null) {
|
|
59
62
|
const storyPath = match[1];
|
|
60
63
|
const storyProjectPath = path.resolve(cwd, storyPath);
|
|
61
64
|
const storyCodebasePath = path.resolve(baseDir, storyPath);
|
|
65
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-DETECT - Check if referenced story file is missing in both project and codebase paths
|
|
62
66
|
if (!fs.existsSync(storyProjectPath) &&
|
|
63
67
|
!fs.existsSync(storyCodebasePath)) {
|
|
64
68
|
stale.add(storyPath);
|
|
@@ -10,6 +10,8 @@ const detect_1 = require("./detect");
|
|
|
10
10
|
*/
|
|
11
11
|
function generateMaintenanceReport(codebasePath) {
|
|
12
12
|
const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
|
|
13
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-SAFE - When no stale annotations are found, return empty string to indicate no actions required
|
|
14
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-REPORT - When stale annotations exist, produce a newline-separated report
|
|
13
15
|
if (staleAnnotations.length === 0) {
|
|
14
16
|
return "";
|
|
15
17
|
}
|
|
@@ -42,6 +42,14 @@ const utils_1 = require("./utils");
|
|
|
42
42
|
* @req REQ-MAINT-UPDATE - Update annotation references
|
|
43
43
|
*/
|
|
44
44
|
function updateAnnotationReferences(codebasePath, oldPath, newPath) {
|
|
45
|
+
/**
|
|
46
|
+
* Check that the provided codebase path exists and is a directory.
|
|
47
|
+
* If not, abort early.
|
|
48
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
49
|
+
* @req REQ-MAINT-UPDATE
|
|
50
|
+
*/
|
|
51
|
+
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
52
|
+
// @req REQ-MAINT-UPDATE
|
|
45
53
|
if (!fs.existsSync(codebasePath) ||
|
|
46
54
|
!fs.statSync(codebasePath).isDirectory()) {
|
|
47
55
|
return 0;
|
|
@@ -50,15 +58,46 @@ function updateAnnotationReferences(codebasePath, oldPath, newPath) {
|
|
|
50
58
|
const escapedOldPath = oldPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
51
59
|
const regex = new RegExp(`(@story\\s*)${escapedOldPath}`, "g");
|
|
52
60
|
const files = (0, utils_1.getAllFiles)(codebasePath);
|
|
61
|
+
/**
|
|
62
|
+
* Iterate over all files and replace annotation references
|
|
63
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
64
|
+
* @req REQ-MAINT-UPDATE
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Loop over each discovered file path
|
|
68
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
69
|
+
* @req REQ-MAINT-UPDATE
|
|
70
|
+
*/
|
|
53
71
|
for (const fullPath of files) {
|
|
54
72
|
const stat = fs.statSync(fullPath);
|
|
73
|
+
/**
|
|
74
|
+
* Skip non-files in iteration
|
|
75
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
76
|
+
* @req REQ-MAINT-UPDATE
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* Skip entries that are not regular files (e.g., directories)
|
|
80
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
81
|
+
* @req REQ-MAINT-UPDATE
|
|
82
|
+
*/
|
|
55
83
|
if (!stat.isFile())
|
|
56
84
|
continue;
|
|
57
85
|
const content = fs.readFileSync(fullPath, "utf8");
|
|
58
|
-
const newContent = content.replace(regex,
|
|
86
|
+
const newContent = content.replace(regex,
|
|
87
|
+
/**
|
|
88
|
+
* Replacement callback to update annotation references
|
|
89
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
90
|
+
* @req REQ-MAINT-UPDATE
|
|
91
|
+
*/
|
|
92
|
+
(match, p1) => {
|
|
59
93
|
replacementCount++;
|
|
60
94
|
return `${p1}${newPath}`;
|
|
61
95
|
});
|
|
96
|
+
/**
|
|
97
|
+
* Write file only if content changed
|
|
98
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
99
|
+
* @req REQ-MAINT-UPDATE
|
|
100
|
+
*/
|
|
62
101
|
if (newContent !== content) {
|
|
63
102
|
fs.writeFileSync(fullPath, newContent, "utf8");
|
|
64
103
|
}
|
|
@@ -43,6 +43,16 @@ const path = __importStar(require("path"));
|
|
|
43
43
|
*/
|
|
44
44
|
function getAllFiles(dir) {
|
|
45
45
|
const fileList = [];
|
|
46
|
+
/**
|
|
47
|
+
* Ensure the provided path exists and is a directory before traversal.
|
|
48
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
49
|
+
* @req REQ-MAINT-UTILS-VALIDATE-DIR - Validate input directory path
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Traceability for the directory-existence branch.
|
|
53
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
54
|
+
* @req REQ-MAINT-UTILS-VALIDATE-DIR-BRANCH - Traceability for directory-existence branch
|
|
55
|
+
*/
|
|
46
56
|
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
|
|
47
57
|
return fileList;
|
|
48
58
|
}
|
|
@@ -53,15 +63,36 @@ function getAllFiles(dir) {
|
|
|
53
63
|
*/
|
|
54
64
|
function traverse(currentDir) {
|
|
55
65
|
const entries = fs.readdirSync(currentDir);
|
|
66
|
+
/**
|
|
67
|
+
* Iterate over directory entries using a for-of loop.
|
|
68
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
69
|
+
* @req REQ-MAINT-UTILS-TRAVERSE-FOROF - Traceability for ForOfStatement branch handling entries
|
|
70
|
+
*/
|
|
56
71
|
for (const entry of entries) {
|
|
57
72
|
const fullPath = path.join(currentDir, entry);
|
|
58
73
|
const stat = fs.statSync(fullPath);
|
|
74
|
+
/**
|
|
75
|
+
* Recurse into directories to continue traversal.
|
|
76
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
77
|
+
* @req REQ-MAINT-UTILS-TRAVERSE-DIR - Handle directory entries during traversal
|
|
78
|
+
*/
|
|
59
79
|
if (stat.isDirectory()) {
|
|
60
80
|
traverse(fullPath);
|
|
81
|
+
/**
|
|
82
|
+
* Collect regular file entries during traversal.
|
|
83
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
84
|
+
* @req REQ-MAINT-UTILS-TRAVERSE-FILE - Handle file entries during traversal
|
|
85
|
+
*/
|
|
61
86
|
}
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Skip non-file entries encountered during traversal.
|
|
89
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
90
|
+
* @req REQ-MAINT-UTILS-TRAVERSE-SKIP-NONFILE - Traceability for skipping non-file entries
|
|
91
|
+
*/
|
|
92
|
+
if (!stat.isFile()) {
|
|
93
|
+
continue;
|
|
64
94
|
}
|
|
95
|
+
fileList.push(fullPath);
|
|
65
96
|
}
|
|
66
97
|
}
|
|
67
98
|
traverse(dir);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Rule } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Create a fixer function that inserts a @story annotation before the target node.
|
|
4
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
6
|
+
*/
|
|
7
|
+
export declare function createAddStoryFix(target: any): (fixer: any) => any;
|
|
8
|
+
/**
|
|
9
|
+
* Create a fixer function for class method annotations.
|
|
10
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
11
|
+
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
12
|
+
*/
|
|
13
|
+
export declare function createMethodFix(node: any): (fixer: any) => any;
|
|
14
|
+
/**
|
|
15
|
+
* Default set of node types to check for missing @story annotations.
|
|
16
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
17
|
+
* @req REQ-ANNOTATION-REQUIRED - Provide sensible default scope for rule checks
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_SCOPE: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Allowed values for export priority option.
|
|
22
|
+
*/
|
|
23
|
+
export declare const EXPORT_PRIORITY_VALUES: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Report a missing @story annotation for a general function-like node.
|
|
26
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
27
|
+
* @req REQ-AUTOFIX - Report missing annotation and provide autofix using createAddStoryFix
|
|
28
|
+
*/
|
|
29
|
+
export declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node: any, target?: any): void;
|
|
30
|
+
/**
|
|
31
|
+
* Report missing @story annotation for methods
|
|
32
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
33
|
+
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
34
|
+
*/
|
|
35
|
+
export declare function reportMethod(context: Rule.RuleContext, sourceCode: any, node: any, target?: any): void;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = void 0;
|
|
4
|
+
exports.createAddStoryFix = createAddStoryFix;
|
|
5
|
+
exports.createMethodFix = createMethodFix;
|
|
6
|
+
exports.reportMissing = reportMissing;
|
|
7
|
+
exports.reportMethod = reportMethod;
|
|
8
|
+
const require_story_helpers_1 = require("./require-story-helpers");
|
|
9
|
+
/**
|
|
10
|
+
* Create a fixer function that inserts a @story annotation before the target node.
|
|
11
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
12
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
13
|
+
*/
|
|
14
|
+
function createAddStoryFix(target) {
|
|
15
|
+
/**
|
|
16
|
+
* Fixer that inserts a @story annotation before the target node.
|
|
17
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
18
|
+
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
19
|
+
*/
|
|
20
|
+
function addStoryFixer(fixer) {
|
|
21
|
+
const start = target && typeof target === "object"
|
|
22
|
+
? target.parent &&
|
|
23
|
+
(target.parent.type === "ExportNamedDeclaration" ||
|
|
24
|
+
target.parent.type === "ExportDefaultDeclaration") &&
|
|
25
|
+
Array.isArray(target.parent.range) &&
|
|
26
|
+
typeof target.parent.range[0] === "number"
|
|
27
|
+
? target.parent.range[0]
|
|
28
|
+
: Array.isArray(target.range) && typeof target.range[0] === "number"
|
|
29
|
+
? target.range[0]
|
|
30
|
+
: 0
|
|
31
|
+
: 0;
|
|
32
|
+
return fixer.insertTextBeforeRange([start, start], `${require_story_helpers_1.ANNOTATION}\n`);
|
|
33
|
+
}
|
|
34
|
+
return addStoryFixer;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create a fixer function for class method annotations.
|
|
38
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
39
|
+
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
40
|
+
*/
|
|
41
|
+
function createMethodFix(node) {
|
|
42
|
+
/**
|
|
43
|
+
* Fixer that inserts a @story annotation before a method node.
|
|
44
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
45
|
+
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
46
|
+
*/
|
|
47
|
+
function methodFixer(fixer) {
|
|
48
|
+
const start = node && typeof node === "object"
|
|
49
|
+
? node.parent &&
|
|
50
|
+
(node.parent.type === "ExportNamedDeclaration" ||
|
|
51
|
+
node.parent.type === "ExportDefaultDeclaration") &&
|
|
52
|
+
Array.isArray(node.parent.range) &&
|
|
53
|
+
typeof node.parent.range[0] === "number"
|
|
54
|
+
? node.parent.range[0]
|
|
55
|
+
: Array.isArray(node.range) && typeof node.range[0] === "number"
|
|
56
|
+
? node.range[0]
|
|
57
|
+
: 0
|
|
58
|
+
: 0;
|
|
59
|
+
return fixer.insertTextBeforeRange([start, start], `${require_story_helpers_1.ANNOTATION}\n `);
|
|
60
|
+
}
|
|
61
|
+
return methodFixer;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Default set of node types to check for missing @story annotations.
|
|
65
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
66
|
+
* @req REQ-ANNOTATION-REQUIRED - Provide sensible default scope for rule checks
|
|
67
|
+
*/
|
|
68
|
+
exports.DEFAULT_SCOPE = [
|
|
69
|
+
"FunctionDeclaration",
|
|
70
|
+
"FunctionExpression",
|
|
71
|
+
"ArrowFunctionExpression",
|
|
72
|
+
"MethodDefinition",
|
|
73
|
+
"TSMethodSignature",
|
|
74
|
+
"TSDeclareFunction",
|
|
75
|
+
"VariableDeclarator",
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Allowed values for export priority option.
|
|
79
|
+
*/
|
|
80
|
+
exports.EXPORT_PRIORITY_VALUES = ["all", "exported", "non-exported"];
|
|
81
|
+
/**
|
|
82
|
+
* Report a missing @story annotation for a general function-like node.
|
|
83
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
84
|
+
* @req REQ-AUTOFIX - Report missing annotation and provide autofix using createAddStoryFix
|
|
85
|
+
*/
|
|
86
|
+
function reportMissing(context, sourceCode, node, target) {
|
|
87
|
+
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
88
|
+
// @req REQ-AUTOFIX - Prefer provided sourceCode, fallback to context.getSourceCode()
|
|
89
|
+
const sc = sourceCode || context.getSourceCode();
|
|
90
|
+
/**
|
|
91
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
92
|
+
* @req REQ-AUTOFIX - Only attempt to read JSDoc comment if source supports it
|
|
93
|
+
*/
|
|
94
|
+
if (typeof sc?.getJSDocComment === "function") {
|
|
95
|
+
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
96
|
+
// @req REQ-ANNOTATION-REQUIRED - Skip reporting when JSDoc already contains @story
|
|
97
|
+
const js = sc.getJSDocComment(node);
|
|
98
|
+
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
99
|
+
// @req REQ-ANNOTATION-REQUIRED - If @story present in JSDoc, do not report
|
|
100
|
+
if (js && typeof js.value === "string" && js.value.includes("@story"))
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
104
|
+
// @req REQ-ANNOTATION-REQUIRED - Resolve function name for reporting, default to <unknown>
|
|
105
|
+
const name = node && node.id && node.id.name ? node.id.name : "<unknown>";
|
|
106
|
+
const resolvedTarget = target ?? node;
|
|
107
|
+
context.report({
|
|
108
|
+
node,
|
|
109
|
+
messageId: "missingStory",
|
|
110
|
+
data: { name },
|
|
111
|
+
suggest: [
|
|
112
|
+
{
|
|
113
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${require_story_helpers_1.ANNOTATION}`,
|
|
114
|
+
fix: createAddStoryFix(resolvedTarget),
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Report missing @story annotation for methods
|
|
121
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
122
|
+
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
123
|
+
*/
|
|
124
|
+
function reportMethod(context, sourceCode, node, target) {
|
|
125
|
+
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
126
|
+
// @req REQ-ANNOTATION-REQUIRED - Resolve method name for reporting, default to <unknown>
|
|
127
|
+
const name = node && node.key && node.key.name ? node.key.name : "<unknown>";
|
|
128
|
+
context.report({
|
|
129
|
+
node,
|
|
130
|
+
messageId: "missingStory",
|
|
131
|
+
data: { name },
|
|
132
|
+
suggest: [
|
|
133
|
+
{
|
|
134
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${require_story_helpers_1.ANNOTATION}`,
|
|
135
|
+
fix: createMethodFix(target ?? node),
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for the "require-story" rule
|
|
3
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
|
+
* @req REQ-ANNOTATION-REQUIRED - File-level header for rule helper utilities
|
|
5
|
+
*/
|
|
6
|
+
import type { Rule } from "eslint";
|
|
7
|
+
import { linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory } from "./require-story-io";
|
|
8
|
+
import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES } from "./require-story-core";
|
|
9
|
+
/**
|
|
10
|
+
* Path to the story file for annotations
|
|
11
|
+
*/
|
|
12
|
+
declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
13
|
+
declare const ANNOTATION = "/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */";
|
|
14
|
+
/**
|
|
15
|
+
* Number of physical source lines to inspect before a node when searching for @story text
|
|
16
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
17
|
+
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for lookback lines with named constant
|
|
18
|
+
*/
|
|
19
|
+
declare const LOOKBACK_LINES = 4;
|
|
20
|
+
/**
|
|
21
|
+
* Window (in characters) to inspect before a node as a fallback when searching for @story text
|
|
22
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
23
|
+
* @req REQ-ANNOTATION-REQUIRED - Replace magic number for fallback text window with named constant
|
|
24
|
+
*/
|
|
25
|
+
declare const FALLBACK_WINDOW = 800;
|
|
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
|
+
* @param {any} node - AST node to check for export ancestry
|
|
31
|
+
* @returns {boolean} true if node is within an export declaration
|
|
32
|
+
*/
|
|
33
|
+
declare function isExportedNode(node: any): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Check whether the JSDoc associated with node contains @story
|
|
36
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
37
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
|
|
38
|
+
* @param {any} sourceCode - ESLint sourceCode object
|
|
39
|
+
* @param {any} node - AST node to inspect
|
|
40
|
+
* @returns {boolean} true if JSDoc contains @story
|
|
41
|
+
*/
|
|
42
|
+
declare function jsdocHasStory(sourceCode: any, node: any): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Check whether comments returned by sourceCode.getCommentsBefore contain @story
|
|
45
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
46
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
|
|
47
|
+
* @param {any} sourceCode - ESLint sourceCode object
|
|
48
|
+
* @param {any} node - AST node to inspect
|
|
49
|
+
* @returns {boolean} true if any preceding comment contains @story
|
|
50
|
+
*/
|
|
51
|
+
declare function commentsBeforeHasStory(sourceCode: any, node: any): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Check whether leadingComments attached to the node contain @story
|
|
54
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
55
|
+
* @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
|
|
56
|
+
* @param {any} node - AST node to inspect
|
|
57
|
+
* @returns {boolean} true if any leading comment contains @story
|
|
58
|
+
*/
|
|
59
|
+
declare function leadingCommentsHasStory(node: any): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Check if @story annotation already present in JSDoc or preceding comments
|
|
62
|
+
* Consolidates a variety of heuristics through smaller helpers.
|
|
63
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
64
|
+
* @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
|
|
65
|
+
* @param {any} sourceCode - ESLint sourceCode object
|
|
66
|
+
* @param {any} node - AST node to inspect for existing annotations
|
|
67
|
+
* @returns {boolean} true if @story annotation already present
|
|
68
|
+
*/
|
|
69
|
+
declare function hasStoryAnnotation(sourceCode: any, node: any): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get the name of the function-like node
|
|
72
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
73
|
+
* @req REQ-ANNOTATION-REQUIRED - Resolve a human-friendly name for a function-like AST node
|
|
74
|
+
* @param {any} node - AST node representing a function-like construct
|
|
75
|
+
* @returns {string} the resolved name or "<unknown>"
|
|
76
|
+
*/
|
|
77
|
+
declare function getNodeName(node: any): string;
|
|
78
|
+
/**
|
|
79
|
+
* Determine AST node where annotation should be inserted
|
|
80
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
81
|
+
* @req REQ-ANNOTATION-REQUIRED - Determine correct insertion target for annotation
|
|
82
|
+
* @param {any} sourceCode - ESLint sourceCode object (unused but kept for parity)
|
|
83
|
+
* @param {any} node - function-like AST node to resolve target for
|
|
84
|
+
* @returns {any} AST node that should receive the annotation
|
|
85
|
+
*/
|
|
86
|
+
declare function resolveTargetNode(sourceCode: any, node: any): any;
|
|
87
|
+
/**
|
|
88
|
+
* Check if this node is within scope and matches exportPriority
|
|
89
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
90
|
+
* @req REQ-ANNOTATION-REQUIRED - Determine whether a node should be processed by rule
|
|
91
|
+
* @param {any} node - AST node to evaluate
|
|
92
|
+
* @param {string[]} scope - allowed node types
|
|
93
|
+
* @param {string} [exportPriority='all'] - 'all' | 'exported' | 'non-exported' (default: 'all')
|
|
94
|
+
* @returns {boolean} whether node should be processed
|
|
95
|
+
*/
|
|
96
|
+
declare function shouldProcessNode(node: any, scope: string[], exportPriority?: string): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Report a missing @story annotation for a function-like node
|
|
99
|
+
* Provides a suggestion to add the annotation.
|
|
100
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
101
|
+
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing annotations with suggestion
|
|
102
|
+
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
103
|
+
* @param {any} sourceCode - ESLint sourceCode object
|
|
104
|
+
* @param {any} node - AST node that is missing the annotation
|
|
105
|
+
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
106
|
+
*/
|
|
107
|
+
declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node: any, passedTarget?: any): void;
|
|
108
|
+
/**
|
|
109
|
+
* Report a missing @story annotation for a method-like node
|
|
110
|
+
* Provides a suggestion to update the method/interface with the annotation.
|
|
111
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
112
|
+
* @req REQ-ANNOTATION-REQUIRED - Implement reporting for missing method/interface annotations with suggestion
|
|
113
|
+
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
114
|
+
* @param {any} sourceCode - ESLint sourceCode object
|
|
115
|
+
* @param {any} node - AST node that is missing the annotation
|
|
116
|
+
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
117
|
+
*/
|
|
118
|
+
declare function reportMethod(context: Rule.RuleContext, sourceCode: any, node: any, passedTarget?: any): void;
|
|
119
|
+
/**
|
|
120
|
+
* Explicit exports for require-story-annotation consumers
|
|
121
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
122
|
+
* @req REQ-ANNOTATION-REQUIRED - Explicitly export helper functions and constants used by requiring modules
|
|
123
|
+
*/
|
|
124
|
+
export { STORY_PATH, ANNOTATION, LOOKBACK_LINES, FALLBACK_WINDOW, isExportedNode, jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, getNodeName, resolveTargetNode, shouldProcessNode, reportMissing, reportMethod, DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory, };
|