@@ -197,6 +197,9 @@ module ts {
197
197
let list = createNode ( SyntaxKind . SyntaxList , nodes . pos , nodes . end , NodeFlags . Synthetic , this ) ;
198
198
list . _children = [ ] ;
199
199
let pos = nodes . pos ;
200
+
201
+
202
+
200
203
for ( let node of nodes ) {
201
204
if ( pos < node . pos ) {
202
205
pos = this . addSyntheticNodes ( list . _children , pos , node . pos ) ;
@@ -972,6 +975,10 @@ module ts {
972
975
getSyntacticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
973
976
getSemanticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
974
977
978
+ // Encoded as triples of [start, length, ClassificationType].
979
+ getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
980
+ getSemanticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
981
+
975
982
getCompletionsAtPosition ( fileName : string , position : number ) : CompletionInfo ;
976
983
getCompletionEntryDetails ( fileName : string , position : number , entryName : string ) : CompletionEntryDetails ;
977
984
@@ -1487,6 +1494,24 @@ module ts {
1487
1494
public static typeAlias = "type alias name" ;
1488
1495
}
1489
1496
1497
+ export const enum ClassificationType {
1498
+ comment = 1 ,
1499
+ identifier = 2 ,
1500
+ keyword = 3 ,
1501
+ numericLiteral = 4 ,
1502
+ operator = 5 ,
1503
+ 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 ,
1513
+ }
1514
+
1490
1515
/// Language Service
1491
1516
1492
1517
interface FormattingOptions {
@@ -5801,35 +5826,45 @@ module ts {
5801
5826
return NavigationBar . getNavigationBarItems ( sourceFile ) ;
5802
5827
}
5803
5828
5804
- function getSemanticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] {
5829
+ function getSemanticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] {
5830
+ return convertClassifications ( getSemanticClassifications2 ( fileName , span ) ) ;
5831
+ }
5832
+
5833
+ function getSemanticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] {
5805
5834
synchronizeHostData ( ) ;
5806
5835
5807
5836
let sourceFile = getValidSourceFile ( fileName ) ;
5808
5837
let typeChecker = program . getTypeChecker ( ) ;
5809
5838
5810
- let result : ClassifiedSpan [ ] = [ ] ;
5839
+ let result : number [ ] = [ ] ;
5811
5840
processNode ( sourceFile ) ;
5812
5841
5813
5842
return result ;
5814
5843
5815
- function classifySymbol ( symbol : Symbol , meaningAtPosition : SemanticMeaning ) {
5844
+ function pushClassification ( start : number , length : number , type : ClassificationType ) {
5845
+ result . push ( start ) ;
5846
+ result . push ( length ) ;
5847
+ result . push ( type ) ;
5848
+ }
5849
+
5850
+ function classifySymbol ( symbol : Symbol , meaningAtPosition : SemanticMeaning ) : ClassificationType {
5816
5851
let flags = symbol . getFlags ( ) ;
5817
5852
5818
5853
if ( flags & SymbolFlags . Class ) {
5819
- return ClassificationTypeNames . className ;
5854
+ return ClassificationType . className ;
5820
5855
}
5821
5856
else if ( flags & SymbolFlags . Enum ) {
5822
- return ClassificationTypeNames . enumName ;
5857
+ return ClassificationType . enumName ;
5823
5858
}
5824
5859
else if ( flags & SymbolFlags . TypeAlias ) {
5825
- return ClassificationTypeNames . typeAlias ;
5860
+ return ClassificationType . typeAlias ;
5826
5861
}
5827
5862
else if ( meaningAtPosition & SemanticMeaning . Type ) {
5828
5863
if ( flags & SymbolFlags . Interface ) {
5829
- return ClassificationTypeNames . interfaceName ;
5864
+ return ClassificationType . interfaceName ;
5830
5865
}
5831
5866
else if ( flags & SymbolFlags . TypeParameter ) {
5832
- return ClassificationTypeNames . typeParameterName ;
5867
+ return ClassificationType . typeParameterName ;
5833
5868
}
5834
5869
}
5835
5870
else if ( flags & SymbolFlags . Module ) {
@@ -5838,7 +5873,7 @@ module ts {
5838
5873
// - There exists a module declaration which actually impacts the value side.
5839
5874
if ( meaningAtPosition & SemanticMeaning . Namespace ||
5840
5875
( meaningAtPosition & SemanticMeaning . Value && hasValueSideModule ( symbol ) ) ) {
5841
- return ClassificationTypeNames . moduleName ;
5876
+ return ClassificationType . moduleName ;
5842
5877
}
5843
5878
}
5844
5879
@@ -5862,10 +5897,7 @@ module ts {
5862
5897
if ( symbol ) {
5863
5898
let type = classifySymbol ( symbol , getMeaningFromLocation ( node ) ) ;
5864
5899
if ( type ) {
5865
- result . push ( {
5866
- textSpan : createTextSpan ( node . getStart ( ) , node . getWidth ( ) ) ,
5867
- classificationType : type
5868
- } ) ;
5900
+ pushClassification ( node . getStart ( ) , node . getWidth ( ) , type ) ;
5869
5901
}
5870
5902
}
5871
5903
}
@@ -5875,19 +5907,62 @@ module ts {
5875
5907
}
5876
5908
}
5877
5909
5878
- function getSyntacticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] {
5910
+ function getClassificationTypeName ( type : ClassificationType ) {
5911
+ switch ( type ) {
5912
+ case ClassificationType . comment : return ClassificationTypeNames . comment ;
5913
+ case ClassificationType . identifier : return ClassificationTypeNames . identifier ;
5914
+ case ClassificationType . keyword : return ClassificationTypeNames . keyword ;
5915
+ case ClassificationType . numericLiteral : return ClassificationTypeNames . numericLiteral ;
5916
+ case ClassificationType . operator : return ClassificationTypeNames . operator ;
5917
+ case ClassificationType . stringLiteral : return ClassificationTypeNames . stringLiteral ;
5918
+ case ClassificationType . whiteSpace : return ClassificationTypeNames . whiteSpace ;
5919
+ case ClassificationType . text : return ClassificationTypeNames . text ;
5920
+ case ClassificationType . punctuation : return ClassificationTypeNames . punctuation ;
5921
+ case ClassificationType . className : return ClassificationTypeNames . className ;
5922
+ case ClassificationType . enumName : return ClassificationTypeNames . enumName ;
5923
+ case ClassificationType . interfaceName : return ClassificationTypeNames . interfaceName ;
5924
+ case ClassificationType . moduleName : return ClassificationTypeNames . moduleName ;
5925
+ case ClassificationType . typeParameterName : return ClassificationTypeNames . typeParameterName ;
5926
+ case ClassificationType . typeAlias : return ClassificationTypeNames . typeAlias ;
5927
+ }
5928
+ }
5929
+
5930
+ function convertClassifications ( dense : number [ ] ) : ClassifiedSpan [ ] {
5931
+ Debug . assert ( dense . length % 3 === 0 ) ;
5932
+ let result : ClassifiedSpan [ ] = [ ] ;
5933
+ for ( let i = 0 , n = dense . length ; i < n ; i += 3 ) {
5934
+ result . push ( {
5935
+ textSpan : createTextSpan ( dense [ i ] , dense [ i + 1 ] ) ,
5936
+ classificationType : getClassificationTypeName ( dense [ i + 2 ] )
5937
+ } ) ;
5938
+ }
5939
+
5940
+ return result ;
5941
+ }
5942
+
5943
+ function getSyntacticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] {
5944
+ return convertClassifications ( getSyntacticClassifications2 ( fileName , span ) ) ;
5945
+ }
5946
+
5947
+ function getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] {
5879
5948
// doesn't use compiler - no need to synchronize with host
5880
5949
let sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ;
5881
5950
5882
5951
// Make a scanner we can get trivia from.
5883
5952
let triviaScanner = createScanner ( ScriptTarget . Latest , /*skipTrivia:*/ false , sourceFile . text ) ;
5884
5953
let mergeConflictScanner = createScanner ( ScriptTarget . Latest , /*skipTrivia:*/ false , sourceFile . text ) ;
5885
5954
5886
- let result : ClassifiedSpan [ ] = [ ] ;
5955
+ let result : number [ ] = [ ] ;
5887
5956
processElement ( sourceFile ) ;
5888
5957
5889
5958
return result ;
5890
5959
5960
+ function pushClassification ( start : number , length : number , type : ClassificationType ) {
5961
+ result . push ( start ) ;
5962
+ result . push ( length ) ;
5963
+ result . push ( type ) ;
5964
+ }
5965
+
5891
5966
function classifyLeadingTrivia ( token : Node ) : void {
5892
5967
let tokenStart = skipTrivia ( sourceFile . text , token . pos , /*stopAfterLineBreak:*/ false ) ;
5893
5968
if ( tokenStart === token . pos ) {
@@ -5909,10 +5984,7 @@ module ts {
5909
5984
5910
5985
if ( isComment ( kind ) ) {
5911
5986
// Simple comment. Just add as is.
5912
- result . push ( {
5913
- textSpan : createTextSpan ( start , width ) ,
5914
- classificationType : ClassificationTypeNames . comment
5915
- } )
5987
+ pushClassification ( start , width , ClassificationType . comment ) ;
5916
5988
continue ;
5917
5989
}
5918
5990
@@ -5923,10 +5995,7 @@ module ts {
5923
5995
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
5924
5996
// in the classification stream.
5925
5997
if ( ch === CharacterCodes . lessThan || ch === CharacterCodes . greaterThan ) {
5926
- result . push ( {
5927
- textSpan : createTextSpan ( start , width ) ,
5928
- classificationType : ClassificationTypeNames . comment
5929
- } ) ;
5998
+ pushClassification ( start , width , ClassificationType . comment ) ;
5930
5999
continue ;
5931
6000
}
5932
6001
@@ -5947,11 +6016,7 @@ module ts {
5947
6016
break ;
5948
6017
}
5949
6018
}
5950
- result . push ( {
5951
- textSpan : createTextSpanFromBounds ( start , i ) ,
5952
- classificationType : ClassificationTypeNames . comment
5953
- } ) ;
5954
-
6019
+ pushClassification ( start , i - start , ClassificationType . comment ) ;
5955
6020
mergeConflictScanner . setTextPos ( i ) ;
5956
6021
5957
6022
while ( mergeConflictScanner . getTextPos ( ) < end ) {
@@ -5966,10 +6031,7 @@ module ts {
5966
6031
5967
6032
let type = classifyTokenType ( tokenKind ) ;
5968
6033
if ( type ) {
5969
- result . push ( {
5970
- textSpan : createTextSpanFromBounds ( start , end ) ,
5971
- classificationType : type
5972
- } ) ;
6034
+ pushClassification ( start , end - start , type ) ;
5973
6035
}
5974
6036
}
5975
6037
@@ -5979,20 +6041,17 @@ module ts {
5979
6041
if ( token . getWidth ( ) > 0 ) {
5980
6042
let type = classifyTokenType ( token . kind , token ) ;
5981
6043
if ( type ) {
5982
- result . push ( {
5983
- textSpan : createTextSpan ( token . getStart ( ) , token . getWidth ( ) ) ,
5984
- classificationType : type
5985
- } ) ;
6044
+ pushClassification ( token . getStart ( ) , token . getWidth ( ) , type ) ;
5986
6045
}
5987
6046
}
5988
6047
}
5989
6048
5990
6049
// for accurate classification, the actual token should be passed in. however, for
5991
6050
// cases like 'disabled merge code' classification, we just get the token kind and
5992
6051
// classify based on that instead.
5993
- function classifyTokenType ( tokenKind : SyntaxKind , token ?: Node ) : string {
6052
+ function classifyTokenType ( tokenKind : SyntaxKind , token ?: Node ) : ClassificationType {
5994
6053
if ( isKeyword ( tokenKind ) ) {
5995
- return ClassificationTypeNames . keyword ;
6054
+ return ClassificationType . keyword ;
5996
6055
}
5997
6056
5998
6057
// Special case < and > If they appear in a generic context they are punctuation,
@@ -6001,7 +6060,7 @@ module ts {
6001
6060
// If the node owning the token has a type argument list or type parameter list, then
6002
6061
// we can effectively assume that a '<' and '>' belong to those lists.
6003
6062
if ( token && getTypeArgumentOrTypeParameterList ( token . parent ) ) {
6004
- return ClassificationTypeNames . punctuation ;
6063
+ return ClassificationType . punctuation ;
6005
6064
}
6006
6065
}
6007
6066
@@ -6012,66 +6071,66 @@ module ts {
6012
6071
if ( token . parent . kind === SyntaxKind . VariableDeclaration ||
6013
6072
token . parent . kind === SyntaxKind . PropertyDeclaration ||
6014
6073
token . parent . kind === SyntaxKind . Parameter ) {
6015
- return ClassificationTypeNames . operator ;
6074
+ return ClassificationType . operator ;
6016
6075
}
6017
6076
}
6018
6077
6019
6078
if ( token . parent . kind === SyntaxKind . BinaryExpression ||
6020
6079
token . parent . kind === SyntaxKind . PrefixUnaryExpression ||
6021
6080
token . parent . kind === SyntaxKind . PostfixUnaryExpression ||
6022
6081
token . parent . kind === SyntaxKind . ConditionalExpression ) {
6023
- return ClassificationTypeNames . operator ;
6082
+ return ClassificationType . operator ;
6024
6083
}
6025
6084
}
6026
6085
6027
- return ClassificationTypeNames . punctuation ;
6086
+ return ClassificationType . punctuation ;
6028
6087
}
6029
6088
else if ( tokenKind === SyntaxKind . NumericLiteral ) {
6030
- return ClassificationTypeNames . numericLiteral ;
6089
+ return ClassificationType . numericLiteral ;
6031
6090
}
6032
6091
else if ( tokenKind === SyntaxKind . StringLiteral ) {
6033
- return ClassificationTypeNames . stringLiteral ;
6092
+ return ClassificationType . stringLiteral ;
6034
6093
}
6035
6094
else if ( tokenKind === SyntaxKind . RegularExpressionLiteral ) {
6036
6095
// TODO: we should get another classification type for these literals.
6037
- return ClassificationTypeNames . stringLiteral ;
6096
+ return ClassificationType . stringLiteral ;
6038
6097
}
6039
6098
else if ( isTemplateLiteralKind ( tokenKind ) ) {
6040
6099
// TODO (drosen): we should *also* get another classification type for these literals.
6041
- return ClassificationTypeNames . stringLiteral ;
6100
+ return ClassificationType . stringLiteral ;
6042
6101
}
6043
6102
else if ( tokenKind === SyntaxKind . Identifier ) {
6044
6103
if ( token ) {
6045
6104
switch ( token . parent . kind ) {
6046
6105
case SyntaxKind . ClassDeclaration :
6047
6106
if ( ( < ClassDeclaration > token . parent ) . name === token ) {
6048
- return ClassificationTypeNames . className ;
6107
+ return ClassificationType . className ;
6049
6108
}
6050
6109
return ;
6051
6110
case SyntaxKind . TypeParameter :
6052
6111
if ( ( < TypeParameterDeclaration > token . parent ) . name === token ) {
6053
- return ClassificationTypeNames . typeParameterName ;
6112
+ return ClassificationType . typeParameterName ;
6054
6113
}
6055
6114
return ;
6056
6115
case SyntaxKind . InterfaceDeclaration :
6057
6116
if ( ( < InterfaceDeclaration > token . parent ) . name === token ) {
6058
- return ClassificationTypeNames . interfaceName ;
6117
+ return ClassificationType . interfaceName ;
6059
6118
}
6060
6119
return ;
6061
6120
case SyntaxKind . EnumDeclaration :
6062
6121
if ( ( < EnumDeclaration > token . parent ) . name === token ) {
6063
- return ClassificationTypeNames . enumName ;
6122
+ return ClassificationType . enumName ;
6064
6123
}
6065
6124
return ;
6066
6125
case SyntaxKind . ModuleDeclaration :
6067
6126
if ( ( < ModuleDeclaration > token . parent ) . name === token ) {
6068
- return ClassificationTypeNames . moduleName ;
6127
+ return ClassificationType . moduleName ;
6069
6128
}
6070
6129
return ;
6071
6130
}
6072
6131
}
6073
6132
6074
- return ClassificationTypeNames . text ;
6133
+ return ClassificationType . text ;
6075
6134
}
6076
6135
}
6077
6136
@@ -6402,6 +6461,8 @@ module ts {
6402
6461
getCompilerOptionsDiagnostics,
6403
6462
getSyntacticClassifications,
6404
6463
getSemanticClassifications,
6464
+ getSyntacticClassifications2,
6465
+ getSemanticClassifications2,
6405
6466
getCompletionsAtPosition,
6406
6467
getCompletionEntryDetails,
6407
6468
getSignatureHelpItems,
0 commit comments