@@ -773,48 +773,89 @@ namespace ts {
773
773
function getJavaScriptSyntacticDiagnosticsForFile ( sourceFile : SourceFile ) : Diagnostic [ ] {
774
774
return runWithCancellationToken ( ( ) => {
775
775
const diagnostics : Diagnostic [ ] = [ ] ;
776
+ let parent : Node = sourceFile ;
776
777
walk ( sourceFile ) ;
777
778
778
779
return diagnostics ;
779
780
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
+ }
783
809
}
784
810
785
811
switch ( node . kind ) {
786
812
case SyntaxKind . ImportEqualsDeclaration :
787
813
diagnostics . push ( createDiagnosticForNode ( node , Diagnostics . import_can_only_be_used_in_a_ts_file ) ) ;
788
- return true ;
814
+ return ;
789
815
case SyntaxKind . ExportAssignment :
790
816
if ( ( < ExportAssignment > node ) . isExportEquals ) {
791
817
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 ;
800
819
}
801
820
break ;
802
821
case SyntaxKind . HeritageClause :
803
822
let heritageClause = < HeritageClause > node ;
804
823
if ( heritageClause . token === SyntaxKind . ImplementsKeyword ) {
805
824
diagnostics . push ( createDiagnosticForNode ( node , Diagnostics . implements_clauses_can_only_be_used_in_a_ts_file ) ) ;
806
- return true ;
825
+ return ;
807
826
}
808
827
break ;
809
828
case SyntaxKind . InterfaceDeclaration :
810
829
diagnostics . push ( createDiagnosticForNode ( node , Diagnostics . interface_declarations_can_only_be_used_in_a_ts_file ) ) ;
811
- return true ;
830
+ return ;
812
831
case SyntaxKind . ModuleDeclaration :
813
832
diagnostics . push ( createDiagnosticForNode ( node , Diagnostics . module_declarations_can_only_be_used_in_a_ts_file ) ) ;
814
- return true ;
833
+ return ;
815
834
case SyntaxKind . TypeAliasDeclaration :
816
835
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 :
818
859
case SyntaxKind . MethodDeclaration :
819
860
case SyntaxKind . MethodSignature :
820
861
case SyntaxKind . Constructor :
@@ -824,124 +865,76 @@ namespace ts {
824
865
case SyntaxKind . FunctionDeclaration :
825
866
case SyntaxKind . ArrowFunction :
826
867
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 ;
832
872
}
833
- break ;
873
+ // pass through
834
874
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 ) ;
871
878
}
872
879
break ;
873
880
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 ) {
877
884
if ( modifier . kind !== SyntaxKind . StaticKeyword ) {
878
885
diagnostics . push ( createDiagnosticForNode ( modifier , Diagnostics . _0_can_only_be_used_in_a_ts_file , tokenToString ( modifier . kind ) ) ) ;
879
- return true ;
880
886
}
881
887
}
888
+ return ;
882
889
}
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 ;
885
896
}
886
897
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 ;
897
905
}
898
- return true ;
906
+ break ;
899
907
}
900
908
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 ) ;
909
911
}
910
- return false ;
911
912
}
912
913
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 :
941
931
}
942
932
}
933
+ }
943
934
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 ) ;
945
938
}
946
939
947
940
// Since these are syntactic diagnostics, parent might not have been set
0 commit comments