@@ -1143,6 +1143,9 @@ module ts {
1143
1143
InMultiLineCommentTrivia ,
1144
1144
InSingleQuoteStringLiteral ,
1145
1145
InDoubleQuoteStringLiteral ,
1146
+ InTemplateHeadLiteral , // this could also be a NoSubstitutionTemplateLiteral
1147
+ InTemplateMiddleLiteral , //this could also be a TemplateTail
1148
+ InTemplateSubstitutionPosition ,
1146
1149
}
1147
1150
1148
1151
export enum TokenClass {
@@ -5650,12 +5653,12 @@ module ts {
5650
5653
// if there are more cases we want the classifier to be better at.
5651
5654
return true ;
5652
5655
}
5653
-
5654
- // 'classifyKeywordsInGenerics' should be 'true' when a syntactic classifier is not present.
5655
- function getClassificationsForLine ( text : string , lexState : EndOfLineState , classifyKeywordsInGenerics ?: boolean ) : ClassificationResult {
5656
+
5657
+ function getClassificationsForLine ( text : string , lexState : EndOfLineState , syntacticClassifierAbsent ?: boolean ) : ClassificationResult {
5656
5658
var offset = 0 ;
5657
5659
var token = SyntaxKind . Unknown ;
5658
5660
var lastNonTriviaToken = SyntaxKind . Unknown ;
5661
+ var templateStack : SyntaxKind [ ] ;
5659
5662
5660
5663
// If we're in a string literal, then prepend: "\
5661
5664
// (and a newline). That way when we lex we'll think we're still in a string literal.
@@ -5675,6 +5678,21 @@ module ts {
5675
5678
text = "/*\n" + text ;
5676
5679
offset = 3 ;
5677
5680
break ;
5681
+ case EndOfLineState . InTemplateHeadLiteral :
5682
+ if ( syntacticClassifierAbsent ) {
5683
+ text = "`\n" + text ;
5684
+ offset = 2 ;
5685
+ }
5686
+ break ;
5687
+ case EndOfLineState . InTemplateMiddleLiteral :
5688
+ if ( syntacticClassifierAbsent ) {
5689
+ text = "${\n" + text ;
5690
+ offset = 3 ;
5691
+ }
5692
+ // fallthrough
5693
+ case EndOfLineState . InTemplateSubstitutionPosition :
5694
+ templateStack = [ SyntaxKind . TemplateHead ] ;
5695
+ break ;
5678
5696
}
5679
5697
5680
5698
scanner . setText ( text ) ;
@@ -5739,12 +5757,50 @@ module ts {
5739
5757
token === SyntaxKind . StringKeyword ||
5740
5758
token === SyntaxKind . NumberKeyword ||
5741
5759
token === SyntaxKind . BooleanKeyword ) {
5742
- if ( angleBracketStack > 0 && ! classifyKeywordsInGenerics ) {
5743
- // If it looks like we're could be in something generic, don't classify this
5744
- // as a keyword. We may just get overwritten by the syntactic classifier,
5745
- // causing a noisy experience for the user.
5746
- token = SyntaxKind . Identifier ;
5747
- }
5760
+ if ( angleBracketStack > 0 && ! syntacticClassifierAbsent ) {
5761
+ // If it looks like we're could be in something generic, don't classify this
5762
+ // as a keyword. We may just get overwritten by the syntactic classifier,
5763
+ // causing a noisy experience for the user.
5764
+ token = SyntaxKind . Identifier ;
5765
+ }
5766
+ }
5767
+ else if ( token === SyntaxKind . TemplateHead && syntacticClassifierAbsent ) {
5768
+ if ( ! templateStack ) {
5769
+ templateStack = [ token ] ;
5770
+ }
5771
+ else {
5772
+ templateStack . push ( token ) ;
5773
+ }
5774
+ }
5775
+ else if ( token === SyntaxKind . OpenBraceToken && syntacticClassifierAbsent ) {
5776
+ // If we don't have anything on the template stack,
5777
+ // then we aren't trying to keep track of a previously scanned template head.
5778
+ if ( templateStack && templateStack . length > 0 ) {
5779
+ templateStack . push ( token ) ;
5780
+ }
5781
+ }
5782
+ else if ( token === SyntaxKind . CloseBraceToken && syntacticClassifierAbsent ) {
5783
+ // If we don't have anything on the template stack,
5784
+ // then we aren't trying to keep track of a previously scanned template head.
5785
+ if ( templateStack && templateStack . length > 0 ) {
5786
+ var lastTemplateStackToken = lastOrUndefined ( templateStack ) ;
5787
+
5788
+ if ( lastTemplateStackToken === SyntaxKind . TemplateHead ) {
5789
+ token = scanner . reScanTemplateToken ( ) ;
5790
+
5791
+ // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
5792
+ if ( token === SyntaxKind . TemplateTail ) {
5793
+ templateStack . pop ( ) ;
5794
+ }
5795
+ else {
5796
+ Debug . assert ( token === SyntaxKind . TemplateMiddle , "Should have been a template middle. Was " + token ) ;
5797
+ }
5798
+ }
5799
+ else {
5800
+ Debug . assert ( token === SyntaxKind . CloseBraceToken , "Should have been an open brace. Was: " + token ) ;
5801
+ templateStack . pop ( ) ;
5802
+ }
5803
+ }
5748
5804
}
5749
5805
5750
5806
lastNonTriviaToken = token ;
@@ -5760,7 +5816,7 @@ module ts {
5760
5816
var start = scanner . getTokenPos ( ) ;
5761
5817
var end = scanner . getTextPos ( ) ;
5762
5818
5763
- addResult ( end - start , classFromKind ( token ) ) ;
5819
+ addResult ( end - start , classFromKind ( token , syntacticClassifierAbsent ) ) ;
5764
5820
5765
5821
if ( end >= text . length ) {
5766
5822
if ( token === SyntaxKind . StringLiteral ) {
@@ -5789,6 +5845,19 @@ module ts {
5789
5845
result . finalLexState = EndOfLineState . InMultiLineCommentTrivia ;
5790
5846
}
5791
5847
}
5848
+ else if ( isTemplateLiteralKind ( token ) && syntacticClassifierAbsent ) {
5849
+ if ( scanner . isUnterminated ( ) ) {
5850
+ if ( token === SyntaxKind . TemplateMiddle ) {
5851
+ result . finalLexState = EndOfLineState . InTemplateMiddleLiteral ;
5852
+ }
5853
+ else {
5854
+ result . finalLexState = EndOfLineState . InTemplateHeadLiteral ;
5855
+ }
5856
+ }
5857
+ }
5858
+ else if ( templateStack && templateStack . length > 0 && lastOrUndefined ( templateStack ) === SyntaxKind . TemplateHead ) {
5859
+ result . finalLexState = EndOfLineState . InTemplateSubstitutionPosition ;
5860
+ }
5792
5861
}
5793
5862
}
5794
5863
@@ -5866,7 +5935,7 @@ module ts {
5866
5935
return token >= SyntaxKind . FirstKeyword && token <= SyntaxKind . LastKeyword ;
5867
5936
}
5868
5937
5869
- function classFromKind ( token : SyntaxKind ) {
5938
+ function classFromKind ( token : SyntaxKind , syntacticClassifierAbsent ?: boolean ) {
5870
5939
if ( isKeyword ( token ) ) {
5871
5940
return TokenClass . Keyword ;
5872
5941
}
@@ -5892,6 +5961,10 @@ module ts {
5892
5961
return TokenClass . Whitespace ;
5893
5962
case SyntaxKind . Identifier :
5894
5963
default :
5964
+ // Only give a classification if nothing will more accurately classify.
5965
+ if ( syntacticClassifierAbsent && isTemplateLiteralKind ( token ) ) {
5966
+ return TokenClass . StringLiteral ; // should make a TemplateLiteral
5967
+ }
5895
5968
return TokenClass . Identifier ;
5896
5969
}
5897
5970
}
0 commit comments