@@ -197,6 +197,9 @@ module ts {
197197 let list = createNode ( SyntaxKind . SyntaxList , nodes . pos , nodes . end , NodeFlags . Synthetic , this ) ;
198198 list . _children = [ ] ;
199199 let pos = nodes . pos ;
200+
201+
202+
200203 for ( let node of nodes ) {
201204 if ( pos < node . pos ) {
202205 pos = this . addSyntheticNodes ( list . _children , pos , node . pos ) ;
@@ -972,6 +975,10 @@ module ts {
972975 getSyntacticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
973976 getSemanticClassifications ( fileName : string , span : TextSpan ) : ClassifiedSpan [ ] ;
974977
978+ // Encoded as triples of [start, length, ClassificationType].
979+ getSyntacticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
980+ getSemanticClassifications2 ( fileName : string , span : TextSpan ) : number [ ] ;
981+
975982 getCompletionsAtPosition ( fileName : string , position : number ) : CompletionInfo ;
976983 getCompletionEntryDetails ( fileName : string , position : number , entryName : string ) : CompletionEntryDetails ;
977984
@@ -1487,6 +1494,24 @@ module ts {
14871494 public static typeAlias = "type alias name" ;
14881495 }
14891496
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+
14901515 /// Language Service
14911516
14921517 interface FormattingOptions {
@@ -5801,35 +5826,45 @@ module ts {
58015826 return NavigationBar . getNavigationBarItems ( sourceFile ) ;
58025827 }
58035828
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 [ ] {
58055834 synchronizeHostData ( ) ;
58065835
58075836 let sourceFile = getValidSourceFile ( fileName ) ;
58085837 let typeChecker = program . getTypeChecker ( ) ;
58095838
5810- let result : ClassifiedSpan [ ] = [ ] ;
5839+ let result : number [ ] = [ ] ;
58115840 processNode ( sourceFile ) ;
58125841
58135842 return result ;
58145843
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 {
58165851 let flags = symbol . getFlags ( ) ;
58175852
58185853 if ( flags & SymbolFlags . Class ) {
5819- return ClassificationTypeNames . className ;
5854+ return ClassificationType . className ;
58205855 }
58215856 else if ( flags & SymbolFlags . Enum ) {
5822- return ClassificationTypeNames . enumName ;
5857+ return ClassificationType . enumName ;
58235858 }
58245859 else if ( flags & SymbolFlags . TypeAlias ) {
5825- return ClassificationTypeNames . typeAlias ;
5860+ return ClassificationType . typeAlias ;
58265861 }
58275862 else if ( meaningAtPosition & SemanticMeaning . Type ) {
58285863 if ( flags & SymbolFlags . Interface ) {
5829- return ClassificationTypeNames . interfaceName ;
5864+ return ClassificationType . interfaceName ;
58305865 }
58315866 else if ( flags & SymbolFlags . TypeParameter ) {
5832- return ClassificationTypeNames . typeParameterName ;
5867+ return ClassificationType . typeParameterName ;
58335868 }
58345869 }
58355870 else if ( flags & SymbolFlags . Module ) {
@@ -5838,7 +5873,7 @@ module ts {
58385873 // - There exists a module declaration which actually impacts the value side.
58395874 if ( meaningAtPosition & SemanticMeaning . Namespace ||
58405875 ( meaningAtPosition & SemanticMeaning . Value && hasValueSideModule ( symbol ) ) ) {
5841- return ClassificationTypeNames . moduleName ;
5876+ return ClassificationType . moduleName ;
58425877 }
58435878 }
58445879
@@ -5862,10 +5897,7 @@ module ts {
58625897 if ( symbol ) {
58635898 let type = classifySymbol ( symbol , getMeaningFromLocation ( node ) ) ;
58645899 if ( type ) {
5865- result . push ( {
5866- textSpan : createTextSpan ( node . getStart ( ) , node . getWidth ( ) ) ,
5867- classificationType : type
5868- } ) ;
5900+ pushClassification ( node . getStart ( ) , node . getWidth ( ) , type ) ;
58695901 }
58705902 }
58715903 }
@@ -5875,19 +5907,62 @@ module ts {
58755907 }
58765908 }
58775909
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 [ ] {
58795948 // doesn't use compiler - no need to synchronize with host
58805949 let sourceFile = syntaxTreeCache . getCurrentSourceFile ( fileName ) ;
58815950
58825951 // Make a scanner we can get trivia from.
58835952 let triviaScanner = createScanner ( ScriptTarget . Latest , /*skipTrivia:*/ false , sourceFile . text ) ;
58845953 let mergeConflictScanner = createScanner ( ScriptTarget . Latest , /*skipTrivia:*/ false , sourceFile . text ) ;
58855954
5886- let result : ClassifiedSpan [ ] = [ ] ;
5955+ let result : number [ ] = [ ] ;
58875956 processElement ( sourceFile ) ;
58885957
58895958 return result ;
58905959
5960+ function pushClassification ( start : number , length : number , type : ClassificationType ) {
5961+ result . push ( start ) ;
5962+ result . push ( length ) ;
5963+ result . push ( type ) ;
5964+ }
5965+
58915966 function classifyLeadingTrivia ( token : Node ) : void {
58925967 let tokenStart = skipTrivia ( sourceFile . text , token . pos , /*stopAfterLineBreak:*/ false ) ;
58935968 if ( tokenStart === token . pos ) {
@@ -5909,10 +5984,7 @@ module ts {
59095984
59105985 if ( isComment ( kind ) ) {
59115986 // 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 ) ;
59165988 continue ;
59175989 }
59185990
@@ -5923,10 +5995,7 @@ module ts {
59235995 // for the <<<<<<< and >>>>>>> markers, we just add them in as comments
59245996 // in the classification stream.
59255997 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 ) ;
59305999 continue ;
59316000 }
59326001
@@ -5947,11 +6016,7 @@ module ts {
59476016 break ;
59486017 }
59496018 }
5950- result . push ( {
5951- textSpan : createTextSpanFromBounds ( start , i ) ,
5952- classificationType : ClassificationTypeNames . comment
5953- } ) ;
5954-
6019+ pushClassification ( start , i - start , ClassificationType . comment ) ;
59556020 mergeConflictScanner . setTextPos ( i ) ;
59566021
59576022 while ( mergeConflictScanner . getTextPos ( ) < end ) {
@@ -5966,10 +6031,7 @@ module ts {
59666031
59676032 let type = classifyTokenType ( tokenKind ) ;
59686033 if ( type ) {
5969- result . push ( {
5970- textSpan : createTextSpanFromBounds ( start , end ) ,
5971- classificationType : type
5972- } ) ;
6034+ pushClassification ( start , end - start , type ) ;
59736035 }
59746036 }
59756037
@@ -5979,20 +6041,17 @@ module ts {
59796041 if ( token . getWidth ( ) > 0 ) {
59806042 let type = classifyTokenType ( token . kind , token ) ;
59816043 if ( type ) {
5982- result . push ( {
5983- textSpan : createTextSpan ( token . getStart ( ) , token . getWidth ( ) ) ,
5984- classificationType : type
5985- } ) ;
6044+ pushClassification ( token . getStart ( ) , token . getWidth ( ) , type ) ;
59866045 }
59876046 }
59886047 }
59896048
59906049 // for accurate classification, the actual token should be passed in. however, for
59916050 // cases like 'disabled merge code' classification, we just get the token kind and
59926051 // classify based on that instead.
5993- function classifyTokenType ( tokenKind : SyntaxKind , token ?: Node ) : string {
6052+ function classifyTokenType ( tokenKind : SyntaxKind , token ?: Node ) : ClassificationType {
59946053 if ( isKeyword ( tokenKind ) ) {
5995- return ClassificationTypeNames . keyword ;
6054+ return ClassificationType . keyword ;
59966055 }
59976056
59986057 // Special case < and > If they appear in a generic context they are punctuation,
@@ -6001,7 +6060,7 @@ module ts {
60016060 // If the node owning the token has a type argument list or type parameter list, then
60026061 // we can effectively assume that a '<' and '>' belong to those lists.
60036062 if ( token && getTypeArgumentOrTypeParameterList ( token . parent ) ) {
6004- return ClassificationTypeNames . punctuation ;
6063+ return ClassificationType . punctuation ;
60056064 }
60066065 }
60076066
@@ -6012,66 +6071,66 @@ module ts {
60126071 if ( token . parent . kind === SyntaxKind . VariableDeclaration ||
60136072 token . parent . kind === SyntaxKind . PropertyDeclaration ||
60146073 token . parent . kind === SyntaxKind . Parameter ) {
6015- return ClassificationTypeNames . operator ;
6074+ return ClassificationType . operator ;
60166075 }
60176076 }
60186077
60196078 if ( token . parent . kind === SyntaxKind . BinaryExpression ||
60206079 token . parent . kind === SyntaxKind . PrefixUnaryExpression ||
60216080 token . parent . kind === SyntaxKind . PostfixUnaryExpression ||
60226081 token . parent . kind === SyntaxKind . ConditionalExpression ) {
6023- return ClassificationTypeNames . operator ;
6082+ return ClassificationType . operator ;
60246083 }
60256084 }
60266085
6027- return ClassificationTypeNames . punctuation ;
6086+ return ClassificationType . punctuation ;
60286087 }
60296088 else if ( tokenKind === SyntaxKind . NumericLiteral ) {
6030- return ClassificationTypeNames . numericLiteral ;
6089+ return ClassificationType . numericLiteral ;
60316090 }
60326091 else if ( tokenKind === SyntaxKind . StringLiteral ) {
6033- return ClassificationTypeNames . stringLiteral ;
6092+ return ClassificationType . stringLiteral ;
60346093 }
60356094 else if ( tokenKind === SyntaxKind . RegularExpressionLiteral ) {
60366095 // TODO: we should get another classification type for these literals.
6037- return ClassificationTypeNames . stringLiteral ;
6096+ return ClassificationType . stringLiteral ;
60386097 }
60396098 else if ( isTemplateLiteralKind ( tokenKind ) ) {
60406099 // TODO (drosen): we should *also* get another classification type for these literals.
6041- return ClassificationTypeNames . stringLiteral ;
6100+ return ClassificationType . stringLiteral ;
60426101 }
60436102 else if ( tokenKind === SyntaxKind . Identifier ) {
60446103 if ( token ) {
60456104 switch ( token . parent . kind ) {
60466105 case SyntaxKind . ClassDeclaration :
60476106 if ( ( < ClassDeclaration > token . parent ) . name === token ) {
6048- return ClassificationTypeNames . className ;
6107+ return ClassificationType . className ;
60496108 }
60506109 return ;
60516110 case SyntaxKind . TypeParameter :
60526111 if ( ( < TypeParameterDeclaration > token . parent ) . name === token ) {
6053- return ClassificationTypeNames . typeParameterName ;
6112+ return ClassificationType . typeParameterName ;
60546113 }
60556114 return ;
60566115 case SyntaxKind . InterfaceDeclaration :
60576116 if ( ( < InterfaceDeclaration > token . parent ) . name === token ) {
6058- return ClassificationTypeNames . interfaceName ;
6117+ return ClassificationType . interfaceName ;
60596118 }
60606119 return ;
60616120 case SyntaxKind . EnumDeclaration :
60626121 if ( ( < EnumDeclaration > token . parent ) . name === token ) {
6063- return ClassificationTypeNames . enumName ;
6122+ return ClassificationType . enumName ;
60646123 }
60656124 return ;
60666125 case SyntaxKind . ModuleDeclaration :
60676126 if ( ( < ModuleDeclaration > token . parent ) . name === token ) {
6068- return ClassificationTypeNames . moduleName ;
6127+ return ClassificationType . moduleName ;
60696128 }
60706129 return ;
60716130 }
60726131 }
60736132
6074- return ClassificationTypeNames . text ;
6133+ return ClassificationType . text ;
60756134 }
60766135 }
60776136
@@ -6402,6 +6461,8 @@ module ts {
64026461 getCompilerOptionsDiagnostics,
64036462 getSyntacticClassifications,
64046463 getSemanticClassifications,
6464+ getSyntacticClassifications2,
6465+ getSemanticClassifications2,
64056466 getCompletionsAtPosition,
64066467 getCompletionEntryDetails,
64076468 getSignatureHelpItems,
0 commit comments