@@ -75,7 +75,7 @@ module ts {
75
75
76
76
var scanner : Scanner = createScanner ( ScriptTarget . ES5 ) ;
77
77
78
- var emptyArray : any [ ] = [ ] ;
78
+ var emptyArray : any [ ] = [ ] ;
79
79
80
80
function createNode ( kind : SyntaxKind , pos : number , end : number , flags : NodeFlags , parent ?: Node ) : NodeObject {
81
81
var node = < NodeObject > new ( getNodeConstructor ( kind ) ) ( ) ;
@@ -259,7 +259,7 @@ module ts {
259
259
getProperty ( propertyName : string ) : Symbol {
260
260
return this . checker . getPropertyOfType ( this , propertyName ) ;
261
261
}
262
- getApparentProperties ( ) : Symbol [ ] {
262
+ getApparentProperties ( ) : Symbol [ ] {
263
263
return this . checker . getAugmentedPropertiesOfApparentType ( this ) ;
264
264
}
265
265
getCallSignatures ( ) : Signature [ ] {
@@ -302,7 +302,7 @@ module ts {
302
302
}
303
303
}
304
304
305
- var incrementalParse : IncrementalParse = TypeScript . IncrementalParser . parse ;
305
+ var incrementalParse : IncrementalParse = TypeScript . IncrementalParser . parse ;
306
306
307
307
class SourceFileObject extends NodeObject implements SourceFile {
308
308
public filename : string ;
@@ -430,6 +430,8 @@ module ts {
430
430
getSemanticDiagnostics ( fileName : string ) : Diagnostic [ ] ;
431
431
getCompilerOptionsDiagnostics ( ) : Diagnostic [ ] ;
432
432
433
+ getSyntacticClassifications ( fileName : string , span : TypeScript . TextSpan ) : ClassifiedSpan [ ] ;
434
+
433
435
getCompletionsAtPosition ( fileName : string , position : number , isMemberCompletion : boolean ) : CompletionInfo ;
434
436
getCompletionEntryDetails ( fileName : string , position : number , entryName : string ) : CompletionEntryDetails ;
435
437
@@ -467,6 +469,32 @@ module ts {
467
469
dispose ( ) : void ;
468
470
}
469
471
472
+ class ClassificationTypeNames {
473
+ public static comment = "comment" ;
474
+ public static identifier = "identifier" ;
475
+ public static keyword = "keyword" ;
476
+ public static numericLiteral = "number" ;
477
+ public static operator = "operator" ;
478
+ public static stringLiteral = "string" ;
479
+ public static whiteSpace = "whitespace" ;
480
+ public static text = "text" ;
481
+
482
+ public static punctuation = "punctuation" ;
483
+
484
+ public static className = "class name" ;
485
+ public static enumName = "enum name" ;
486
+ public static interfaceName = "interface name" ;
487
+ public static moduleName = "module name" ;
488
+ public static typeParameterName = "type parameter name" ;
489
+ }
490
+
491
+ export class ClassifiedSpan {
492
+ constructor ( public textSpan : TypeScript . TextSpan ,
493
+ public classificationType : string ) {
494
+
495
+ }
496
+ }
497
+
470
498
export class NavigationBarItem {
471
499
constructor ( public text : string ,
472
500
public kind : string ,
@@ -3124,6 +3152,140 @@ module ts {
3124
3152
return new TypeScript . Services . NavigationBarItemGetter ( ) . getItems ( syntaxTree . sourceUnit ( ) ) ;
3125
3153
}
3126
3154
3155
+ function getSyntacticClassifications ( fileName : string , span : TypeScript . TextSpan ) : ClassifiedSpan [ ] {
3156
+ // doesn't use compiler - no need to synchronize with host
3157
+ fileName = TypeScript . switchToForwardSlashes ( fileName ) ;
3158
+ var sourceFile = getCurrentSourceFile ( fileName ) ;
3159
+
3160
+ var result : ClassifiedSpan [ ] = [ ] ;
3161
+ processElement ( sourceFile . getSourceUnit ( ) ) ;
3162
+
3163
+ return result ;
3164
+
3165
+ function classifyTrivia ( trivia : TypeScript . ISyntaxTrivia ) {
3166
+ if ( span . intersectsWith ( trivia . fullStart ( ) , trivia . fullWidth ( ) ) ) {
3167
+ result . push ( new ClassifiedSpan (
3168
+ new TypeScript . TextSpan ( trivia . fullStart ( ) , trivia . fullWidth ( ) ) ,
3169
+ ClassificationTypeNames . comment ) ) ;
3170
+ }
3171
+ }
3172
+
3173
+ function classifyTriviaList ( trivia : TypeScript . ISyntaxTriviaList ) {
3174
+ for ( var i = 0 , n = trivia . count ( ) ; i < n ; i ++ ) {
3175
+ classifyTrivia ( trivia . syntaxTriviaAt ( i ) ) ;
3176
+ }
3177
+ }
3178
+
3179
+ function classifyToken ( token : TypeScript . ISyntaxToken ) {
3180
+ if ( token . hasLeadingComment ( ) ) {
3181
+ classifyTriviaList ( token . leadingTrivia ( ) ) ;
3182
+ }
3183
+
3184
+ if ( TypeScript . width ( token ) > 0 ) {
3185
+ var span = new TypeScript . TextSpan ( TypeScript . start ( token ) , TypeScript . width ( token ) ) ;
3186
+ var type = classifyTokenType ( token ) ;
3187
+
3188
+ result . push ( new ClassifiedSpan ( span , type ) ) ;
3189
+ }
3190
+
3191
+ if ( token . hasTrailingComment ( ) ) {
3192
+ classifyTriviaList ( token . trailingTrivia ( ) ) ;
3193
+ }
3194
+ }
3195
+
3196
+ function classifyTokenType ( token : TypeScript . ISyntaxToken ) : string {
3197
+ var tokenKind = token . kind ( ) ;
3198
+ if ( TypeScript . SyntaxFacts . isAnyKeyword ( token . kind ( ) ) ) {
3199
+ return ClassificationTypeNames . keyword ;
3200
+ }
3201
+
3202
+ // Special case < and > If they appear in a generic context they are punctation,
3203
+ // not operators.
3204
+ if ( tokenKind === TypeScript . SyntaxKind . LessThanToken || tokenKind === TypeScript . SyntaxKind . GreaterThanToken ) {
3205
+ var tokenParentKind = token . parent . kind ( ) ;
3206
+ if ( tokenParentKind === TypeScript . SyntaxKind . TypeArgumentList ||
3207
+ tokenParentKind === TypeScript . SyntaxKind . TypeParameterList ) {
3208
+
3209
+ return ClassificationTypeNames . punctuation ;
3210
+ }
3211
+ }
3212
+
3213
+ if ( TypeScript . SyntaxFacts . isBinaryExpressionOperatorToken ( tokenKind ) ||
3214
+ TypeScript . SyntaxFacts . isPrefixUnaryExpressionOperatorToken ( tokenKind ) ) {
3215
+ return ClassificationTypeNames . operator ;
3216
+ }
3217
+ else if ( TypeScript . SyntaxFacts . isAnyPunctuation ( tokenKind ) ) {
3218
+ return ClassificationTypeNames . punctuation ;
3219
+ }
3220
+ else if ( tokenKind === TypeScript . SyntaxKind . NumericLiteral ) {
3221
+ return ClassificationTypeNames . numericLiteral ;
3222
+ }
3223
+ else if ( tokenKind === TypeScript . SyntaxKind . StringLiteral ) {
3224
+ return ClassificationTypeNames . stringLiteral ;
3225
+ }
3226
+ else if ( tokenKind === TypeScript . SyntaxKind . RegularExpressionLiteral ) {
3227
+ // TODO: we shoudl get another classification type for these literals.
3228
+ return ClassificationTypeNames . stringLiteral ;
3229
+ }
3230
+ else if ( tokenKind === TypeScript . SyntaxKind . IdentifierName ) {
3231
+ var current : TypeScript . ISyntaxNodeOrToken = token ;
3232
+ var parent = token . parent ;
3233
+ while ( parent . kind ( ) === TypeScript . SyntaxKind . QualifiedName ) {
3234
+ current = parent ;
3235
+ parent = parent . parent ;
3236
+ }
3237
+
3238
+ switch ( parent . kind ( ) ) {
3239
+ case TypeScript . SyntaxKind . ClassDeclaration :
3240
+ if ( ( < TypeScript . ClassDeclarationSyntax > parent ) . identifier === token ) {
3241
+ return ClassificationTypeNames . className ;
3242
+ }
3243
+ return ;
3244
+ case TypeScript . SyntaxKind . TypeParameter :
3245
+ if ( ( < TypeScript . TypeParameterSyntax > parent ) . identifier === token ) {
3246
+ return ClassificationTypeNames . typeParameterName ;
3247
+ }
3248
+ return ;
3249
+ case TypeScript . SyntaxKind . InterfaceDeclaration :
3250
+ if ( ( < TypeScript . InterfaceDeclarationSyntax > parent ) . identifier === token ) {
3251
+ return ClassificationTypeNames . interfaceName ;
3252
+ }
3253
+ return ;
3254
+ case TypeScript . SyntaxKind . EnumDeclaration :
3255
+ if ( ( < TypeScript . EnumDeclarationSyntax > parent ) . identifier === token ) {
3256
+ return ClassificationTypeNames . enumName ;
3257
+ }
3258
+ return ;
3259
+ case TypeScript . SyntaxKind . ModuleDeclaration :
3260
+ if ( ( < TypeScript . ModuleDeclarationSyntax > parent ) . name === current ) {
3261
+ return ClassificationTypeNames . moduleName ;
3262
+ }
3263
+ return ;
3264
+ default :
3265
+ return ClassificationTypeNames . text ;
3266
+ }
3267
+ }
3268
+ }
3269
+
3270
+ function processElement ( element : TypeScript . ISyntaxElement ) {
3271
+ // Ignore nodes that don't intersect the original span to classify.
3272
+ if ( ! TypeScript . isShared ( element ) && span . intersectsWith ( TypeScript . fullStart ( element ) , TypeScript . fullWidth ( element ) ) ) {
3273
+ for ( var i = 0 , n = TypeScript . childCount ( element ) ; i < n ; i ++ ) {
3274
+ var child = TypeScript . childAt ( element , i ) ;
3275
+ if ( child ) {
3276
+ if ( TypeScript . isToken ( child ) ) {
3277
+ classifyToken ( < TypeScript . ISyntaxToken > child ) ;
3278
+ }
3279
+ else {
3280
+ // Recurse into our child nodes.
3281
+ processElement ( child ) ;
3282
+ }
3283
+ }
3284
+ }
3285
+ }
3286
+ }
3287
+ }
3288
+
3127
3289
function getOutliningSpans ( filename : string ) : OutliningSpan [ ] {
3128
3290
// doesn't use compiler - no need to synchronize with host
3129
3291
filename = TypeScript . switchToForwardSlashes ( filename ) ;
@@ -3371,6 +3533,7 @@ module ts {
3371
3533
getSyntacticDiagnostics : getSyntacticDiagnostics ,
3372
3534
getSemanticDiagnostics : getSemanticDiagnostics ,
3373
3535
getCompilerOptionsDiagnostics : getCompilerOptionsDiagnostics ,
3536
+ getSyntacticClassifications : getSyntacticClassifications ,
3374
3537
getCompletionsAtPosition : getCompletionsAtPosition ,
3375
3538
getCompletionEntryDetails : getCompletionEntryDetails ,
3376
3539
getTypeAtPosition : getTypeAtPosition ,
0 commit comments