eslint-plugin-traceability 1.19.1 → 1.19.3

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 CHANGED
@@ -1,10 +1,9 @@
1
- ## [1.19.1](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.19.0...v1.19.1) (2025-12-18)
1
+ ## [1.19.3](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.19.2...v1.19.3) (2025-12-18)
2
2
 
3
3
 
4
4
  ### Bug Fixes
5
5
 
6
- * apply inside placement semantics to loop branches ([e0ba06f](https://github.com/voder-ai/eslint-plugin-traceability/commit/e0ba06fb9aba6947c6ac675f65cc1fb4639dc785))
7
- * honor inside placement for catch clauses in branch annotation rule ([0e7a8e0](https://github.com/voder-ai/eslint-plugin-traceability/commit/0e7a8e01505bfa1e37e013dfda00e866f975ad33))
6
+ * support inside placement for switch cases in branch helpers ([3fd08d1](https://github.com/voder-ai/eslint-plugin-traceability/commit/3fd08d1314085a7aa9894f6248dbb7f42a07bda0))
8
7
 
9
8
  # Changelog
10
9
 
@@ -9,7 +9,8 @@ exports.reportMissingReq = reportMissingReq;
9
9
  const branch_annotation_report_helpers_1 = require("./branch-annotation-report-helpers");
10
10
  Object.defineProperty(exports, "reportMissingAnnotations", { enumerable: true, get: function () { return branch_annotation_report_helpers_1.reportMissingAnnotations; } });
11
11
  const branch_annotation_loop_helpers_1 = require("./branch-annotation-loop-helpers");
12
- const PRE_COMMENT_OFFSET = 2; // number of lines above branch to inspect for comments
12
+ const branch_annotation_if_helpers_1 = require("./branch-annotation-if-helpers");
13
+ const branch_annotation_switch_helpers_1 = require("./branch-annotation-switch-helpers");
13
14
  /**
14
15
  * Valid branch types for require-branch-annotation rule.
15
16
  * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
@@ -153,14 +154,6 @@ function scanCommentLinesInRange(lines, startIndex, endIndexInclusive) {
153
154
  }
154
155
  return comments.join(" ");
155
156
  }
156
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
157
- function isElseIfBranch(node, parent) {
158
- return (node &&
159
- node.type === "IfStatement" &&
160
- parent &&
161
- parent.type === "IfStatement" &&
162
- parent.alternate === node);
163
- }
164
157
  function getInsideCatchCommentText(sourceCode, node) {
165
158
  const getCommentsInside = sourceCode.getCommentsInside;
166
159
  if (node.body && typeof getCommentsInside === "function") {
@@ -186,6 +179,30 @@ function getInsideCatchCommentText(sourceCode, node) {
186
179
  }
187
180
  return "";
188
181
  }
182
+ /**
183
+ * Gather comment text from the first contiguous comment lines inside a TryStatement block body.
184
+ * @supports docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md REQ-INSIDE-BRACE-PLACEMENT REQ-PLACEMENT-CONFIG
185
+ */
186
+ function getInsideTryBlockCommentText(sourceCode, node) {
187
+ const block = node && node.block;
188
+ if (!block ||
189
+ block.type !== "BlockStatement" ||
190
+ !block.loc ||
191
+ !block.loc.start ||
192
+ !block.loc.end ||
193
+ typeof block.loc.start.line !== "number" ||
194
+ typeof block.loc.end.line !== "number") {
195
+ return "";
196
+ }
197
+ const lines = sourceCode.lines;
198
+ const startIndex = block.loc.start.line - 1;
199
+ const endIndex = block.loc.end.line - 1;
200
+ const insideText = scanCommentLinesInRange(lines, startIndex + 1, endIndex);
201
+ if (insideText) {
202
+ return insideText;
203
+ }
204
+ return "";
205
+ }
189
206
  /**
190
207
  * Gather annotation text for CatchClause nodes, supporting both before-catch and inside-catch positions.
191
208
  * @story docs/stories/025.0-DEV-CATCH-ANNOTATION-POSITION.story.md
@@ -260,144 +277,105 @@ function gatherSimpleIfCommentText(sourceCode, node, annotationPlacement, before
260
277
  }
261
278
  return "";
262
279
  }
263
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
264
- function scanElseIfPrecedingComments(sourceCode, node) {
265
- const lines = sourceCode.lines;
266
- if (!node.loc || !node.loc.start || typeof node.loc.start.line !== "number") {
267
- return "";
268
- }
269
- const startLine = node.loc.start.line - 1;
270
- const comments = [];
271
- let i = startLine - 1;
272
- let scanned = 0;
273
- while (i >= 0 && scanned < PRE_COMMENT_OFFSET) {
274
- const commentText = getCommentTextAtLine(lines, i);
275
- if (!commentText) {
276
- break;
280
+ function handleTryCatchBranch(sourceCode, node, context) {
281
+ const { annotationPlacement, beforeText } = context;
282
+ if (node.type === "TryStatement") {
283
+ if (annotationPlacement === "inside") {
284
+ const insideText = getInsideTryBlockCommentText(sourceCode, node);
285
+ if (insideText) {
286
+ return insideText;
287
+ }
288
+ return "";
277
289
  }
278
- comments.unshift(commentText);
279
- i--;
280
- scanned++;
290
+ return beforeText;
281
291
  }
282
- return comments.join(" ");
283
- }
284
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
285
- function hasValidElseIfBlockLoc(node) {
286
- const hasBlockConsequent = node.consequent &&
287
- node.consequent.type === "BlockStatement" &&
288
- node.consequent.loc &&
289
- node.consequent.loc.start;
290
- return !!(node.test &&
291
- node.test.loc &&
292
- node.test.loc.end &&
293
- hasBlockConsequent);
294
- }
295
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
296
- function scanElseIfBetweenConditionAndBody(sourceCode, node) {
297
- const lines = sourceCode.lines;
298
- const conditionEndLine = node.test.loc.end.line;
299
- const consequentStartLine = node.consequent.loc.start.line;
300
- // Lines in sourceCode are 0-based indexes, but loc.line values are 1-based.
301
- // We want to scan comments strictly between the condition and the
302
- // consequent body, so we start at the line after the condition's end and
303
- // stop at the line immediately before the consequent's starting line.
304
- const startIndex = conditionEndLine; // already the next logical line index when 0-based
305
- const endIndexExclusive = consequentStartLine - 1;
306
- if (endIndexExclusive <= startIndex) {
307
- return "";
292
+ if (node.type === "CatchClause") {
293
+ return gatherCatchClauseCommentText(sourceCode, node, annotationPlacement, beforeText);
308
294
  }
309
- return scanCommentLinesInRange(lines, startIndex, endIndexExclusive - 1);
295
+ return null;
310
296
  }
311
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
312
- function scanElseIfInsideBlockComments(sourceCode, node) {
313
- const lines = sourceCode.lines;
314
- const consequentStartLine = node.consequent.loc.start.line;
315
- const comments = [];
316
- // Intentionally start from the block's start line (using the same 1-based line value as provided by the parser)
317
- // so that, when indexing into sourceCode.lines, this corresponds to the first logical line inside the block body
318
- // for typical formatter layouts.
319
- let lineIndex = consequentStartLine;
320
- while (lineIndex < lines.length) {
321
- if (!collectCommentLine(lines, lineIndex, comments)) {
322
- break;
323
- }
324
- lineIndex++;
297
+ function handleLoopBranch(sourceCode, node, context) {
298
+ const { annotationPlacement, beforeText } = context;
299
+ if (node.type === "ForStatement" ||
300
+ node.type === "ForInStatement" ||
301
+ node.type === "ForOfStatement" ||
302
+ node.type === "WhileStatement" ||
303
+ node.type === "DoWhileStatement") {
304
+ return (0, branch_annotation_loop_helpers_1.gatherLoopCommentText)(sourceCode, node, annotationPlacement, beforeText);
325
305
  }
326
- return comments.join(" ");
306
+ return null;
327
307
  }
328
308
  /**
329
- * Gather annotation text for IfStatement else-if branches, supporting comments placed
330
- * before the else keyword, between the else-if condition and the consequent body,
331
- * and in the first comment-only lines inside the consequent block body.
332
- * @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
333
- * @supports REQ-DUAL-POSITION-DETECTION
334
- * @supports REQ-FALLBACK-LOGIC
309
+ * Helper that gathers comment text for non-IfStatement branch types using
310
+ * straightforward behavior (SwitchCase, CatchClause, and loop statements).
311
+ * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
312
+ * @supports REQ-COMMENT-ASSOCIATION
313
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
314
+ * @supports REQ-PLACEMENT-CONFIG
335
315
  */
336
- function gatherElseIfCommentText(sourceCode, node, parent, beforeText) {
337
- if (beforeText &&
338
- (/@story\b/.test(beforeText) ||
339
- /@req\b/.test(beforeText) ||
340
- /@supports\b/.test(beforeText))) {
341
- return beforeText;
342
- }
343
- if (!isElseIfBranch(node, parent)) {
344
- return beforeText;
345
- }
346
- const beforeElseText = scanElseIfPrecedingComments(sourceCode, node);
347
- if (beforeElseText &&
348
- (/@story\b/.test(beforeElseText) ||
349
- /@req\b/.test(beforeElseText) ||
350
- /@supports\b/.test(beforeElseText))) {
351
- return beforeElseText;
352
- }
353
- if (!hasValidElseIfBlockLoc(node)) {
354
- return beforeText;
355
- }
356
- const betweenText = scanElseIfBetweenConditionAndBody(sourceCode, node);
357
- if (betweenText) {
358
- return betweenText;
316
+ function gatherNonIfBranchCommentText(sourceCode, node, context) {
317
+ if (node.type === "SwitchCase") {
318
+ const { annotationPlacement, beforeText } = context;
319
+ return (0, branch_annotation_switch_helpers_1.gatherSwitchCaseCommentText)(sourceCode, node, annotationPlacement, beforeText);
359
320
  }
360
- const insideText = scanElseIfInsideBlockComments(sourceCode, node);
361
- if (insideText) {
362
- return insideText;
321
+ const tryCatchResult = handleTryCatchBranch(sourceCode, node, context);
322
+ if (tryCatchResult != null) {
323
+ return tryCatchResult;
363
324
  }
364
- return beforeText;
365
- }
366
- /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
367
- function gatherSwitchCaseCommentText(sourceCode, node) {
368
- const lines = sourceCode.lines;
369
- const startLine = node.loc.start.line;
370
- let i = startLine - PRE_COMMENT_OFFSET;
371
- const comments = [];
372
- while (i >= 0 && /^\s*(\/\/|\/\*)/.test(lines[i])) {
373
- comments.unshift(lines[i].trim());
374
- i--;
325
+ const loopResult = handleLoopBranch(sourceCode, node, context);
326
+ if (loopResult != null) {
327
+ return loopResult;
375
328
  }
376
- return comments.join(" ");
329
+ return null;
377
330
  }
378
- function gatherBranchCommentTextByType(sourceCode, node, parent, context) {
331
+ /**
332
+ * Helper that gathers comment text for IfStatement branches, including both
333
+ * simple if and else-if specific logic.
334
+ * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
335
+ * @supports REQ-COMMENT-ASSOCIATION
336
+ * @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
337
+ * @supports REQ-DUAL-POSITION-DETECTION
338
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
339
+ * @supports REQ-PLACEMENT-CONFIG
340
+ * @supports REQ-DEFAULT-BACKWARD-COMPAT
341
+ */
342
+ function gatherIfBranchCommentText(sourceCode, node, parent, context) {
379
343
  const { annotationPlacement, beforeText } = context;
380
- if (node.type === "SwitchCase") {
381
- return gatherSwitchCaseCommentText(sourceCode, node);
344
+ if (node.type !== "IfStatement") {
345
+ return null;
382
346
  }
383
- if (node.type === "CatchClause") {
384
- return gatherCatchClauseCommentText(sourceCode, node, annotationPlacement, beforeText);
347
+ if ((0, branch_annotation_if_helpers_1.isElseIfBranch)(node, parent)) {
348
+ return (0, branch_annotation_if_helpers_1.gatherElseIfCommentText)(sourceCode, node, parent, {
349
+ annotationPlacement,
350
+ beforeText,
351
+ });
385
352
  }
386
- if (node.type === "IfStatement") {
387
- if (isElseIfBranch(node, parent)) {
388
- return gatherElseIfCommentText(sourceCode, node, parent, beforeText);
389
- }
390
- return gatherSimpleIfCommentText(sourceCode, node, annotationPlacement, beforeText);
353
+ return gatherSimpleIfCommentText(sourceCode, node, annotationPlacement, beforeText);
354
+ }
355
+ /**
356
+ * Internal helper that performs type-based dispatch for gathering branch comment text.
357
+ * This keeps the public gatherBranchCommentTextByType wrapper small for ESLint limits.
358
+ * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
359
+ * @supports REQ-COMMENT-ASSOCIATION
360
+ * @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
361
+ * @supports REQ-DUAL-POSITION-DETECTION
362
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
363
+ * @supports REQ-PLACEMENT-CONFIG
364
+ */
365
+ function gatherBranchCommentTextByTypeInternal(sourceCode, node, parent, context) {
366
+ const nonIfResult = gatherNonIfBranchCommentText(sourceCode, node, context);
367
+ if (nonIfResult != null) {
368
+ return nonIfResult;
391
369
  }
392
- if (node.type === "ForStatement" ||
393
- node.type === "ForInStatement" ||
394
- node.type === "ForOfStatement" ||
395
- node.type === "WhileStatement" ||
396
- node.type === "DoWhileStatement") {
397
- return (0, branch_annotation_loop_helpers_1.gatherLoopCommentText)(sourceCode, node, annotationPlacement, beforeText);
370
+ const ifResult = gatherIfBranchCommentText(sourceCode, node, parent, context);
371
+ if (ifResult != null) {
372
+ return ifResult;
398
373
  }
399
374
  return null;
400
375
  }
376
+ function gatherBranchCommentTextByType(sourceCode, node, parent, context) {
377
+ return gatherBranchCommentTextByTypeInternal(sourceCode, node, parent, context);
378
+ }
401
379
  /**
402
380
  * Gather leading comment text for a branch node.
403
381
  * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
@@ -0,0 +1,12 @@
1
+ import type { Rule } from "eslint";
2
+ import type { AnnotationPlacement } from "./branch-annotation-helpers";
3
+ export declare function isElseIfBranch(node: any, parent: any | undefined): boolean;
4
+ export declare function hasValidElseIfBlockLoc(node: any): boolean;
5
+ export declare function scanElseIfPrecedingComments(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any): string;
6
+ export declare function scanElseIfBetweenConditionAndBody(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any): string;
7
+ export declare function scanElseIfInsideBlockComments(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any): string;
8
+ export declare function getInsideElseIfCommentText(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any): string;
9
+ export declare function gatherElseIfCommentText(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any, parent: any | undefined, options: {
10
+ annotationPlacement: AnnotationPlacement;
11
+ beforeText: string;
12
+ }): string;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isElseIfBranch = isElseIfBranch;
4
+ exports.hasValidElseIfBlockLoc = hasValidElseIfBlockLoc;
5
+ exports.scanElseIfPrecedingComments = scanElseIfPrecedingComments;
6
+ exports.scanElseIfBetweenConditionAndBody = scanElseIfBetweenConditionAndBody;
7
+ exports.scanElseIfInsideBlockComments = scanElseIfInsideBlockComments;
8
+ exports.getInsideElseIfCommentText = getInsideElseIfCommentText;
9
+ exports.gatherElseIfCommentText = gatherElseIfCommentText;
10
+ const branch_annotation_helpers_1 = require("./branch-annotation-helpers");
11
+ /**
12
+ * Small shared helpers for IfStatement/else-if specific annotation handling.
13
+ * Extracted from branch-annotation-helpers to keep that file within ESLint
14
+ * max-lines limits while preserving behaviour.
15
+ *
16
+ * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
17
+ * @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
18
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
19
+ */
20
+ const PRE_COMMENT_OFFSET = 2; // kept in sync with main helpers
21
+ function getCommentTextAtLine(lines, index) {
22
+ const line = lines[index];
23
+ if (!line || !line.trim()) {
24
+ return null;
25
+ }
26
+ if (!/^\s*(\/\/|\/\*)/.test(line)) {
27
+ return null;
28
+ }
29
+ return line.trim();
30
+ }
31
+ function isElseIfBranch(node, parent) {
32
+ return (node &&
33
+ node.type === "IfStatement" &&
34
+ parent &&
35
+ parent.type === "IfStatement" &&
36
+ parent.alternate === node);
37
+ }
38
+ function hasValidElseIfBlockLoc(node) {
39
+ const hasBlockConsequent = node.consequent &&
40
+ node.consequent.type === "BlockStatement" &&
41
+ node.consequent.loc &&
42
+ node.consequent.loc.start;
43
+ return !!(node.test &&
44
+ node.test.loc &&
45
+ node.test.loc.end &&
46
+ hasBlockConsequent);
47
+ }
48
+ function scanElseIfPrecedingComments(sourceCode, node) {
49
+ const lines = sourceCode.lines;
50
+ if (!node.loc || !node.loc.start || typeof node.loc.start.line !== "number") {
51
+ return "";
52
+ }
53
+ const startLine = node.loc.start.line - 1;
54
+ const comments = [];
55
+ let i = startLine - 1;
56
+ let scanned = 0;
57
+ while (i >= 0 && scanned < PRE_COMMENT_OFFSET) {
58
+ const commentText = getCommentTextAtLine(lines, i);
59
+ if (!commentText) {
60
+ break;
61
+ }
62
+ comments.unshift(commentText);
63
+ i--;
64
+ scanned++;
65
+ }
66
+ return comments.join(" ");
67
+ }
68
+ function scanElseIfBetweenConditionAndBody(sourceCode, node) {
69
+ const lines = sourceCode.lines;
70
+ const conditionEndLine = node.test.loc.end.line;
71
+ const consequentStartLine = node.consequent.loc.start.line;
72
+ const startIndex = conditionEndLine;
73
+ const endIndexExclusive = consequentStartLine - 1;
74
+ if (endIndexExclusive <= startIndex) {
75
+ return "";
76
+ }
77
+ return (0, branch_annotation_helpers_1.scanCommentLinesInRange)(lines, startIndex, endIndexExclusive - 1);
78
+ }
79
+ function scanElseIfInsideBlockComments(sourceCode, node) {
80
+ const lines = sourceCode.lines;
81
+ const consequentStartLine = node.consequent.loc.start.line;
82
+ const comments = [];
83
+ let lineIndex = consequentStartLine;
84
+ while (lineIndex < lines.length) {
85
+ const lineText = getCommentTextAtLine(lines, lineIndex);
86
+ if (!lineText) {
87
+ break;
88
+ }
89
+ comments.push(lineText);
90
+ lineIndex++;
91
+ }
92
+ return comments.join(" ");
93
+ }
94
+ function getInsideElseIfCommentText(sourceCode, node) {
95
+ if (!hasValidElseIfBlockLoc(node)) {
96
+ return "";
97
+ }
98
+ const insideText = scanElseIfInsideBlockComments(sourceCode, node);
99
+ if (insideText) {
100
+ return insideText;
101
+ }
102
+ return "";
103
+ }
104
+ function gatherElseIfCommentText(sourceCode, node, parent, options) {
105
+ const { annotationPlacement, beforeText } = options;
106
+ if (!isElseIfBranch(node, parent)) {
107
+ return beforeText;
108
+ }
109
+ if (annotationPlacement === "inside") {
110
+ return getInsideElseIfCommentText(sourceCode, node);
111
+ }
112
+ if (beforeText &&
113
+ (/@story\b/.test(beforeText) ||
114
+ /@req\b/.test(beforeText) ||
115
+ /@supports\b/.test(beforeText))) {
116
+ return beforeText;
117
+ }
118
+ const beforeElseText = scanElseIfPrecedingComments(sourceCode, node);
119
+ if (beforeElseText &&
120
+ (/@story\b/.test(beforeElseText) ||
121
+ /@req\b/.test(beforeElseText) ||
122
+ /@supports\b/.test(beforeElseText))) {
123
+ return beforeElseText;
124
+ }
125
+ if (!hasValidElseIfBlockLoc(node)) {
126
+ return beforeText;
127
+ }
128
+ const betweenText = scanElseIfBetweenConditionAndBody(sourceCode, node);
129
+ if (betweenText) {
130
+ return betweenText;
131
+ }
132
+ const insideText = scanElseIfInsideBlockComments(sourceCode, node);
133
+ if (insideText) {
134
+ return insideText;
135
+ }
136
+ return beforeText;
137
+ }
@@ -83,7 +83,8 @@ function getIfStatementIndentAndInsertPos(sourceCode, node, options, context) {
83
83
  }
84
84
  const isElseIf = isElseIfBranchForInsert(node, parent);
85
85
  const isSimpleIfInsidePlacement = annotationPlacement === "inside" && !isElseIf;
86
- if (isSimpleIfInsidePlacement || isElseIf) {
86
+ if (annotationPlacement === "inside" &&
87
+ (isSimpleIfInsidePlacement || isElseIf)) {
87
88
  const commentLine = node.consequent.loc.start.line + 1;
88
89
  const commentLineInfo = getIndentAndInsertPosForLine(sourceCode, commentLine, indent);
89
90
  indent = commentLineInfo.indent;
@@ -0,0 +1,11 @@
1
+ import type { Rule } from "eslint";
2
+ import { type AnnotationPlacement } from "./branch-annotation-helpers";
3
+ /**
4
+ * Gather annotation text for SwitchCase branches, honoring the configured placement
5
+ * while preserving legacy before-branch behavior in the default mode.
6
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
7
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
8
+ * @supports REQ-PLACEMENT-CONFIG
9
+ * @supports REQ-INSIDE-BRACE-PLACEMENT
10
+ */
11
+ export declare function gatherSwitchCaseCommentText(sourceCode: ReturnType<Rule.RuleContext["getSourceCode"]>, node: any, annotationPlacement: AnnotationPlacement, beforeText: string): string;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.gatherSwitchCaseCommentText = gatherSwitchCaseCommentText;
4
+ const branch_annotation_helpers_1 = require("./branch-annotation-helpers");
5
+ /**
6
+ * Gather comment text from the first contiguous comment lines "inside" a SwitchCase body.
7
+ * Prefers a BlockStatement consequent when present, with a fallback to the entire case range.
8
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
9
+ * @supports REQ-INSIDE-BRACE-PLACEMENT
10
+ * @supports REQ-PLACEMENT-CONFIG
11
+ */
12
+ function getInsideSwitchCaseCommentText(sourceCode, node) {
13
+ const lines = sourceCode.lines;
14
+ const firstConsequent = node.consequent && node.consequent[0];
15
+ if (firstConsequent &&
16
+ firstConsequent.type === "BlockStatement" &&
17
+ firstConsequent.loc &&
18
+ firstConsequent.loc.start &&
19
+ firstConsequent.loc.end &&
20
+ typeof firstConsequent.loc.start.line === "number" &&
21
+ typeof firstConsequent.loc.end.line === "number") {
22
+ const startIndex = firstConsequent.loc.start.line - 1;
23
+ const endIndex = firstConsequent.loc.end.line - 1;
24
+ const insideText = (0, branch_annotation_helpers_1.scanCommentLinesInRange)(lines, startIndex + 1, endIndex);
25
+ if (insideText) {
26
+ return insideText;
27
+ }
28
+ return "";
29
+ }
30
+ if (node.loc &&
31
+ node.loc.start &&
32
+ node.loc.end &&
33
+ typeof node.loc.start.line === "number" &&
34
+ typeof node.loc.end.line === "number") {
35
+ const startIndex = node.loc.start.line - 1;
36
+ const endIndex = node.loc.end.line - 1;
37
+ const insideText = (0, branch_annotation_helpers_1.scanCommentLinesInRange)(lines, startIndex + 1, endIndex);
38
+ if (insideText) {
39
+ return insideText;
40
+ }
41
+ }
42
+ return "";
43
+ }
44
+ /**
45
+ * Gather annotation text for SwitchCase branches, honoring the configured placement
46
+ * while preserving legacy before-branch behavior in the default mode.
47
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
48
+ * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
49
+ * @supports REQ-PLACEMENT-CONFIG
50
+ * @supports REQ-INSIDE-BRACE-PLACEMENT
51
+ */
52
+ function gatherSwitchCaseCommentText(sourceCode, node, annotationPlacement, beforeText) {
53
+ if (annotationPlacement === "inside") {
54
+ const insideText = getInsideSwitchCaseCommentText(sourceCode, node);
55
+ if (insideText) {
56
+ return insideText;
57
+ }
58
+ return "";
59
+ }
60
+ if (/@story\b/.test(beforeText) ||
61
+ /@req\b/.test(beforeText) ||
62
+ /@supports\b/.test(beforeText)) {
63
+ return beforeText;
64
+ }
65
+ // In before-placement mode, rely on the caller's beforeText and any
66
+ // configured PRE_COMMENT_OFFSET logic in the main helpers module.
67
+ return beforeText;
68
+ }