@@ -3811,14 +3811,42 @@ module ts {
38113811 case SyntaxKind . ClassKeyword :
38123812 case SyntaxKind . EnumKeyword :
38133813 return StatementFlags . Statement ;
3814+
3815+ // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
3816+ // however, an identifier cannot be followed by another identifier on the same line. This is what we
3817+ // count on to parse out the respective declarations. For instance, we exploit this to say that
3818+ //
3819+ // namespace n
3820+ //
3821+ // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
3822+ //
3823+ // namespace
3824+ // n
3825+ //
3826+ // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
3827+ // We need to look one token ahead to see if it permissible to try parsing a declaration.
3828+ //
3829+ // *Note*: 'interface' is actually a strict mode reserved word. So while
3830+ //
3831+ // "use strict"
3832+ // interface
3833+ // I {}
3834+ //
3835+ // could be legal, it would add complexity for very little gain.
38143836 case SyntaxKind . InterfaceKeyword :
38153837 case SyntaxKind . TypeKeyword :
3816- nextToken ( ) ;
3817- return isIdentifierOrKeyword ( ) ? StatementFlags . Statement : StatementFlags . None ;
3838+ return nextTokenIsIdentifierOnSameLine ( ) ? StatementFlags . Statement : StatementFlags . None ;
38183839 case SyntaxKind . ModuleKeyword :
38193840 case SyntaxKind . NamespaceKeyword :
3841+ return nextTokenIsIdentifierOrStringLiteralOnSameLine ( ) ? StatementFlags . ModuleElement : StatementFlags . None ;
3842+ case SyntaxKind . DeclareKeyword :
38203843 nextToken ( ) ;
3821- return isIdentifierOrKeyword ( ) || token === SyntaxKind . StringLiteral ? StatementFlags . ModuleElement : StatementFlags . None ;
3844+ // ASI takes effect for this modifier.
3845+ if ( scanner . hasPrecedingLineBreak ( ) ) {
3846+ return StatementFlags . None ;
3847+ }
3848+ continue ;
3849+
38223850 case SyntaxKind . ImportKeyword :
38233851 nextToken ( ) ;
38243852 return token === SyntaxKind . StringLiteral || token === SyntaxKind . AsteriskToken ||
@@ -3831,7 +3859,6 @@ module ts {
38313859 return StatementFlags . ModuleElement ;
38323860 }
38333861 continue ;
3834- case SyntaxKind . DeclareKeyword :
38353862 case SyntaxKind . PublicKeyword :
38363863 case SyntaxKind . PrivateKeyword :
38373864 case SyntaxKind . ProtectedKeyword :
@@ -3982,6 +4009,11 @@ module ts {
39824009 case SyntaxKind . AtToken :
39834010 return parseDeclaration ( ) ;
39844011
4012+ case SyntaxKind . InterfaceKeyword :
4013+ case SyntaxKind . TypeKeyword :
4014+ case SyntaxKind . ModuleKeyword :
4015+ case SyntaxKind . NamespaceKeyword :
4016+ case SyntaxKind . DeclareKeyword :
39854017 case SyntaxKind . ConstKeyword :
39864018 case SyntaxKind . EnumKeyword :
39874019 case SyntaxKind . ExportKeyword :
@@ -3994,45 +4026,6 @@ module ts {
39944026 return parseDeclaration ( ) ;
39954027 }
39964028 break ;
3997-
3998- // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
3999- // however, an identifier cannot be followed by another identifier on the same line. This is what we
4000- // count on to parse out the respective declarations. For instance, we exploit this to say that
4001- //
4002- // namespace n
4003- //
4004- // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
4005- //
4006- // namespace
4007- // n
4008- //
4009- // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
4010- // We need to look one token ahead to see if it permissible to try parsing a declaration.
4011- //
4012- // *Note*: 'interface' is actually a strict mode reserved word. So while
4013- //
4014- // "use strict"
4015- // interface
4016- // I {}
4017- //
4018- // could be legal, it would add complexity for very little gain.
4019- case SyntaxKind . DeclareKeyword :
4020- if ( lookAhead ( nextTokenIsIdentifierOrKeywordOnSameLine ) && getDeclarationFlags ( ) & flags ) {
4021- return parseDeclaration ( ) ;
4022- }
4023- break ;
4024- case SyntaxKind . ModuleKeyword :
4025- if ( lookAhead ( nextTokenIsIdentifierOrStringLiteralOnSameLine ) && getDeclarationFlags ( ) & flags ) {
4026- return parseDeclaration ( ) ;
4027- }
4028- break ;
4029- case SyntaxKind . InterfaceKeyword :
4030- case SyntaxKind . NamespaceKeyword :
4031- case SyntaxKind . TypeKeyword :
4032- if ( lookAhead ( nextTokenIsIdentifierOnSameLine ) && getDeclarationFlags ( ) & flags ) {
4033- return parseDeclaration ( ) ;
4034- }
4035- break ;
40364029 }
40374030 return parseExpressionOrLabeledStatement ( ) ;
40384031 }
0 commit comments