Skip to content

Commit 06331b5

Browse files
committed
Report all the js file errors and skip only the nodes that are not allowed in js
Fixes #11800
1 parent d896d3f commit 06331b5

File tree

6 files changed

+133
-143
lines changed

6 files changed

+133
-143
lines changed

src/compiler/program.ts

Lines changed: 106 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -773,48 +773,89 @@ namespace ts {
773773
function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
774774
return runWithCancellationToken(() => {
775775
const diagnostics: Diagnostic[] = [];
776+
let parent: Node = sourceFile;
776777
walk(sourceFile);
777778

778779
return diagnostics;
779780

780-
function walk(node: Node): boolean {
781-
if (!node) {
782-
return false;
781+
function walk(node: Node) {
782+
// Return directly from the case if the given node doesnt want to visit each child
783+
// Otherwise break to visit each child
784+
785+
switch (parent.kind) {
786+
case SyntaxKind.Parameter:
787+
case SyntaxKind.PropertyDeclaration:
788+
if ((<ParameterDeclaration | PropertyDeclaration>parent).questionToken === node) {
789+
diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_can_only_be_used_in_a_ts_file, "?"));
790+
return;
791+
}
792+
793+
// Pass through
794+
case SyntaxKind.MethodDeclaration:
795+
case SyntaxKind.MethodSignature:
796+
case SyntaxKind.Constructor:
797+
case SyntaxKind.GetAccessor:
798+
case SyntaxKind.SetAccessor:
799+
case SyntaxKind.FunctionExpression:
800+
case SyntaxKind.FunctionDeclaration:
801+
case SyntaxKind.ArrowFunction:
802+
case SyntaxKind.FunctionDeclaration:
803+
case SyntaxKind.VariableDeclaration:
804+
// type annotation
805+
if ((<FunctionLikeDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration>parent).type === node) {
806+
diagnostics.push(createDiagnosticForNode(node, Diagnostics.types_can_only_be_used_in_a_ts_file));
807+
return;
808+
}
783809
}
784810

785811
switch (node.kind) {
786812
case SyntaxKind.ImportEqualsDeclaration:
787813
diagnostics.push(createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_a_ts_file));
788-
return true;
814+
return;
789815
case SyntaxKind.ExportAssignment:
790816
if ((<ExportAssignment>node).isExportEquals) {
791817
diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_a_ts_file));
792-
return true;
793-
}
794-
break;
795-
case SyntaxKind.ClassDeclaration:
796-
let classDeclaration = <ClassDeclaration>node;
797-
if (checkModifiers(classDeclaration.modifiers) ||
798-
checkTypeParameters(classDeclaration.typeParameters)) {
799-
return true;
818+
return;
800819
}
801820
break;
802821
case SyntaxKind.HeritageClause:
803822
let heritageClause = <HeritageClause>node;
804823
if (heritageClause.token === SyntaxKind.ImplementsKeyword) {
805824
diagnostics.push(createDiagnosticForNode(node, Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file));
806-
return true;
825+
return;
807826
}
808827
break;
809828
case SyntaxKind.InterfaceDeclaration:
810829
diagnostics.push(createDiagnosticForNode(node, Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file));
811-
return true;
830+
return;
812831
case SyntaxKind.ModuleDeclaration:
813832
diagnostics.push(createDiagnosticForNode(node, Diagnostics.module_declarations_can_only_be_used_in_a_ts_file));
814-
return true;
833+
return;
815834
case SyntaxKind.TypeAliasDeclaration:
816835
diagnostics.push(createDiagnosticForNode(node, Diagnostics.type_aliases_can_only_be_used_in_a_ts_file));
817-
return true;
836+
return;
837+
case SyntaxKind.EnumDeclaration:
838+
diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
839+
return;
840+
case SyntaxKind.TypeAssertionExpression:
841+
let typeAssertionExpression = <TypeAssertion>node;
842+
diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
843+
return;
844+
}
845+
846+
const prevParent = parent;
847+
parent = node;
848+
forEachChild(node, walk, walkArray);
849+
parent = prevParent;
850+
}
851+
852+
function walkArray(nodes: NodeArray<Node>) {
853+
if (parent.decorators === nodes && !options.experimentalDecorators) {
854+
diagnostics.push(createDiagnosticForNode(parent, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning));
855+
}
856+
857+
switch (parent.kind) {
858+
case SyntaxKind.ClassDeclaration:
818859
case SyntaxKind.MethodDeclaration:
819860
case SyntaxKind.MethodSignature:
820861
case SyntaxKind.Constructor:
@@ -824,124 +865,76 @@ namespace ts {
824865
case SyntaxKind.FunctionDeclaration:
825866
case SyntaxKind.ArrowFunction:
826867
case SyntaxKind.FunctionDeclaration:
827-
const functionDeclaration = <FunctionLikeDeclaration>node;
828-
if (checkModifiers(functionDeclaration.modifiers) ||
829-
checkTypeParameters(functionDeclaration.typeParameters) ||
830-
checkTypeAnnotation(functionDeclaration.type)) {
831-
return true;
868+
// Check type parameters
869+
if (nodes === (<ClassDeclaration | FunctionLikeDeclaration>parent).typeParameters) {
870+
diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file));
871+
return;
832872
}
833-
break;
873+
// pass through
834874
case SyntaxKind.VariableStatement:
835-
const variableStatement = <VariableStatement>node;
836-
if (checkModifiers(variableStatement.modifiers)) {
837-
return true;
838-
}
839-
break;
840-
case SyntaxKind.VariableDeclaration:
841-
const variableDeclaration = <VariableDeclaration>node;
842-
if (checkTypeAnnotation(variableDeclaration.type)) {
843-
return true;
844-
}
845-
break;
846-
case SyntaxKind.CallExpression:
847-
case SyntaxKind.NewExpression:
848-
const expression = <CallExpression>node;
849-
if (expression.typeArguments && expression.typeArguments.length > 0) {
850-
const start = expression.typeArguments.pos;
851-
diagnostics.push(createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start,
852-
Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
853-
return true;
854-
}
855-
break;
856-
case SyntaxKind.Parameter:
857-
const parameter = <ParameterDeclaration>node;
858-
if (parameter.modifiers) {
859-
const start = parameter.modifiers.pos;
860-
diagnostics.push(createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start,
861-
Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
862-
return true;
863-
}
864-
if (parameter.questionToken) {
865-
diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics._0_can_only_be_used_in_a_ts_file, "?"));
866-
return true;
867-
}
868-
if (parameter.type) {
869-
diagnostics.push(createDiagnosticForNode(parameter.type, Diagnostics.types_can_only_be_used_in_a_ts_file));
870-
return true;
875+
// Check modifiers
876+
if (nodes === (<ClassDeclaration | FunctionLikeDeclaration | VariableStatement>parent).modifiers) {
877+
return checkModifiers(<NodeArray<Modifier>>nodes);
871878
}
872879
break;
873880
case SyntaxKind.PropertyDeclaration:
874-
const propertyDeclaration = <PropertyDeclaration>node;
875-
if (propertyDeclaration.modifiers) {
876-
for (const modifier of propertyDeclaration.modifiers) {
881+
// Check modifiers of property declaration
882+
if (nodes === (<PropertyDeclaration>parent).modifiers) {
883+
for (const modifier of <NodeArray<Modifier>>nodes) {
877884
if (modifier.kind !== SyntaxKind.StaticKeyword) {
878885
diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
879-
return true;
880886
}
881887
}
888+
return;
882889
}
883-
if (checkTypeAnnotation((<PropertyDeclaration>node).type)) {
884-
return true;
890+
break;
891+
case SyntaxKind.Parameter:
892+
// Check modifiers of parameter declaration
893+
if (nodes === (<ParameterDeclaration>parent).modifiers) {
894+
diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
895+
return;
885896
}
886897
break;
887-
case SyntaxKind.EnumDeclaration:
888-
diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
889-
return true;
890-
case SyntaxKind.TypeAssertionExpression:
891-
let typeAssertionExpression = <TypeAssertion>node;
892-
diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
893-
return true;
894-
case SyntaxKind.Decorator:
895-
if (!options.experimentalDecorators) {
896-
diagnostics.push(createDiagnosticForNode(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning));
898+
case SyntaxKind.CallExpression:
899+
case SyntaxKind.NewExpression:
900+
case SyntaxKind.ExpressionWithTypeArguments:
901+
// Check type arguments
902+
if (nodes === (<CallExpression | NewExpression | ExpressionWithTypeArguments>parent).typeArguments) {
903+
diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
904+
return;
897905
}
898-
return true;
906+
break;
899907
}
900908

901-
return forEachChild(node, walk);
902-
}
903-
904-
function checkTypeParameters(typeParameters: NodeArray<TypeParameterDeclaration>): boolean {
905-
if (typeParameters) {
906-
const start = typeParameters.pos;
907-
diagnostics.push(createFileDiagnostic(sourceFile, start, typeParameters.end - start, Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file));
908-
return true;
909+
for (const node of nodes) {
910+
walk(node);
909911
}
910-
return false;
911912
}
912913

913-
function checkTypeAnnotation(type: TypeNode): boolean {
914-
if (type) {
915-
diagnostics.push(createDiagnosticForNode(type, Diagnostics.types_can_only_be_used_in_a_ts_file));
916-
return true;
917-
}
918-
919-
return false;
920-
}
921-
922-
function checkModifiers(modifiers: NodeArray<Modifier>): boolean {
923-
if (modifiers) {
924-
for (const modifier of modifiers) {
925-
switch (modifier.kind) {
926-
case SyntaxKind.PublicKeyword:
927-
case SyntaxKind.PrivateKeyword:
928-
case SyntaxKind.ProtectedKeyword:
929-
case SyntaxKind.ReadonlyKeyword:
930-
case SyntaxKind.DeclareKeyword:
931-
diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
932-
return true;
933-
934-
// These are all legal modifiers.
935-
case SyntaxKind.StaticKeyword:
936-
case SyntaxKind.ExportKeyword:
937-
case SyntaxKind.ConstKeyword:
938-
case SyntaxKind.DefaultKeyword:
939-
case SyntaxKind.AbstractKeyword:
940-
}
914+
function checkModifiers(modifiers: NodeArray<Modifier>) {
915+
for (const modifier of modifiers) {
916+
switch (modifier.kind) {
917+
case SyntaxKind.PublicKeyword:
918+
case SyntaxKind.PrivateKeyword:
919+
case SyntaxKind.ProtectedKeyword:
920+
case SyntaxKind.ReadonlyKeyword:
921+
case SyntaxKind.DeclareKeyword:
922+
diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
923+
break;
924+
925+
// These are all legal modifiers.
926+
case SyntaxKind.StaticKeyword:
927+
case SyntaxKind.ExportKeyword:
928+
case SyntaxKind.ConstKeyword:
929+
case SyntaxKind.DefaultKeyword:
930+
case SyntaxKind.AbstractKeyword:
941931
}
942932
}
933+
}
943934

944-
return false;
935+
function createDiagnosticForNodeArray(nodes: NodeArray<Node>, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
936+
const start = nodes.pos;
937+
return createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2);
945938
}
946939

947940
// Since these are syntactic diagnostics, parent might not have been set
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
tests/cases/compiler/a.js(4,12): error TS8010: 'types' can only be used in a .ts file.
2+
3+
4+
==== tests/cases/compiler/a.js (1 errors) ====
5+
6+
@SomeDecorator
7+
class SomeClass {
8+
foo(x: number) {
9+
~~~~~~
10+
!!! error TS8010: 'types' can only be used in a .ts file.
11+
12+
}
13+
}

tests/baselines/reference/decoratorInJsFile.symbols

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

tests/baselines/reference/decoratorInJsFile.types

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
tests/cases/compiler/a.js(2,1): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
1+
tests/cases/compiler/a.js(3,7): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
2+
tests/cases/compiler/a.js(4,12): error TS8010: 'types' can only be used in a .ts file.
23

34

4-
==== tests/cases/compiler/a.js (1 errors) ====
5+
==== tests/cases/compiler/a.js (2 errors) ====
56

67
@SomeDecorator
7-
~~~~~~~~~~~~~~
8-
!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
98
class SomeClass {
9+
~~~~~~~~~
10+
!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.
1011
foo(x: number) {
12+
~~~~~~
13+
!!! error TS8010: 'types' can only be used in a .ts file.
1114

1215
}
1316
}

tests/cases/fourslash/server/getJavaScriptSyntacticDiagnostics02.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ verify.getSyntacticDiagnostics(`[
1515
"category": "error",
1616
"code": 8010
1717
},
18+
{
19+
"message": "\'types\' can only be used in a .ts file.",
20+
"start": 52,
21+
"length": 6,
22+
"category": "error",
23+
"code": 8010
24+
},
1825
{
1926
"message": "Variable declaration expected.",
2027
"start": 67,

0 commit comments

Comments
 (0)