Skip to content

Commit a76f6f6

Browse files
Copilotjakebailey
andcommitted
Fix JS syntactic diagnostics for null/undefined literals and type arguments in heritage clauses
Co-authored-by: jakebailey <[email protected]>
1 parent b48403d commit a76f6f6

File tree

119 files changed

+346
-2752
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+346
-2752
lines changed

internal/parser/js_diagnostics.go

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,26 @@ func (v *jsDiagnosticsVisitor) walkNodeForJSDiagnosticsWorker(node *ast.Node) bo
7676
}
7777
case ast.KindNullKeyword, ast.KindUndefinedKeyword:
7878
// Only flag null/undefined when used in type context, not as literal values
79-
if ast.IsPartOfTypeNode(node) {
79+
// Check if this is actually used as a type annotation by examining the parent context
80+
if v.isUsedAsTypeAnnotation(node) {
8081
v.diagnostics = append(v.diagnostics, v.createDiagnosticForNode(node, diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files))
8182
return false
8283
}
8384
case ast.KindExpressionWithTypeArguments:
84-
// Only flag when it's actually part of a type expression (implements clause), not extends clause
85+
// In heritage clauses, flag as type annotation error if it has type arguments
86+
if parent.Kind == ast.KindHeritageClause &&
87+
node.AsExpressionWithTypeArguments() != nil &&
88+
node.AsExpressionWithTypeArguments().TypeArguments != nil {
89+
v.diagnostics = append(v.diagnostics, v.createDiagnosticForNode(node, diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files))
90+
return false
91+
}
92+
// Use the standard type node check for other cases (e.g., implements clauses)
8593
if ast.IsPartOfTypeNode(node) {
8694
v.diagnostics = append(v.diagnostics, v.createDiagnosticForNode(node, diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files))
8795
return false
8896
}
8997
}
90-
98+
9199
// Check for type nodes in the type node range
92100
if node.Kind >= ast.KindFirstTypeNode && node.Kind <= ast.KindLastTypeNode {
93101
// Skip ExpressionWithTypeArguments as it's handled above
@@ -199,7 +207,6 @@ func (v *jsDiagnosticsVisitor) walkNodeForJSDiagnosticsWorker(node *ast.Node) bo
199207
return false
200208
}
201209

