@@ -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
0 commit comments