@@ -972,12 +972,19 @@ module ts {
972
972
getSemanticDiagnostics ( fileName : string ) : Diagnostic [ ] ;
973
973
getCompilerOptionsDiagnostics ( ) : Diagnostic [ ] ;
974
974
975
+ /**
976
+ * @deprecated Use getSyntacticClassifications2 instead.
977
+ */
975
978
getSyntacticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
979
+
980
+ /**
981
+ * @deprecated Use getSemanticClassifications2 instead.
982
+ */
976
983
getSemanticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
977
984
978
985
// Encoded as triples of [start, length, ClassificationType].
979
- getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
980
- getSemanticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
986
+ getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : Classifications ;
987
+ getSemanticClassifications2 ( fileName : string , span : TextSpan ) : Classifications ;
981
988
982
989
getCompletionsAtPosition ( fileName : string , position : number ) : CompletionInfo ;
983
990
getCompletionEntryDetails ( fileName : string , position : number , entryName : string ) : CompletionEntryDetails ;
@@ -1022,6 +1029,11 @@ module ts {
1022
1029
dispose ( ) : void ;
1023
1030
}
1024
1031
1032
+ export interface Classifications {
1033
+ spans : number [ ] ,
1034
+ endOfLineState : EndOfLineState
1035
+ }
1036
+
1025
1037
export interface ClassifiedSpan {
1026
1038
textSpan : TextSpan ;
1027
1039
classificationType : string ; // ClassificationTypeNames
@@ -1265,7 +1277,7 @@ module ts {
1265
1277
}
1266
1278
1267
1279
export const enum EndOfLineState {
1268
- Start ,
1280
+ None ,
1269
1281
InMultiLineCommentTrivia ,
1270
1282
InSingleQuoteStringLiteral ,
1271
1283
InDoubleQuoteStringLiteral ,
@@ -1315,8 +1327,10 @@ module ts {
1315
1327
* classifications which may be incorrectly categorized will be given
1316
1328
* back as Identifiers in order to allow the syntactic classifier to
1317
1329
* subsume the classification.
1330
+ * @deprecated Use getLexicalClassifications instead.
1318
1331
*/
1319
1332
getClassificationsForLine ( text : string , lexState : EndOfLineState , syntacticClassifierAbsent : boolean ) : ClassificationResult ;
1333
+ getLexicalClassifications2 ( text : string , endOfLineState : EndOfLineState , syntacticClassifierAbsent : boolean ) : Classifications ;
1320
1334
}
1321
1335
1322
1336
/**
@@ -1501,15 +1515,17 @@ module ts {
1501
1515
numericLiteral = 4 ,
1502
1516
operator = 5 ,
1503
1517
stringLiteral = 6 ,
1504
- whiteSpace = 7 ,
1505
- text = 8 ,
1506
- punctuation = 9 ,
1507
- className = 10 ,
1508
- enumName = 11 ,
1509
- interfaceName = 12 ,
1510
- moduleName = 13 ,
1511
- typeParameterName = 14 ,
1512
- typeAlias = 15 ,
1518
+ regularExpressionLiteral = 7 ,
1519
+ whiteSpace = 8 ,
1520
+ text = 9 ,
1521
+ punctuation = 10 ,
1522
+ className = 11 ,
1523
+ enumName = 12 ,
1524
+ interfaceName = 13 ,
1525
+ moduleName = 14 ,
1526
+ typeParameterName = 15 ,
1527
+ typeAlias = 16 ,
1528
+ parameterName = 17
1513
1529
}
1514
1530
1515
1531
/// Language Service
@@ -5830,7 +5846,7 @@ module ts {
5830
5846
return convertClassifications ( getSemanticClassifications2 ( fileName , span ) ) ;
5831
5847
}
5832
5848
5833
- function getSemanticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] {
5849
+ function getSemanticClassifications2 ( fileName : string , span : TextSpan ) : Classifications {
5834
5850
synchronizeHostData ( ) ;
5835
5851
5836
5852
let sourceFile = getValidSourceFile ( fileName ) ;
@@ -5839,7 +5855,7 @@ module ts {
5839
5855
let result : number [ ] = [ ] ;
5840
5856
processNode ( sourceFile ) ;
5841
5857
5842
- return result ;
5858
+ return { spans : result , endOfLineState : EndOfLineState . None } ;
5843
5859
5844
5860
function pushClassification ( start : number , length : number , type : ClassificationType ) {
5845
5861
result . push ( start ) ;
@@ -5927,8 +5943,9 @@ module ts {
5927
5943
}
5928
5944
}
5929
5945
5930
- function convertClassifications ( dense : number [ ] ) : ClassifiedSpan [ ] {
5931
- Debug . assert ( dense . length % 3 === 0 ) ;
5946
+ function convertClassifications ( classifications : Classifications ) : ClassifiedSpan [ ] {
5947
+ Debug . assert ( classifications . spans . length % 3 === 0 ) ;
5948
+ let dense = classifications . spans ;
5932
5949
let result : ClassifiedSpan [ ] = [ ] ;
5933
5950
for ( let i = 0 , n = dense . length ; i < n ; i += 3 ) {
5934
5951
result . push ( {
@@ -5944,7 +5961,7 @@ module ts {
5944
5961
return convertClassifications ( getSyntacticClassifications2 ( fileName , span ) ) ;
5945
5962
}
5946
5963
5947
- function getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] {
5964
+ function getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : Classifications {
5948
5965
// doesn't use compiler - no need to synchronize with host
5949
5966
let sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ;
5950
5967
@@ -5955,7 +5972,7 @@ module ts {
5955
5972
let result : number [ ] = [ ] ;
5956
5973
processElement ( sourceFile ) ;
5957
5974
5958
- return result ;
5975
+ return { spans : result , endOfLineState : EndOfLineState . None } ;
5959
5976
5960
5977
function pushClassification ( start : number , length : number , type : ClassificationType ) {
5961
5978
result . push ( start ) ;
@@ -6603,10 +6620,67 @@ module ts {
6603
6620
// if there are more cases we want the classifier to be better at.
6604
6621
return true ;
6605
6622
}
6606
-
6623
+
6624
+ function convertClassifications ( classifications : Classifications , text : string ) : ClassificationResult {
6625
+ var entries : ClassificationInfo [ ] = [ ] ;
6626
+ let dense = classifications . spans ;
6627
+ let lastEnd = 0 ;
6628
+
6629
+ for ( let i = 0 , n = dense . length ; i < n ; i += 3 ) {
6630
+ let start = dense [ i ] ;
6631
+ let length = dense [ i + 1 ] ;
6632
+ let type = < ClassificationType > dense [ i + 2 ] ;
6633
+
6634
+ // Make a whitespace entry between the last item and this one.
6635
+ if ( lastEnd >= 0 ) {
6636
+ let whitespaceLength = start - lastEnd ;
6637
+ if ( whitespaceLength > 0 ) {
6638
+ entries . push ( { length : whitespaceLength , classification : TokenClass . Whitespace } ) ;
6639
+ }
6640
+ }
6641
+
6642
+ entries . push ( { length, classification : convertClassification ( type ) } ) ;
6643
+ lastEnd = start + length ;
6644
+ }
6645
+
6646
+ let whitespaceLength = text . length - lastEnd ;
6647
+ if ( whitespaceLength > 0 ) {
6648
+ entries . push ( { length : whitespaceLength , classification : TokenClass . Whitespace } ) ;
6649
+ }
6650
+
6651
+ return { entries, finalLexState : classifications . endOfLineState } ;
6652
+ }
6653
+
6654
+ function convertClassification ( type : ClassificationType ) : TokenClass {
6655
+ switch ( type ) {
6656
+ case ClassificationType . comment : return TokenClass . Comment ;
6657
+ case ClassificationType . keyword : return TokenClass . Keyword ;
6658
+ case ClassificationType . numericLiteral : return TokenClass . NumberLiteral ;
6659
+ case ClassificationType . operator : return TokenClass . Operator ;
6660
+ case ClassificationType . stringLiteral : return TokenClass . StringLiteral ;
6661
+ case ClassificationType . whiteSpace : return TokenClass . Whitespace ;
6662
+ case ClassificationType . punctuation : return TokenClass . Punctuation ;
6663
+ case ClassificationType . identifier :
6664
+ case ClassificationType . className :
6665
+ case ClassificationType . enumName :
6666
+ case ClassificationType . interfaceName :
6667
+ case ClassificationType . moduleName :
6668
+ case ClassificationType . typeParameterName :
6669
+ case ClassificationType . typeAlias :
6670
+ case ClassificationType . text :
6671
+ case ClassificationType . parameterName :
6672
+ default :
6673
+ return TokenClass . Identifier ;
6674
+ }
6675
+ }
6676
+
6677
+ function getClassificationsForLine ( text : string , lexState : EndOfLineState , syntacticClassifierAbsent : boolean ) : ClassificationResult {
6678
+ return convertClassifications ( getLexicalClassifications2 ( text , lexState , syntacticClassifierAbsent ) , text ) ;
6679
+ }
6680
+
6607
6681
// If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
6608
6682
// we will be more conservative in order to avoid conflicting with the syntactic classifier.
6609
- function getClassificationsForLine ( text : string , lexState : EndOfLineState , syntacticClassifierAbsent : boolean ) : ClassificationResult {
6683
+ function getLexicalClassifications2 ( text : string , lexState : EndOfLineState , syntacticClassifierAbsent : boolean ) : Classifications {
6610
6684
let offset = 0 ;
6611
6685
let token = SyntaxKind . Unknown ;
6612
6686
let lastNonTriviaToken = SyntaxKind . Unknown ;
@@ -6649,9 +6723,9 @@ module ts {
6649
6723
6650
6724
scanner . setText ( text ) ;
6651
6725
6652
- let result : ClassificationResult = {
6653
- finalLexState : EndOfLineState . Start ,
6654
- entries : [ ]
6726
+ let result : Classifications = {
6727
+ endOfLineState : EndOfLineState . None ,
6728
+ spans : [ ]
6655
6729
} ;
6656
6730
6657
6731
// We can run into an unfortunate interaction between the lexical and syntactic classifier
@@ -6764,7 +6838,7 @@ module ts {
6764
6838
let start = scanner . getTokenPos ( ) ;
6765
6839
let end = scanner . getTextPos ( ) ;
6766
6840
6767
- addResult ( end - start , classFromKind ( token ) ) ;
6841
+ addResult ( start , end , classFromKind ( token ) ) ;
6768
6842
6769
6843
if ( end >= text . length ) {
6770
6844
if ( token === SyntaxKind . StringLiteral ) {
@@ -6781,7 +6855,7 @@ module ts {
6781
6855
// If we have an odd number of backslashes, then the multiline string is unclosed
6782
6856
if ( numBackslashes & 1 ) {
6783
6857
let quoteChar = tokenText . charCodeAt ( 0 ) ;
6784
- result . finalLexState = quoteChar === CharacterCodes . doubleQuote
6858
+ result . endOfLineState = quoteChar === CharacterCodes . doubleQuote
6785
6859
? EndOfLineState . InDoubleQuoteStringLiteral
6786
6860
: EndOfLineState . InSingleQuoteStringLiteral ;
6787
6861
}
@@ -6790,37 +6864,51 @@ module ts {
6790
6864
else if ( token === SyntaxKind . MultiLineCommentTrivia ) {
6791
6865
// Check to see if the multiline comment was unclosed.
6792
6866
if ( scanner . isUnterminated ( ) ) {
6793
- result . finalLexState = EndOfLineState . InMultiLineCommentTrivia ;
6867
+ result . endOfLineState = EndOfLineState . InMultiLineCommentTrivia ;
6794
6868
}
6795
6869
}
6796
6870
else if ( isTemplateLiteralKind ( token ) ) {
6797
6871
if ( scanner . isUnterminated ( ) ) {
6798
6872
if ( token === SyntaxKind . TemplateTail ) {
6799
- result . finalLexState = EndOfLineState . InTemplateMiddleOrTail ;
6873
+ result . endOfLineState = EndOfLineState . InTemplateMiddleOrTail ;
6800
6874
}
6801
6875
else if ( token === SyntaxKind . NoSubstitutionTemplateLiteral ) {
6802
- result . finalLexState = EndOfLineState . InTemplateHeadOrNoSubstitutionTemplate ;
6876
+ result . endOfLineState = EndOfLineState . InTemplateHeadOrNoSubstitutionTemplate ;
6803
6877
}
6804
6878
else {
6805
6879
Debug . fail ( "Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token ) ;
6806
6880
}
6807
6881
}
6808
6882
}
6809
6883
else if ( templateStack . length > 0 && lastOrUndefined ( templateStack ) === SyntaxKind . TemplateHead ) {
6810
- result . finalLexState = EndOfLineState . InTemplateSubstitutionPosition ;
6884
+ result . endOfLineState = EndOfLineState . InTemplateSubstitutionPosition ;
6811
6885
}
6812
6886
}
6813
6887
}
6814
6888
6815
- function addResult ( length : number , classification : TokenClass ) : void {
6816
- if ( length > 0 ) {
6817
- // If this is the first classification we're adding to the list, then remove any
6818
- // offset we have if we were continuing a construct from the previous line.
6819
- if ( result . entries . length === 0 ) {
6820
- length -= offset ;
6821
- }
6889
+ function addResult ( start : number , end : number , classification : ClassificationType ) : void {
6890
+ if ( classification === ClassificationType . whiteSpace ) {
6891
+ // Don't bother with whitespace classifications. They're not needed.
6892
+ return ;
6893
+ }
6894
+
6895
+ if ( start === 0 && offset > 0 ) {
6896
+ // We're classifying the first token, and this was a case where we prepended
6897
+ // text. We should consider the start of this token to be at the start of
6898
+ // the original text.
6899
+ start += offset ;
6900
+ }
6901
+
6902
+ // All our tokens are in relation to the augmented text. Move them back to be
6903
+ // relative to the original text.
6904
+ start -= offset ;
6905
+ end -= offset ;
6906
+ let length = end - start ;
6822
6907
6823
- result . entries . push ( { length : length , classification : classification } ) ;
6908
+ if ( length > 0 ) {
6909
+ result . spans . push ( start ) ;
6910
+ result . spans . push ( length ) ;
6911
+ result . spans . push ( classification ) ;
6824
6912
}
6825
6913
}
6826
6914
}
@@ -6887,41 +6975,44 @@ module ts {
6887
6975
return token >= SyntaxKind . FirstKeyword && token <= SyntaxKind . LastKeyword ;
6888
6976
}
6889
6977
6890
- function classFromKind ( token : SyntaxKind ) {
6978
+ function classFromKind ( token : SyntaxKind ) : ClassificationType {
6891
6979
if ( isKeyword ( token ) ) {
6892
- return TokenClass . Keyword ;
6980
+ return ClassificationType . keyword ;
6893
6981
}
6894
6982
else if ( isBinaryExpressionOperatorToken ( token ) || isPrefixUnaryExpressionOperatorToken ( token ) ) {
6895
- return TokenClass . Operator ;
6983
+ return ClassificationType . operator ;
6896
6984
}
6897
6985
else if ( token >= SyntaxKind . FirstPunctuation && token <= SyntaxKind . LastPunctuation ) {
6898
- return TokenClass . Punctuation ;
6986
+ return ClassificationType . punctuation ;
6899
6987
}
6900
6988
6901
6989
switch ( token ) {
6902
6990
case SyntaxKind . NumericLiteral :
6903
- return TokenClass . NumberLiteral ;
6991
+ return ClassificationType . numericLiteral ;
6904
6992
case SyntaxKind . StringLiteral :
6905
- return TokenClass . StringLiteral ;
6993
+ return ClassificationType . stringLiteral ;
6906
6994
case SyntaxKind . RegularExpressionLiteral :
6907
- return TokenClass . RegExpLiteral ;
6995
+ return ClassificationType . regularExpressionLiteral ;
6908
6996
case SyntaxKind . ConflictMarkerTrivia :
6909
6997
case SyntaxKind . MultiLineCommentTrivia :
6910
6998
case SyntaxKind . SingleLineCommentTrivia :
6911
- return TokenClass . Comment ;
6999
+ return ClassificationType . comment ;
6912
7000
case SyntaxKind . WhitespaceTrivia :
6913
7001
case SyntaxKind . NewLineTrivia :
6914
- return TokenClass . Whitespace ;
7002
+ return ClassificationType . whiteSpace ;
6915
7003
case SyntaxKind . Identifier :
6916
7004
default :
6917
7005
if ( isTemplateLiteralKind ( token ) ) {
6918
- return TokenClass . StringLiteral ;
7006
+ return ClassificationType . stringLiteral ;
6919
7007
}
6920
- return TokenClass . Identifier ;
7008
+ return ClassificationType . identifier ;
6921
7009
}
6922
7010
}
6923
7011
6924
- return { getClassificationsForLine } ;
7012
+ return {
7013
+ getClassificationsForLine,
7014
+ getLexicalClassifications2
7015
+ } ;
6925
7016
}
6926
7017
6927
7018
/// getDefaultLibraryFilePath
0 commit comments