202-
203210
// isSignatureDeclaration checks if a node is a signature declaration (function without body)
204211
func (v *jsDiagnosticsVisitor) isSignatureDeclaration(node *ast.Node) bool {
205212
switch node.Kind {
@@ -237,7 +244,7 @@ func (v *jsDiagnosticsVisitor) getTypeParameters(node *ast.Node) *ast.NodeList {
237244
}
238245

239246
var typeParameters *ast.NodeList
240-
247+
241248
// Try class-like nodes first
242249
if classLike := node.ClassLikeData(); classLike != nil {
243250
typeParameters = classLike.TypeParameters
@@ -272,11 +279,11 @@ func (v *jsDiagnosticsVisitor) getTypeArguments(node *ast.Node) *ast.NodeList {
272279
}
273280

274281
var typeArguments *ast.NodeList
275-
282+
276283
// Handle specific node types that can have type arguments
277284
switch node.Kind {
278285
case ast.KindCallExpression, ast.KindNewExpression, ast.KindTaggedTemplateExpression,
279-
ast.KindJsxOpeningElement, ast.KindJsxSelfClosingElement:
286+
ast.KindJsxOpeningElement, ast.KindJsxSelfClosingElement:
280287
if ast.IsCallLikeExpression(node) {
281288
typeArguments = node.TypeArgumentList()
282289
}
@@ -386,6 +393,60 @@ func (v *jsDiagnosticsVisitor) checkModifier(modifier *ast.Node, isConstValid bo
386393
}
387394
}
388395

396+
// isUsedAsTypeAnnotation checks if a node is used as a type annotation rather than a literal value
397+
func (v *jsDiagnosticsVisitor) isUsedAsTypeAnnotation(node *ast.Node) bool {
398+
parent := node.Parent
399+
if parent == nil {
400+
return false
401+
}
402+
403+
// Check parent context to determine if this is a type annotation
404+
switch parent.Kind {
405+
case ast.KindUnionType, ast.KindIntersectionType, ast.KindConditionalType,
406+
ast.KindMappedType, ast.KindIndexedAccessType, ast.KindTypeReference,
407+
ast.KindTypePredicate, ast.KindTypeOperator, ast.KindInferType:
408+
return true
409+
case ast.KindParameter:
410+
// Check if this is the type annotation of a parameter
411+
if param := parent.AsParameterDeclaration(); param != nil && param.Type == node {
412+
return true
413+
}
414+
case ast.KindVariableDeclaration:
415+
// Check if this is the type annotation of a variable
416+
if varDecl := parent.AsVariableDeclaration(); varDecl != nil && varDecl.Type == node {
417+
return true
418+
}
419+
case ast.KindPropertyDeclaration:
420+
// Check if this is the type annotation of a property
421+
if propDecl := parent.AsPropertyDeclaration(); propDecl != nil && propDecl.Type == node {
422+
return true
423+
}
424+
case ast.KindMethodDeclaration, ast.KindFunctionDeclaration, ast.KindArrowFunction, ast.KindFunctionExpression:
425+
// Check if this is the return type annotation
426+
if fnLike := parent.FunctionLikeData(); fnLike != nil && fnLike.Type == node {
427+
return true
428+
}
429+
case ast.KindTypeAssertionExpression:
430+
// Check if this is the type in a type assertion
431+
if typeAssertion := parent.AsTypeAssertion(); typeAssertion != nil && typeAssertion.Type == node {
432+
return true
433+
}
434+
case ast.KindAsExpression:
435+
// Check if this is the type in an 'as' expression
436+
if asExpression := parent.AsAsExpression(); asExpression != nil && asExpression.Type == node {
437+
return true
438+
}
439+
case ast.KindSatisfiesExpression:
440+
// Check if this is the type in a 'satisfies' expression
441+
if satisfiesExpression := parent.AsSatisfiesExpression(); satisfiesExpression != nil && satisfiesExpression.Type == node {
442+
return true
443+
}
444+
}
445+
446+
// If none of the above type annotation contexts match, this is likely a literal value
447+
return false
448+
}
449+
389450
// createDiagnosticForNode creates a diagnostic for a specific node
390451
func (v *jsDiagnosticsVisitor) createDiagnosticForNode(node *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic {
391452
return ast.NewDiagnostic(v.sourceFile, scanner.GetErrorRangeForNode(v.sourceFile, node), message, args...)

testdata/baselines/reference/compiler/superCallInJSWithWrongBaseTypeArgumentCount1(strict=false).errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
error TS5055: Cannot write file 'b.js' because it would overwrite input file.
22
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
3-
b.js(3,25): error TS8010: Type annotations can only be used in TypeScript files.
43
b.js(9,25): error TS8010: Type annotations can only be used in TypeScript files.
54
b.js(15,25): error TS8010: Type annotations can only be used in TypeScript files.
65

@@ -10,12 +9,10 @@ b.js(15,25): error TS8010: Type annotations can only be used in TypeScript files
109
==== a.ts (0 errors) ====
1110
export class A<T> {}
1211

13-
==== b.js (3 errors) ====
12+
==== b.js (2 errors) ====
1413
import { A } from './a.js';
1514

1615
export class B1 extends A {
17-
~
18-
!!! error TS8010: Type annotations can only be used in TypeScript files.
1916
constructor() {
2017
super();
2118
}

testdata/baselines/reference/compiler/superCallInJSWithWrongBaseTypeArgumentCount1(strict=true).errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
error TS5055: Cannot write file 'b.js' because it would overwrite input file.
22
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
3-
b.js(3,25): error TS8010: Type annotations can only be used in TypeScript files.
43
b.js(3,25): error TS8026: Expected A<T> type arguments; provide these with an '@extends' tag.
54
b.js(9,25): error TS8010: Type annotations can only be used in TypeScript files.
65
b.js(15,25): error TS8010: Type annotations can only be used in TypeScript files.
@@ -12,13 +11,11 @@ b.js(15,25): error TS8026: Expected A<T> type arguments; provide these with an '
1211
==== a.ts (0 errors) ====
1312
export class A<T> {}
1413

15-
==== b.js (5 errors) ====
14+
==== b.js (4 errors) ====
1615
import { A } from './a.js';
1716

1817
export class B1 extends A {
1918
~
20-
!!! error TS8010: Type annotations can only be used in TypeScript files.
21-
~
2219
!!! error TS8026: Expected A<T> type arguments; provide these with an '@extends' tag.
2320
constructor() {
2421
super();

testdata/baselines/reference/compiler/superCallInJSWithWrongBaseTypeArgumentCount2(strict=false).errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
error TS5055: Cannot write file 'b.js' because it would overwrite input file.
22
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
3-
b.js(4,25): error TS8010: Type annotations can only be used in TypeScript files.
43
b.js(11,25): error TS8010: Type annotations can only be used in TypeScript files.
54
b.js(18,25): error TS8010: Type annotations can only be used in TypeScript files.
65

@@ -10,13 +9,11 @@ b.js(18,25): error TS8010: Type annotations can only be used in TypeScript files
109
==== a.ts (0 errors) ====
1110
export class A<T> {}
1211

13-
==== b.js (3 errors) ====
12+
==== b.js (2 errors) ====
1413
import { A } from './a.js';
1514

1615
/** @extends {A} */
1716
export class B1 extends A {
18-
~
19-
!!! error TS8010: Type annotations can only be used in TypeScript files.
2017
constructor() {
2118
super();
2219
}

testdata/baselines/reference/compiler/superCallInJSWithWrongBaseTypeArgumentCount2(strict=true).errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
error TS5055: Cannot write file 'b.js' because it would overwrite input file.
22
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
3-
b.js(4,25): error TS8010: Type annotations can only be used in TypeScript files.
43
b.js(4,25): error TS8026: Expected A<T> type arguments; provide these with an '@extends' tag.
54
b.js(11,25): error TS8010: Type annotations can only be used in TypeScript files.
65
b.js(18,25): error TS8010: Type annotations can only be used in TypeScript files.
@@ -12,14 +11,12 @@ b.js(18,25): error TS8026: Expected A<T> type arguments; provide these with an '
1211
==== a.ts (0 errors) ====
1312
export class A<T> {}
1413

15-
==== b.js (5 errors) ====
14+
==== b.js (4 errors) ====
1615
import { A } from './a.js';
1716

1817
/** @extends {A} */
1918
export class B1 extends A {
2019
~
21-
!!! error TS8010: Type annotations can only be used in TypeScript files.
22-
~
2320
!!! error TS8026: Expected A<T> type arguments; provide these with an '@extends' tag.
2421
constructor() {
2522
super();

testdata/baselines/reference/submodule/compiler/argumentsReferenceInConstructor3_Js.errors.txt

Lines changed: 0 additions & 33 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/argumentsReferenceInMethod3_Js.errors.txt

Lines changed: 0 additions & 29 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/checkIndexConstraintOfJavascriptClassExpression.errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
error TS5102: Option 'outFile' has been removed. Please remove it from your configuration.
22
weird.js(1,1): error TS2552: Cannot find name 'someFunction'. Did you mean 'Function'?
33
weird.js(1,23): error TS7006: Parameter 'BaseClass' implicitly has an 'any' type.
4-
weird.js(4,25): error TS8010: Type annotations can only be used in TypeScript files.
54
weird.js(9,17): error TS7006: Parameter 'error' implicitly has an 'any' type.
65

76

87
!!! error TS5102: Option 'outFile' has been removed. Please remove it from your configuration.
9-
==== weird.js (4 errors) ====
8+
==== weird.js (3 errors) ====
109
someFunction(function(BaseClass) {
1110
~~~~~~~~~~~~
1211
!!! error TS2552: Cannot find name 'someFunction'. Did you mean 'Function'?
@@ -16,8 +15,6 @@ weird.js(9,17): error TS7006: Parameter 'error' implicitly has an 'any' type.
1615
'use strict';
1716
const DEFAULT_MESSAGE = "nop!";
1817
class Hello extends BaseClass {
19-
~~~~~~~~~
20-
!!! error TS8010: Type annotations can only be used in TypeScript files.
2118
constructor() {
2219
super();
2320
this.foo = "bar";

testdata/baselines/reference/submodule/compiler/checkJsFiles_noErrorLocation.errors.txt

Lines changed: 0 additions & 25 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/classExtendingAny.errors.txt

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)