@@ -488,89 +488,71 @@ namespace ts {
488488
489489 /* @internal */
490490 export function getEncodedSemanticClassifications ( typeChecker : TypeChecker , cancellationToken : CancellationToken , sourceFile : SourceFile , classifiableNames : UnderscoreEscapedMap < true > , span : TextSpan ) : Classifications {
491- const result : number [ ] = [ ] ;
492- processNode ( sourceFile ) ;
493-
494- return { spans : result , endOfLineState : EndOfLineState . None } ;
495-
496- function pushClassification ( start : number , length : number , type : ClassificationType ) {
497- result . push ( start ) ;
498- result . push ( length ) ;
499- result . push ( type ) ;
500- }
501-
502- function classifySymbol ( symbol : Symbol , meaningAtPosition : SemanticMeaning ) : ClassificationType {
503- const flags = symbol . getFlags ( ) ;
504- if ( ( flags & SymbolFlags . Classifiable ) === SymbolFlags . None ) {
491+ const spans : number [ ] = [ ] ;
492+ sourceFile . forEachChild ( function cb ( node : Node ) : void {
493+ // Only walk into nodes that intersect the requested span.
494+ if ( ! node || ! textSpanIntersectsWith ( span , node . pos , node . getFullWidth ( ) ) ) {
505495 return ;
506496 }
507497
508- if ( flags & SymbolFlags . Class ) {
509- return ClassificationType . className ;
510- }
511- else if ( flags & SymbolFlags . Enum ) {
512- return ClassificationType . enumName ;
513- }
514- else if ( flags & SymbolFlags . TypeAlias ) {
515- return ClassificationType . typeAliasName ;
516- }
517- else if ( meaningAtPosition & SemanticMeaning . Type ) {
518- if ( flags & SymbolFlags . Interface ) {
519- return ClassificationType . interfaceName ;
520- }
521- else if ( flags & SymbolFlags . TypeParameter ) {
522- return ClassificationType . typeParameterName ;
523- }
524- }
525- else if ( flags & SymbolFlags . Module ) {
526- // Only classify a module as such if
527- // - It appears in a namespace context.
528- // - There exists a module declaration which actually impacts the value side.
529- if ( meaningAtPosition & SemanticMeaning . Namespace ||
530- ( meaningAtPosition & SemanticMeaning . Value && hasValueSideModule ( symbol ) ) ) {
531- return ClassificationType . moduleName ;
498+ checkForClassificationCancellation ( cancellationToken , node . kind ) ;
499+ // Only bother calling into the typechecker if this is an identifier that
500+ // could possibly resolve to a type name. This makes classification run
501+ // in a third of the time it would normally take.
502+ if ( isIdentifier ( node ) && ! nodeIsMissing ( node ) && classifiableNames . has ( node . escapedText ) ) {
503+ const symbol = typeChecker . getSymbolAtLocation ( node ) ;
504+ const type = symbol && classifySymbol ( symbol , getMeaningFromLocation ( node ) , typeChecker ) ;
505+ if ( type ) {
506+ pushClassification ( node . getStart ( sourceFile ) , node . getEnd ( ) , type ) ;
532507 }
533508 }
534509
535- return undefined ;
510+ node . forEachChild ( cb ) ;
511+ } ) ;
512+ return { spans, endOfLineState : EndOfLineState . None } ;
536513
537- /**
538- * Returns true if there exists a module that introduces entities on the value side.
539- */
540- function hasValueSideModule ( symbol : Symbol ) : boolean {
541- return forEach ( symbol . declarations , declaration => {
542- return declaration . kind === SyntaxKind . ModuleDeclaration &&
543- getModuleInstanceState ( declaration ) === ModuleInstanceState . Instantiated ;
544- } ) ;
545- }
514+ function pushClassification ( start : number , end : number , type : ClassificationType ) : void {
515+ spans . push ( start ) ;
516+ spans . push ( end - start ) ;
517+ spans . push ( type ) ;
546518 }
519+ }
547520
548- function processNode ( node : Node ) {
549- // Only walk into nodes that intersect the requested span.
550- if ( node && textSpanIntersectsWith ( span , node . getFullStart ( ) , node . getFullWidth ( ) ) ) {
551- const kind = node . kind ;
552- checkForClassificationCancellation ( cancellationToken , kind ) ;
553-
554- if ( kind === SyntaxKind . Identifier && ! nodeIsMissing ( node ) ) {
555- const identifier = < Identifier > node ;
556-
557- // Only bother calling into the typechecker if this is an identifier that
558- // could possibly resolve to a type name. This makes classification run
559- // in a third of the time it would normally take.
560- if ( classifiableNames . has ( identifier . escapedText ) ) {
561- const symbol = typeChecker . getSymbolAtLocation ( node ) ;
562- if ( symbol ) {
563- const type = classifySymbol ( symbol , getMeaningFromLocation ( node ) ) ;
564- if ( type ) {
565- pushClassification ( node . getStart ( ) , node . getWidth ( ) , type ) ;
566- }
567- }
568- }
569- }
570-
571- forEachChild ( node , processNode ) ;
572- }
521+ function classifySymbol ( symbol : Symbol , meaningAtPosition : SemanticMeaning , checker : TypeChecker ) : ClassificationType | undefined {
522+ const flags = symbol . getFlags ( ) ;
523+ if ( ( flags & SymbolFlags . Classifiable ) === SymbolFlags . None ) {
524+ return undefined ;
525+ }
526+ else if ( flags & SymbolFlags . Class ) {
527+ return ClassificationType . className ;
573528 }
529+ else if ( flags & SymbolFlags . Enum ) {
530+ return ClassificationType . enumName ;
531+ }
532+ else if ( flags & SymbolFlags . TypeAlias ) {
533+ return ClassificationType . typeAliasName ;
534+ }
535+ else if ( flags & SymbolFlags . Module ) {
536+ // Only classify a module as such if
537+ // - It appears in a namespace context.
538+ // - There exists a module declaration which actually impacts the value side.
539+ return meaningAtPosition & SemanticMeaning . Namespace || meaningAtPosition & SemanticMeaning . Value && hasValueSideModule ( symbol ) ? ClassificationType . moduleName : undefined ;
540+ }
541+ else if ( flags & SymbolFlags . Alias ) {
542+ return classifySymbol ( checker . getAliasedSymbol ( symbol ) , meaningAtPosition , checker ) ;
543+ }
544+ else if ( meaningAtPosition & SemanticMeaning . Type ) {
545+ return flags & SymbolFlags . Interface ? ClassificationType . interfaceName : flags & SymbolFlags . TypeParameter ? ClassificationType . typeParameterName : undefined ;
546+ }
547+ else {
548+ return undefined ;
549+ }
550+ }
551+
552+ /** Returns true if there exists a module that introduces entities on the value side. */
553+ function hasValueSideModule ( symbol : Symbol ) : boolean {
554+ return some ( symbol . declarations , declaration =>
555+ isModuleDeclaration ( declaration ) && getModuleInstanceState ( declaration ) === ModuleInstanceState . Instantiated ) ;
574556 }
575557
576558 function getClassificationTypeName ( type : ClassificationType ) : ClassificationTypeNames {
0 commit comments