eslint-plugin-traceability 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -3
- package/README.md +1 -0
- package/lib/src/maintenance/cli.js +12 -12
- package/lib/src/maintenance/detect.js +19 -19
- package/lib/src/rules/helpers/require-story-core.d.ts +2 -15
- package/lib/src/rules/helpers/require-story-core.js +4 -71
- package/lib/src/rules/helpers/require-story-helpers.d.ts +32 -8
- package/lib/src/rules/helpers/require-story-helpers.js +44 -15
- 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 +6 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +4 -0
- 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 +1 -1
- 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/rules/auto-fix-behavior-008.test.js +23 -0
- package/lib/tests/rules/require-story-core.autofix.test.js +9 -3
- package/lib/tests/rules/require-story-core.test.js +13 -7
- package/lib/tests/rules/require-story-helpers-edgecases.test.js +1 -1
- package/lib/tests/rules/require-story-helpers.test.js +14 -8
- 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 +8 -4
- package/user-docs/examples.md +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# [1.11.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.10.1...v1.11.0) (2025-12-05)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### Features
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* add configurable auto-fix templates and toggles ([5e0e6e7](https://github.com/voder-ai/eslint-plugin-traceability/commit/5e0e6e782812aebb128c4922931bb9703265bfb1))
|
|
7
|
+
* add configurable auto-fix templates and toggles ([21c3a79](https://github.com/voder-ai/eslint-plugin-traceability/commit/21c3a79ce2e2e7fd95a422a963735d67940c8bd8))
|
|
7
8
|
|
|
8
9
|
# Changelog
|
|
9
10
|
|
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ export default [
|
|
|
54
54
|
- `traceability/valid-annotation-format` Enforces correct format of traceability annotations. (See the rule documentation in the plugin's user guide.)
|
|
55
55
|
- `traceability/valid-story-reference` Validates that `@story` references point to existing story files. (See the rule documentation in the plugin's user guide.)
|
|
56
56
|
- `traceability/valid-req-reference` Validates that `@req` references point to existing requirement IDs. (See the rule documentation in the plugin's user guide.)
|
|
57
|
+
- `traceability/require-test-traceability` Enforces traceability conventions in test files by requiring file-level `@supports` annotations, story references in `describe` blocks, and `[REQ-...]` prefixes in `it`/`test` names. (See the rule documentation in the plugin's user guide.)
|
|
57
58
|
- `traceability/prefer-implements-annotation` Recommends migration from legacy `@story`/`@req` annotations to `@supports` (opt-in; disabled by default in the presets and must be explicitly enabled). (See the rule documentation in the plugin's user guide.)
|
|
58
59
|
|
|
59
60
|
Configuration options: For detailed per-rule options (such as scopes, branch types, and story directory settings), see the individual rule docs in the plugin's user guide and the consolidated [API Reference](user-docs/api-reference.md).
|
|
@@ -18,8 +18,8 @@ function runMaintenanceCli(rawArgv) {
|
|
|
18
18
|
const initialNormalized = (0, flags_1.normalizeCliArgs)(rawArgv);
|
|
19
19
|
const { subcommand: command } = initialNormalized;
|
|
20
20
|
if (!command || command === "-h" || command === "--help") {
|
|
21
|
-
// @
|
|
22
|
-
// @
|
|
21
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
22
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Branch to show usage when no command or help flag is provided; handle help requests safely and provide discoverable usage output
|
|
23
23
|
printHelp();
|
|
24
24
|
return commands_1.EXIT_OK;
|
|
25
25
|
}
|
|
@@ -27,36 +27,36 @@ function runMaintenanceCli(rawArgv) {
|
|
|
27
27
|
// receive the subcommand name and its raw argument vector unchanged.
|
|
28
28
|
const normalized = initialNormalized;
|
|
29
29
|
try {
|
|
30
|
-
// @
|
|
31
|
-
// @
|
|
30
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
31
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch unexpected errors and surface concise diagnostics without crashing
|
|
32
32
|
switch (command) {
|
|
33
33
|
case "detect":
|
|
34
|
-
// @
|
|
34
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Branch to dispatch to detection handler when 'detect' is requested; dispatch to detection handler
|
|
35
35
|
return (0, commands_1.handleDetect)(normalized);
|
|
36
36
|
case "verify":
|
|
37
|
-
// @
|
|
37
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-VERIFY - Branch to dispatch to verification handler when 'verify' is requested; dispatch to verification handler
|
|
38
38
|
return (0, commands_1.handleVerify)(normalized);
|
|
39
39
|
case "report":
|
|
40
|
-
// @
|
|
40
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT - Branch to dispatch to reporting handler when 'report' is requested; dispatch to reporting handler
|
|
41
41
|
return (0, commands_1.handleReport)(normalized);
|
|
42
42
|
case "update": {
|
|
43
|
-
// @
|
|
43
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-UPDATE - Branch to dispatch to update handler when 'update' is requested; dispatch to update handler
|
|
44
44
|
const result = (0, commands_1.handleUpdate)(normalized);
|
|
45
45
|
if (result === commands_1.EXIT_USAGE) {
|
|
46
|
-
// @
|
|
46
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Print help on usage errors from update; help branch for update usage errors
|
|
47
47
|
printHelp();
|
|
48
48
|
}
|
|
49
49
|
return result;
|
|
50
50
|
}
|
|
51
51
|
default:
|
|
52
|
-
// @
|
|
52
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Branch for unknown commands to emit diagnostics and safe usage guidance; handle unknown commands safely with diagnostics
|
|
53
53
|
console.error(`Unknown command: ${command}`);
|
|
54
54
|
printHelp();
|
|
55
55
|
return commands_1.EXIT_USAGE;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
|
-
// @
|
|
59
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch-all error branch to prevent crashes and provide concise diagnostics; catch unexpected errors and surface concise diagnostics without crashing
|
|
60
60
|
const message = error instanceof Error
|
|
61
61
|
? error.message
|
|
62
62
|
: "Unknown error in maintenance CLI";
|
|
@@ -70,7 +70,7 @@ function runMaintenanceCli(rawArgv) {
|
|
|
70
70
|
* @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
|
|
71
71
|
*/
|
|
72
72
|
function printHelp() {
|
|
73
|
-
// @
|
|
73
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Help branch ensures users can discover maintenance CLI usage safely; provide discoverable CLI usage information
|
|
74
74
|
console.log(`traceability-maint - Traceability annotation maintenance tools
|
|
75
75
|
|
|
76
76
|
Usage:
|
|
@@ -54,9 +54,9 @@ function detectStaleAnnotations(codebasePath) {
|
|
|
54
54
|
// @req REQ-MAINT-DETECT - Return empty result if workspaceRoot does not exist or is not a directory
|
|
55
55
|
if (!fs.existsSync(workspaceRoot) ||
|
|
56
56
|
!fs.statSync(workspaceRoot).isDirectory()) {
|
|
57
|
-
// @
|
|
58
|
-
// @
|
|
59
|
-
// @
|
|
57
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
58
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
59
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
60
60
|
return [];
|
|
61
61
|
}
|
|
62
62
|
const stale = new Set();
|
|
@@ -79,12 +79,12 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
|
|
|
79
79
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
80
80
|
// @req REQ-MAINT-DETECT - Handle file read errors gracefully
|
|
81
81
|
try {
|
|
82
|
-
// @
|
|
82
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
83
83
|
content = fs.readFileSync(file, "utf8");
|
|
84
84
|
}
|
|
85
85
|
catch {
|
|
86
|
-
// @
|
|
87
|
-
// @
|
|
86
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
87
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Swallow file read failures without aborting detection
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
const regex = /@story\s+([^\s]+)/g;
|
|
@@ -103,7 +103,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
|
|
|
103
103
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
104
104
|
// @req REQ-MAINT-DETECT REQ-SECURITY-VALIDATION - Skip traversal/absolute-unsafe or invalid-extension story paths before any filesystem or boundary checks
|
|
105
105
|
if ((0, storyReferenceUtils_1.isUnsafeStoryPath)(storyPath)) {
|
|
106
|
-
// @
|
|
106
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
@@ -115,7 +115,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
|
|
|
115
115
|
const inProjectCandidates = getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, workspaceRoot);
|
|
116
116
|
// If both candidates are out-of-project, do not mark as stale and skip FS checks
|
|
117
117
|
if (inProjectCandidates.length === 0) {
|
|
118
|
-
// @
|
|
118
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - No in-project candidates means nothing to check or mark stale
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
@@ -124,7 +124,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
|
|
|
124
124
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
125
125
|
// @req REQ-MAINT-DETECT - Mark story as stale if any in-project candidate exists conceptually but none exist on disk
|
|
126
126
|
if (!anyExists) {
|
|
127
|
-
// @
|
|
127
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
128
128
|
stale.add(storyPath);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -136,24 +136,24 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
136
136
|
let projectBoundary;
|
|
137
137
|
let codebaseBoundary;
|
|
138
138
|
try {
|
|
139
|
-
// @
|
|
139
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
140
140
|
projectBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyProjectCandidate, workspaceRoot);
|
|
141
141
|
}
|
|
142
142
|
catch {
|
|
143
|
-
// @
|
|
144
|
-
// @
|
|
143
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
144
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
|
|
145
145
|
projectBoundary = {
|
|
146
146
|
isWithinProject: false,
|
|
147
147
|
candidate: storyProjectCandidate,
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
try {
|
|
151
|
-
// @
|
|
151
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
152
152
|
codebaseBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyCodebaseCandidate, workspaceRoot);
|
|
153
153
|
}
|
|
154
154
|
catch {
|
|
155
|
-
// @
|
|
156
|
-
// @
|
|
155
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
156
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
|
|
157
157
|
codebaseBoundary = {
|
|
158
158
|
isWithinProject: false,
|
|
159
159
|
candidate: storyCodebaseCandidate,
|
|
@@ -161,11 +161,11 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
161
161
|
}
|
|
162
162
|
const inProjectCandidates = [];
|
|
163
163
|
if (projectBoundary.isWithinProject) {
|
|
164
|
-
// @
|
|
164
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect project-relative in-project candidate
|
|
165
165
|
inProjectCandidates.push(projectBoundary.candidate);
|
|
166
166
|
}
|
|
167
167
|
if (codebaseBoundary.isWithinProject) {
|
|
168
|
-
// @
|
|
168
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect workspace-root-relative in-project candidate
|
|
169
169
|
inProjectCandidates.push(codebaseBoundary.candidate);
|
|
170
170
|
}
|
|
171
171
|
return inProjectCandidates;
|
|
@@ -177,12 +177,12 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
177
177
|
function anyInProjectCandidateExists(inProjectCandidates) {
|
|
178
178
|
return inProjectCandidates.some(
|
|
179
179
|
/**
|
|
180
|
-
* @
|
|
180
|
+
* @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-SAFE
|
|
181
181
|
*/
|
|
182
182
|
(p) => {
|
|
183
183
|
const exists = fs.existsSync(p);
|
|
184
184
|
if (!exists) {
|
|
185
|
-
// @
|
|
185
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Safely handle non-existent candidate without throwing
|
|
186
186
|
}
|
|
187
187
|
return exists;
|
|
188
188
|
});
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import type { Rule } from "eslint";
|
|
2
1
|
/**
|
|
3
2
|
* Create a fixer function that inserts a @story annotation before the target node.
|
|
4
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
4
|
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
6
5
|
*/
|
|
7
|
-
export declare function createAddStoryFix(target: any): (fixer: any) => any;
|
|
6
|
+
export declare function createAddStoryFix(target: any, annotationTemplate: string): (fixer: any) => any;
|
|
8
7
|
/**
|
|
9
8
|
* Create a fixer function for class method annotations.
|
|
10
9
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
11
10
|
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
12
11
|
*/
|
|
13
|
-
export declare function createMethodFix(node: any): (fixer: any) => any;
|
|
12
|
+
export declare function createMethodFix(node: any, annotationTemplate: string): (fixer: any) => any;
|
|
14
13
|
/**
|
|
15
14
|
* Default set of node types to check for missing @story annotations.
|
|
16
15
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -21,15 +20,3 @@ export declare const DEFAULT_SCOPE: string[];
|
|
|
21
20
|
* Allowed values for export priority option.
|
|
22
21
|
*/
|
|
23
22
|
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;
|
|
@@ -3,15 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = void 0;
|
|
4
4
|
exports.createAddStoryFix = createAddStoryFix;
|
|
5
5
|
exports.createMethodFix = createMethodFix;
|
|
6
|
-
exports.reportMissing = reportMissing;
|
|
7
|
-
exports.reportMethod = reportMethod;
|
|
8
|
-
const require_story_helpers_1 = require("./require-story-helpers");
|
|
9
6
|
/**
|
|
10
7
|
* Create a fixer function that inserts a @story annotation before the target node.
|
|
11
8
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
12
9
|
* @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
|
|
13
10
|
*/
|
|
14
|
-
function createAddStoryFix(target) {
|
|
11
|
+
function createAddStoryFix(target, annotationTemplate) {
|
|
15
12
|
/**
|
|
16
13
|
* Fixer that inserts a @story annotation before the target node.
|
|
17
14
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -29,7 +26,7 @@ function createAddStoryFix(target) {
|
|
|
29
26
|
? target.range[0]
|
|
30
27
|
: 0
|
|
31
28
|
: 0;
|
|
32
|
-
return fixer.insertTextBeforeRange([start, start], `${
|
|
29
|
+
return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n`);
|
|
33
30
|
}
|
|
34
31
|
return addStoryFixer;
|
|
35
32
|
}
|
|
@@ -38,7 +35,7 @@ function createAddStoryFix(target) {
|
|
|
38
35
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
39
36
|
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
40
37
|
*/
|
|
41
|
-
function createMethodFix(node) {
|
|
38
|
+
function createMethodFix(node, annotationTemplate) {
|
|
42
39
|
/**
|
|
43
40
|
* Fixer that inserts a @story annotation before a method node.
|
|
44
41
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -56,7 +53,7 @@ function createMethodFix(node) {
|
|
|
56
53
|
? node.range[0]
|
|
57
54
|
: 0
|
|
58
55
|
: 0;
|
|
59
|
-
return fixer.insertTextBeforeRange([start, start], `${
|
|
56
|
+
return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n `);
|
|
60
57
|
}
|
|
61
58
|
return methodFixer;
|
|
62
59
|
}
|
|
@@ -76,67 +73,3 @@ exports.DEFAULT_SCOPE = [
|
|
|
76
73
|
* Allowed values for export priority option.
|
|
77
74
|
*/
|
|
78
75
|
exports.EXPORT_PRIORITY_VALUES = ["all", "exported", "non-exported"];
|
|
79
|
-
/**
|
|
80
|
-
* Report a missing @story annotation for a general function-like node.
|
|
81
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
82
|
-
* @req REQ-AUTOFIX - Report missing annotation and provide autofix using createAddStoryFix
|
|
83
|
-
*/
|
|
84
|
-
function reportMissing(context, sourceCode, node, target) {
|
|
85
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
86
|
-
// @req REQ-AUTOFIX - Prefer provided sourceCode, fallback to context.getSourceCode()
|
|
87
|
-
const sc = sourceCode || context.getSourceCode();
|
|
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"))
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
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
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Report missing @story annotation for methods
|
|
124
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
125
|
-
* @req REQ-AUTOFIX - Provide automatic fix for class method annotations
|
|
126
|
-
*/
|
|
127
|
-
function reportMethod(context, sourceCode, node, target) {
|
|
128
|
-
// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
129
|
-
// @req REQ-ANNOTATION-REQUIRED - Resolve method name for reporting, default to <unknown>
|
|
130
|
-
const name = node && node.key && node.key.name ? node.key.name : "<unknown>";
|
|
131
|
-
context.report({
|
|
132
|
-
node,
|
|
133
|
-
messageId: "missingStory",
|
|
134
|
-
data: { name },
|
|
135
|
-
suggest: [
|
|
136
|
-
{
|
|
137
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${require_story_helpers_1.ANNOTATION}`,
|
|
138
|
-
fix: createMethodFix(target ?? node),
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
});
|
|
142
|
-
}
|
|
@@ -1,7 +1,11 @@
|
|
|
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";
|
|
@@ -11,7 +15,17 @@ import { DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES } from "./require-story-core";
|
|
|
11
15
|
* Path to the story file for annotations
|
|
12
16
|
*/
|
|
13
17
|
declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
14
|
-
|
|
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.
|
|
22
|
+
*/
|
|
23
|
+
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
|
+
declare function shouldApplyAutoFix(autoFix: boolean | undefined): boolean;
|
|
15
29
|
/**
|
|
16
30
|
* Number of physical source lines to inspect before a node when searching for @story text
|
|
17
31
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -96,6 +110,10 @@ declare function extractName(node: any): string;
|
|
|
96
110
|
* @returns {boolean} whether node should be processed
|
|
97
111
|
*/
|
|
98
112
|
declare function shouldProcessNode(node: any, scope: string[], exportPriority?: string): boolean;
|
|
113
|
+
interface ReportOptions {
|
|
114
|
+
annotationTemplateOverride?: string;
|
|
115
|
+
autoFixToggle?: boolean;
|
|
116
|
+
}
|
|
99
117
|
/**
|
|
100
118
|
* Report a missing @story annotation for a function-like node
|
|
101
119
|
* Provides a suggestion to add the annotation.
|
|
@@ -107,10 +125,13 @@ declare function shouldProcessNode(node: any, scope: string[], exportPriority?:
|
|
|
107
125
|
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
108
126
|
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
109
127
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
110
|
-
* @param {any}
|
|
111
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
128
|
+
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
112
129
|
*/
|
|
113
|
-
declare function reportMissing(context: Rule.RuleContext, sourceCode: any,
|
|
130
|
+
declare function reportMissing(context: Rule.RuleContext, sourceCode: any, config: {
|
|
131
|
+
node: any;
|
|
132
|
+
target?: any;
|
|
133
|
+
options?: ReportOptions;
|
|
134
|
+
}): void;
|
|
114
135
|
/**
|
|
115
136
|
* Report a missing @story annotation for a method-like node
|
|
116
137
|
* Provides a suggestion to update the method/interface with the annotation.
|
|
@@ -125,13 +146,16 @@ declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node:
|
|
|
125
146
|
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
126
147
|
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
127
148
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
128
|
-
* @param {any}
|
|
129
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
149
|
+
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
130
150
|
*/
|
|
131
|
-
declare function reportMethod(context: Rule.RuleContext, sourceCode: any,
|
|
151
|
+
declare function reportMethod(context: Rule.RuleContext, sourceCode: any, config: {
|
|
152
|
+
node: any;
|
|
153
|
+
target?: any;
|
|
154
|
+
options?: ReportOptions;
|
|
155
|
+
}): void;
|
|
132
156
|
/**
|
|
133
157
|
* Explicit exports for require-story-annotation consumers
|
|
134
158
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
135
159
|
* @req REQ-ANNOTATION-REQUIRED - Explicitly export helper functions and constants used by requiring modules
|
|
136
160
|
*/
|
|
137
|
-
export { STORY_PATH,
|
|
161
|
+
export { STORY_PATH, getAnnotationTemplate, shouldApplyAutoFix, LOOKBACK_LINES, FALLBACK_WINDOW, isExportedNode, jsdocHasStory, commentsBeforeHasStory, leadingCommentsHasStory, hasStoryAnnotation, getNodeName, extractName, resolveTargetNode, shouldProcessNode, reportMissing, reportMethod, DEFAULT_SCOPE, EXPORT_PRIORITY_VALUES, linesBeforeHasStory, parentChainHasStory, fallbackTextBeforeHasStory, };
|
|
@@ -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.FALLBACK_WINDOW = exports.LOOKBACK_LINES = exports.
|
|
3
|
+
exports.fallbackTextBeforeHasStory = exports.parentChainHasStory = exports.linesBeforeHasStory = exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = exports.getNodeName = exports.FALLBACK_WINDOW = exports.LOOKBACK_LINES = 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;
|
|
@@ -25,8 +27,27 @@ Object.defineProperty(exports, "EXPORT_PRIORITY_VALUES", { enumerable: true, get
|
|
|
25
27
|
*/
|
|
26
28
|
const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
|
|
27
29
|
exports.STORY_PATH = STORY_PATH;
|
|
28
|
-
|
|
29
|
-
|
|
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
|
+
*/
|
|
35
|
+
function getAnnotationTemplate(override) {
|
|
36
|
+
if (typeof override === "string" && override.trim().length > 0) {
|
|
37
|
+
return override.trim();
|
|
38
|
+
}
|
|
39
|
+
return `/** @story ${STORY_PATH} */`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Determine whether auto-fix should be applied.
|
|
43
|
+
* Explicit false disables auto-fix; all other values enable it.
|
|
44
|
+
*/
|
|
45
|
+
function shouldApplyAutoFix(autoFix) {
|
|
46
|
+
if (autoFix === false) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
30
51
|
/**
|
|
31
52
|
* Number of physical source lines to inspect before a node when searching for @story text
|
|
32
53
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
@@ -245,10 +266,10 @@ function shouldProcessNode(node, scope, exportPriority = "all") {
|
|
|
245
266
|
* @req REQ-ERROR-SPECIFIC - Error reports must include both name and functionName in the data payload for specific function context
|
|
246
267
|
* @param {Rule.RuleContext} context - ESLint rule context used to report
|
|
247
268
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
248
|
-
* @param {any}
|
|
249
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
269
|
+
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
250
270
|
*/
|
|
251
|
-
function reportMissing(context, sourceCode,
|
|
271
|
+
function reportMissing(context, sourceCode, config) {
|
|
272
|
+
const { node, target: passedTarget, options = {} } = config;
|
|
252
273
|
try {
|
|
253
274
|
const functionName = extractName(node && (node.id || node.key) ? node.id || node.key : node);
|
|
254
275
|
if (hasStoryAnnotation(sourceCode, node)) {
|
|
@@ -259,15 +280,19 @@ function reportMissing(context, sourceCode, node, passedTarget) {
|
|
|
259
280
|
const nameNode = (node.id && node.id.type === "Identifier" && node.id) ||
|
|
260
281
|
(node.key && node.key.type === "Identifier" && node.key) ||
|
|
261
282
|
node;
|
|
283
|
+
const effectiveTemplate = getAnnotationTemplate(options.annotationTemplateOverride);
|
|
284
|
+
const allowFix = shouldApplyAutoFix(options.autoFixToggle);
|
|
262
285
|
context.report({
|
|
263
286
|
node: nameNode,
|
|
264
287
|
messageId: "missingStory",
|
|
265
288
|
data: { name, functionName: name },
|
|
266
|
-
fix:
|
|
289
|
+
fix: allowFix
|
|
290
|
+
? (0, require_story_core_1.createAddStoryFix)(resolvedTarget, effectiveTemplate)
|
|
291
|
+
: undefined,
|
|
267
292
|
suggest: [
|
|
268
293
|
{
|
|
269
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${
|
|
270
|
-
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget),
|
|
294
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
295
|
+
fix: (0, require_story_core_1.createAddStoryFix)(resolvedTarget, effectiveTemplate),
|
|
271
296
|
},
|
|
272
297
|
],
|
|
273
298
|
});
|
|
@@ -290,10 +315,10 @@ function reportMissing(context, sourceCode, node, passedTarget) {
|
|
|
290
315
|
* @req REQ-ERROR-CONTEXT - Method error reports must include functionName data for consistent error context
|
|
291
316
|
* @param {Rule.RuleContext} context - ESLint rule context to report
|
|
292
317
|
* @param {any} sourceCode - ESLint sourceCode object
|
|
293
|
-
* @param {any}
|
|
294
|
-
* @param {any} [passedTarget] - optional AST node to use as insertion target instead of resolving from node
|
|
318
|
+
* @param {{ node: any; target?: any; options?: ReportOptions }} config - configuration containing the node to report, optional insertion target, and optional report options
|
|
295
319
|
*/
|
|
296
|
-
function reportMethod(context, sourceCode,
|
|
320
|
+
function reportMethod(context, sourceCode, config) {
|
|
321
|
+
const { node, target: passedTarget, options = {} } = config;
|
|
297
322
|
try {
|
|
298
323
|
if (hasStoryAnnotation(sourceCode, node)) {
|
|
299
324
|
return;
|
|
@@ -301,15 +326,19 @@ function reportMethod(context, sourceCode, node, passedTarget) {
|
|
|
301
326
|
const resolvedTarget = passedTarget ?? resolveTargetNode(sourceCode, node);
|
|
302
327
|
const name = extractName(node);
|
|
303
328
|
const nameNode = (node.key && node.key.type === "Identifier" && node.key) || node;
|
|
329
|
+
const effectiveTemplate = getAnnotationTemplate(options.annotationTemplateOverride);
|
|
330
|
+
const allowFix = shouldApplyAutoFix(options.autoFixToggle);
|
|
304
331
|
context.report({
|
|
305
332
|
node: nameNode,
|
|
306
333
|
messageId: "missingStory",
|
|
307
334
|
data: { name, functionName: name },
|
|
308
|
-
fix:
|
|
335
|
+
fix: allowFix
|
|
336
|
+
? (0, require_story_core_1.createMethodFix)(resolvedTarget, effectiveTemplate)
|
|
337
|
+
: undefined,
|
|
309
338
|
suggest: [
|
|
310
339
|
{
|
|
311
|
-
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${
|
|
312
|
-
fix: (0, require_story_core_1.createMethodFix)(resolvedTarget),
|
|
340
|
+
desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
|
|
341
|
+
fix: (0, require_story_core_1.createMethodFix)(resolvedTarget, effectiveTemplate),
|
|
313
342
|
},
|
|
314
343
|
],
|
|
315
344
|
});
|
|
@@ -27,7 +27,14 @@ function buildFunctionDeclarationVisitor(context, sourceCode, options) {
|
|
|
27
27
|
if (!options.shouldProcessNode(node))
|
|
28
28
|
return;
|
|
29
29
|
const target = (0, require_story_helpers_1.resolveTargetNode)(sourceCode, node);
|
|
30
|
-
(0, require_story_helpers_1.reportMissing)(context, sourceCode,
|
|
30
|
+
(0, require_story_helpers_1.reportMissing)(context, sourceCode, {
|
|
31
|
+
node,
|
|
32
|
+
target,
|
|
33
|
+
options: {
|
|
34
|
+
annotationTemplateOverride: options.annotationTemplate,
|
|
35
|
+
autoFixToggle: options.autoFix,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
31
38
|
}
|
|
32
39
|
return {
|
|
33
40
|
FunctionDeclaration: handleFunctionDeclaration,
|
|
@@ -55,7 +62,14 @@ function buildFunctionExpressionVisitor(context, sourceCode, options) {
|
|
|
55
62
|
if (node.parent && node.parent.type === "MethodDefinition")
|
|
56
63
|
return;
|
|
57
64
|
const target = (0, require_story_helpers_1.resolveTargetNode)(sourceCode, node);
|
|
58
|
-
(0, require_story_helpers_1.reportMissing)(context, sourceCode,
|
|
65
|
+
(0, require_story_helpers_1.reportMissing)(context, sourceCode, {
|
|
66
|
+
node,
|
|
67
|
+
target,
|
|
68
|
+
options: {
|
|
69
|
+
annotationTemplateOverride: options.annotationTemplate,
|
|
70
|
+
autoFixToggle: options.autoFix,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
59
73
|
}
|
|
60
74
|
return {
|
|
61
75
|
FunctionExpression: handleFunctionExpression,
|
|
@@ -76,7 +90,14 @@ function buildArrowFunctionVisitor(context, sourceCode, options) {
|
|
|
76
90
|
if (!options.shouldProcessNode(node))
|
|
77
91
|
return;
|
|
78
92
|
const target = (0, require_story_helpers_1.resolveTargetNode)(sourceCode, node);
|
|
79
|
-
(0, require_story_helpers_1.reportMissing)(context, sourceCode,
|
|
93
|
+
(0, require_story_helpers_1.reportMissing)(context, sourceCode, {
|
|
94
|
+
node,
|
|
95
|
+
target,
|
|
96
|
+
options: {
|
|
97
|
+
annotationTemplateOverride: options.annotationTemplate,
|
|
98
|
+
autoFixToggle: options.autoFix,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
80
101
|
}
|
|
81
102
|
return {
|
|
82
103
|
ArrowFunctionExpression: handleArrowFunctionExpression,
|
|
@@ -96,7 +117,14 @@ function buildTSDeclareFunctionVisitor(context, sourceCode, options) {
|
|
|
96
117
|
function handleTSDeclareFunction(node) {
|
|
97
118
|
if (!options.shouldProcessNode(node))
|
|
98
119
|
return;
|
|
99
|
-
(0, require_story_helpers_1.reportMissing)(context, sourceCode,
|
|
120
|
+
(0, require_story_helpers_1.reportMissing)(context, sourceCode, {
|
|
121
|
+
node,
|
|
122
|
+
target: node,
|
|
123
|
+
options: {
|
|
124
|
+
annotationTemplateOverride: options.annotationTemplate,
|
|
125
|
+
autoFixToggle: options.autoFix,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
100
128
|
}
|
|
101
129
|
return {
|
|
102
130
|
TSDeclareFunction: handleTSDeclareFunction,
|
|
@@ -117,7 +145,14 @@ function buildTSMethodSignatureVisitor(context, sourceCode, options) {
|
|
|
117
145
|
if (!options.shouldProcessNode(node))
|
|
118
146
|
return;
|
|
119
147
|
const target = (0, require_story_helpers_1.resolveTargetNode)(sourceCode, node);
|
|
120
|
-
(0, require_story_helpers_1.reportMissing)(context, sourceCode,
|
|
148
|
+
(0, require_story_helpers_1.reportMissing)(context, sourceCode, {
|
|
149
|
+
node,
|
|
150
|
+
target,
|
|
151
|
+
options: {
|
|
152
|
+
annotationTemplateOverride: options.methodAnnotationTemplate ?? options.annotationTemplate,
|
|
153
|
+
autoFixToggle: options.autoFix,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
121
156
|
}
|
|
122
157
|
return {
|
|
123
158
|
TSMethodSignature: handleTSMethodSignature,
|
|
@@ -137,7 +172,13 @@ function buildMethodDefinitionVisitor(context, sourceCode, options) {
|
|
|
137
172
|
function handleMethodDefinition(node) {
|
|
138
173
|
if (!options.shouldProcessNode(node))
|
|
139
174
|
return;
|
|
140
|
-
(0, require_story_helpers_1.reportMethod)(context, sourceCode,
|
|
175
|
+
(0, require_story_helpers_1.reportMethod)(context, sourceCode, {
|
|
176
|
+
node,
|
|
177
|
+
options: {
|
|
178
|
+
annotationTemplateOverride: options.methodAnnotationTemplate ?? options.annotationTemplate,
|
|
179
|
+
autoFixToggle: options.autoFix,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
141
182
|
}
|
|
142
183
|
return {
|
|
143
184
|
MethodDefinition: handleMethodDefinition,
|