Skip to content

Commit 7304258

Browse files
authored
fix: align rule implementations with typescript-eslint (#502)
1 parent fb86153 commit 7304258

19 files changed

Lines changed: 5995 additions & 602 deletions

internal/plugins/typescript/rules/ban_ts_comment/ban_ts_comment.go

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,10 @@ func checkComment(ctx rule.RuleContext, commentText string, commentStart int, co
237237
afterDirective = withoutClosing
238238
}
239239

240-
// Check if there's a description
240+
// Description is everything after the directive, trimmed of whitespace only.
241+
// Separators like ':' and '--' are part of the description (included in length).
241242
description := strings.TrimSpace(afterDirective)
242243

243-
// Remove leading separators (: -- etc.)
244-
description = strings.TrimLeft(description, ": \t-")
245-
description = strings.TrimSpace(description)
246-
247244
// Special case: for ts-ignore with no description allowed, suggest ts-expect-error
248245
if directiveType == "ignore" && !config.AllowWithDescription {
249246
ctx.ReportRange(
@@ -268,28 +265,15 @@ func checkComment(ctx rule.RuleContext, commentText string, commentStart int, co
268265
return
269266
}
270267

271-
// If description is required
268+
// If description is required, check minimum length (handles both empty and too-short)
272269
if config.AllowWithDescription {
273-
// Check if description exists
274-
if len(description) == 0 {
275-
ctx.ReportRange(
276-
core.NewTextRange(commentStart, commentStart+len(commentText)),
277-
rule.RuleMessage{
278-
Id: "tsDirectiveCommentRequiresDescription",
279-
Description: "Include a description after the '@" + directiveName + "' directive to explain why the '@" + directiveName + "' is necessary. The description must be " + formatMinimumDescLength(minDescLength) + " characters long.",
280-
},
281-
)
282-
return
283-
}
284-
285-
// Check minimum description length (counting grapheme clusters for Unicode)
286270
descLength := graphemeLength(description)
287271
if descLength < minDescLength {
288272
ctx.ReportRange(
289273
core.NewTextRange(commentStart, commentStart+len(commentText)),
290274
rule.RuleMessage{
291-
Id: "tsDirectiveCommentDescriptionNotMatchPattern",
292-
Description: "The description for the '@" + directiveName + "' directive must be " + formatMinimumDescLength(minDescLength) + " characters long.",
275+
Id: "tsDirectiveCommentRequiresDescription",
276+
Description: "Include a description after the '@" + directiveName + "' directive to explain why the '@" + directiveName + "' is necessary. The description must be " + formatMinimumDescLength(minDescLength) + " characters long.",
293277
},
294278
)
295279
return
@@ -299,10 +283,7 @@ func checkComment(ctx rule.RuleContext, commentText string, commentStart int, co
299283
if config.DescriptionFormat != "" {
300284
formatRegex, err := regexp.Compile(config.DescriptionFormat)
301285
if err == nil {
302-
// For format checking, we need to check the original afterDirective text
303-
// to preserve the exact format (including leading colons, etc.)
304-
checkText := strings.TrimSpace(afterDirective)
305-
if !formatRegex.MatchString(checkText) {
286+
if !formatRegex.MatchString(description) {
306287
ctx.ReportRange(
307288
core.NewTextRange(commentStart, commentStart+len(commentText)),
308289
rule.RuleMessage{

internal/plugins/typescript/rules/ban_ts_comment/ban_ts_comment_test.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ func TestBanTsCommentRule(t *testing.T) {
2626
{Code: "// @ts-expect-error: This is a very long description that exceeds minimum\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description", "minimumDescriptionLength": 10}},
2727
{Code: "// @ts-expect-error 0123456789012345678901\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description", "minimumDescriptionLength": 21}},
2828

29+
// Description length includes colon separator (": ab" = 4 chars >= 3)
30+
{Code: "// @ts-expect-error: ab\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description"}},
31+
// Description length includes dash separator ("-- ab" = 5 chars >= 3)
32+
{Code: "// @ts-expect-error -- ab\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description"}},
33+
// Colon with single char (": a" = 3 chars, exactly at minimum)
34+
{Code: "// @ts-expect-error: a\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description"}},
35+
// Multi-line with colon separator
36+
{Code: "/* @ts-expect-error: ab */\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": "allow-with-description"}},
37+
2938
// ts-expect-error - description format
3039
{Code: "// @ts-expect-error: TS1234 because reasons\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": map[string]interface{}{"descriptionFormat": "^: TS\\d+ because .+$"}}},
3140
{Code: "// @ts-expect-error: TS2345 because type mismatch\nconst a = 0;", Options: map[string]interface{}{"ts-expect-error": map[string]interface{}{"descriptionFormat": "^: TS\\d+ because .+$"}}},
@@ -96,17 +105,41 @@ func TestBanTsCommentRule(t *testing.T) {
96105

97106
// ts-expect-error - description too short
98107
{
99-
Code: "// @ts-expect-error: ab\nconst a = 0;",
108+
Code: "// @ts-expect-error ab\nconst a = 0;",
100109
Options: map[string]interface{}{"ts-expect-error": "allow-with-description"},
101110
Errors: []rule_tester.InvalidTestCaseError{
102-
{MessageId: "tsDirectiveCommentDescriptionNotMatchPattern"},
111+
{MessageId: "tsDirectiveCommentRequiresDescription"},
103112
},
104113
},
105114
{
106115
Code: "// @ts-expect-error 0123456789012345678\nconst a = 0;",
107116
Options: map[string]interface{}{"ts-expect-error": "allow-with-description", "minimumDescriptionLength": 21},
108117
Errors: []rule_tester.InvalidTestCaseError{
109-
{MessageId: "tsDirectiveCommentDescriptionNotMatchPattern"},
118+
{MessageId: "tsDirectiveCommentRequiresDescription"},
119+
},
120+
},
121+
// Just colon, no real description (length 1 < 3)
122+
{
123+
Code: "// @ts-expect-error:\nconst a = 0;",
124+
Options: map[string]interface{}{"ts-expect-error": "allow-with-description"},
125+
Errors: []rule_tester.InvalidTestCaseError{
126+
{MessageId: "tsDirectiveCommentRequiresDescription"},
127+
},
128+
},
129+
// Just dashes, too short (length 2 < 3)
130+
{
131+
Code: "// @ts-expect-error --\nconst a = 0;",
132+
Options: map[string]interface{}{"ts-expect-error": "allow-with-description"},
133+
Errors: []rule_tester.InvalidTestCaseError{
134+
{MessageId: "tsDirectiveCommentRequiresDescription"},
135+
},
136+
},
137+
// Colon + space only (": " trimmed to ":" = length 1 < 3)
138+
{
139+
Code: "// @ts-expect-error: \nconst a = 0;",
140+
Options: map[string]interface{}{"ts-expect-error": "allow-with-description"},
141+
Errors: []rule_tester.InvalidTestCaseError{
142+
{MessageId: "tsDirectiveCommentRequiresDescription"},
110143
},
111144
},
112145

@@ -133,12 +166,12 @@ func TestBanTsCommentRule(t *testing.T) {
133166
},
134167
},
135168

136-
// ts-expect-error - Unicode/emoji too short
169+
// ts-expect-error - Unicode/emoji too short (": 💩💩💩" = 6 runes, but with minimumDescriptionLength: 8)
137170
{
138171
Code: "// @ts-expect-error: 💩💩💩\nconst a = 0;",
139-
Options: map[string]interface{}{"ts-expect-error": "allow-with-description", "minimumDescriptionLength": 4},
172+
Options: map[string]interface{}{"ts-expect-error": "allow-with-description", "minimumDescriptionLength": 8},
140173
Errors: []rule_tester.InvalidTestCaseError{
141-
{MessageId: "tsDirectiveCommentDescriptionNotMatchPattern"},
174+
{MessageId: "tsDirectiveCommentRequiresDescription"},
142175
},
143176
},
144177

0 commit comments

Comments
 (0)