Skip to content

Commit 0ba54f0

Browse files
committed
Validate "no content before tag" rule
1 parent fa8d50c commit 0ba54f0

4 files changed

Lines changed: 43 additions & 4 deletions

File tree

packages/annotation-comments/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ The function follows these steps to process the code:
388388
389389
- The function goes through the given code line by line, looking for strings that match the annotation comment syntax. If a match is found, it will:
390390
- Extract the annotation name, optional target search query, and optional relative target range from the annotation tag
391-
- Ensure that the current annotation tag has not been ignored by an ´ignore-tags` directive. If it has, it will skip the tag and continue searching
391+
- Ensure that the current annotation tag has not been ignored by an `ignore-tags` directive. If it has, it will skip the tag and continue searching
392392
- If given, call the `validateAnnotationName` handler function to check if the annotation name is valid. If this function returns `false`, skip the tag and continue searching
393393
- **Handle the current annotation tag if it's inside a single-line comment:** Try to find the beginning sequence of a single-line comment directly before the annotation tag, with no non-whitespace character before and after the beginning sequence. If found, it will:
394394
- Mark the location of the beginning sequence as beginning of the comment

packages/annotation-comments/src/parsers/comment-types/multi-line.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,37 @@ function findCommentSyntaxMatches(options: {
176176
// Validate all syntax requirements for the given line
177177
commentSyntaxMatches.forEach((match, index) => {
178178
const syntax = multiLineCommentSyntaxes[index]
179+
// If the current syntax has a continuation line start requirement,
180+
// validate it on non-opening and non-closing lines
179181
if (
180-
// Check matches that are still valid and that have a continuation line requirement
181182
!match.invalid &&
182183
syntax.continuationLineStart &&
183184
// Only check the requirement on non-opening and non-closing lines
184185
lineIndex !== match.openingRange?.start.line &&
185186
lineIndex !== match.closingRange?.start.line &&
186-
// If the line doesn't match the continuation syntax, mark the match as invalid
187+
// If the line doesn't match the continuation syntax, mark the syntax match as invalid
187188
!line.match(syntax.continuationLineStart)
188189
) {
189190
match.invalid = true
190191
}
192+
// If we're looking for an opening sequence and we're on the tag line,
193+
// validate that there is no content (except whitespace) before the tag
194+
if (
195+
!match.invalid &&
196+
type === 'opening' &&
197+
// Only check the tag line (which is the one with `endColumn` defined)
198+
endColumn !== undefined
199+
) {
200+
// Get content between the opening sequence (if found on this line) and the tag
201+
const openingEndColumn = match.openingRangeWithWhitespace?.end.line === lineIndex ? match.openingRangeWithWhitespace?.end.column : undefined
202+
let contentBeforeTag = line.slice(openingEndColumn, endColumn)
203+
// Strip the continuation line start syntax if it's present
204+
if (!openingEndColumn && syntax.continuationLineStart) {
205+
contentBeforeTag = contentBeforeTag.replace(syntax.continuationLineStart, '')
206+
}
207+
// If there is non-whitespace content before the tag, mark the syntax match as invalid
208+
if (contentBeforeTag.trim()) match.invalid = true
209+
}
191210
})
192211

193212
return foundNewMatches

packages/annotation-comments/test/parent-comment.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,26 @@ describe('parseParentComment()', () => {
2020
expect(getParentComment(`someCode() //[!note] Invalid syntax`)).toEqual(undefined)
2121
})
2222
test('Content between comment opening and annotation tag', () => {
23-
expect(getParentComment(`someCode() // Hi [!note] This won't work`)).toEqual(undefined)
23+
expect(getParentComment(`someCode() // Hi [!note] This will not work`)).toEqual(undefined)
24+
})
25+
})
26+
describe('Multi-line comment syntax', () => {
27+
test('Content between the opening syntax and the annotation tag', () => {
28+
expect(getParentComment(`/* Hi [!note] This will not work */`)).toEqual(undefined)
29+
expect(getParentComment(`someCode() /* Hi [!note] This will not work */`)).toEqual(undefined)
30+
})
31+
test('Content between the beginning of the line and the annotation tag', () => {
32+
expect(
33+
getParentComment(
34+
[
35+
'someCode()',
36+
'/*',
37+
// Content before the annotation tag
38+
'Hi [!note] This will not work',
39+
'*/',
40+
].join('\n')
41+
)
42+
).toEqual(undefined)
2443
})
2544
})
2645
})

packages/annotation-comments/test/parse.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ describe('parseAnnotationComments()', () => {
88
test('Todo', () => {
99
expect(true).toBe(true)
1010
})
11+
// TODO: We also need to implement and test the `[!ignore-tags]` logic
1112
})

0 commit comments

Comments
 (0)