@@ -23,6 +23,20 @@ module ts {
23
23
return undefined ;
24
24
}
25
25
26
+ interface SymbolWriter {
27
+ write ( text : string , kind : SymbolDisplayPartKind , symbol : Symbol ) : void ;
28
+ displayPartKind ( symbol : Symbol ) : SymbolDisplayPartKind ;
29
+ clear ( ) : void ;
30
+ }
31
+
32
+ interface DisplayPartsSymbolWriter extends SymbolWriter {
33
+ displayParts ( ) : SymbolDisplayPart [ ] ;
34
+ }
35
+
36
+ interface StringSymbolWriter extends SymbolWriter {
37
+ string ( ) : string ;
38
+ }
39
+
26
40
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
27
41
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
28
42
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
@@ -62,7 +76,9 @@ module ts {
62
76
getTypeOfNode : getTypeOfNode ,
63
77
getApparentType : getApparentType ,
64
78
typeToString : typeToString ,
79
+ typeToDisplayParts : undefined ,
65
80
symbolToString : symbolToString ,
81
+ symbolToDisplayParts : symbolToDisplayParts ,
66
82
getAugmentedPropertiesOfApparentType : getAugmentedPropertiesOfApparentType ,
67
83
getRootSymbol : getRootSymbol ,
68
84
getContextualType : getContextualType ,
@@ -895,51 +911,154 @@ module ts {
895
911
{ accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : firstIdentifierName } ;
896
912
}
897
913
914
+ var displayPartWriters : DisplayPartsSymbolWriter [ ] = [ ] ;
915
+ var stringWriters : StringSymbolWriter [ ] = [ ] ;
916
+
917
+ function displayPartKind ( symbol : Symbol ) : SymbolDisplayPartKind {
918
+ var flags = symbol . flags ;
919
+
920
+ if ( flags & SymbolFlags . Variable ) {
921
+ return symbol . declarations && symbol . declarations . length > 0 && symbol . declarations [ 0 ] . kind === SyntaxKind . Parameter
922
+ ? SymbolDisplayPartKind . ParameterName
923
+ : SymbolDisplayPartKind . LocalName ;
924
+ }
925
+ else if ( flags & SymbolFlags . Property ) { return SymbolDisplayPartKind . PropertyName ; }
926
+ else if ( flags & SymbolFlags . EnumMember ) { return SymbolDisplayPartKind . EnumMemberName ; }
927
+ else if ( flags & SymbolFlags . Function ) { return SymbolDisplayPartKind . FunctionName ; }
928
+ else if ( flags & SymbolFlags . Class ) { return SymbolDisplayPartKind . ClassName ; }
929
+ else if ( flags & SymbolFlags . Interface ) { return SymbolDisplayPartKind . InterfaceName ; }
930
+ else if ( flags & SymbolFlags . Enum ) { return SymbolDisplayPartKind . EnumName ; }
931
+ else if ( flags & SymbolFlags . Module ) { return SymbolDisplayPartKind . ModuleName ; }
932
+ else if ( flags & SymbolFlags . Method ) { return SymbolDisplayPartKind . MethodName ; }
933
+ else if ( flags & SymbolFlags . TypeParameter ) { return SymbolDisplayPartKind . TypeParameterName ; }
934
+
935
+ return SymbolDisplayPartKind . Text ;
936
+ }
937
+
938
+ function getDisplayPartWriter ( ) : DisplayPartsSymbolWriter {
939
+ if ( displayPartWriters . length == 0 ) {
940
+ var displayParts : SymbolDisplayPart [ ] = [ ] ;
941
+ return {
942
+ displayParts : ( ) => displayParts ,
943
+ write : ( text , kind , symbol ) => displayParts . push ( { text : text , kind : kind , symbol : symbol } ) ,
944
+ clear : ( ) => displayParts = [ ] ,
945
+ displayPartKind : displayPartKind
946
+ } ;
947
+ }
948
+
949
+ return displayPartWriters . pop ( ) ;
950
+ }
951
+
952
+ function getStringWriter ( ) : StringSymbolWriter {
953
+ if ( stringWriters . length == 0 ) {
954
+ var str = "" ;
955
+
956
+ return {
957
+ string : ( ) => str ,
958
+ write : text => str += text ,
959
+ clear : ( ) => str = "" ,
960
+ displayPartKind : ( symbol : Symbol ) : SymbolDisplayPartKind => undefined
961
+ } ;
962
+ }
963
+
964
+ return stringWriters . pop ( ) ;
965
+ }
966
+
967
+ function releaseDisplayPartWriter ( writer : DisplayPartsSymbolWriter ) {
968
+ writer . clear ( ) ;
969
+ displayPartWriters . push ( writer ) ;
970
+ }
971
+
972
+ function releaseStringWriter ( writer : StringSymbolWriter ) {
973
+ writer . clear ( )
974
+ stringWriters . push ( writer ) ;
975
+ }
976
+
977
+ function symbolToDisplayParts ( symbol : Symbol , enclosingDeclaration ?: Node , meaning ?: SymbolFlags ) : SymbolDisplayPart [ ] {
978
+ var writer = getDisplayPartWriter ( ) ;
979
+ writeSymbol ( symbol , enclosingDeclaration , meaning , writer ) ;
980
+
981
+ var result = writer . displayParts ( ) ;
982
+ releaseDisplayPartWriter ( writer ) ;
983
+
984
+ return result ;
985
+ }
986
+
987
+ function symbolToString ( symbol : Symbol , enclosingDeclaration ?: Node , meaning ?: SymbolFlags ) : string {
988
+ var writer = getStringWriter ( ) ;
989
+ writeSymbol ( symbol , enclosingDeclaration , meaning , writer ) ;
990
+
991
+ var result = writer . string ( ) ;
992
+ releaseStringWriter ( writer ) ;
993
+
994
+ return result ;
995
+ }
996
+
898
997
// Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
899
998
// Meaning needs to be specified if the enclosing declaration is given
900
- function symbolToString ( symbol : Symbol , enclosingDeclaration ? : Node , meaning ? : SymbolFlags ) {
901
- function getSymbolName ( symbol : Symbol ) {
999
+ function writeSymbol ( symbol : Symbol , enclosingDeclaration : Node , meaning : SymbolFlags , writer : SymbolWriter ) : void {
1000
+ function writeSymbolName ( symbol : Symbol ) : void {
902
1001
if ( symbol . declarations && symbol . declarations . length > 0 ) {
903
1002
var declaration = symbol . declarations [ 0 ] ;
904
1003
if ( declaration . name ) {
905
- return identifierToString ( declaration . name ) ;
1004
+ writer . write ( identifierToString ( declaration . name ) , writer . displayPartKind ( symbol ) , symbol ) ;
1005
+ return ;
906
1006
}
907
1007
}
908
- return symbol . name ;
1008
+
1009
+ writer . write ( symbol . name , writer . displayPartKind ( symbol ) , symbol ) ;
909
1010
}
910
1011
911
- // Get qualified name
912
- if ( enclosingDeclaration &&
913
- // TypeParameters do not need qualification
914
- ! ( symbol . flags & SymbolFlags . TypeParameter ) ) {
915
- var symbolName : string ;
916
- while ( symbol ) {
917
- var isFirstName = ! symbolName ;
1012
+ var needsDot = false ;
1013
+ function walkSymbol ( symbol : Symbol , meaning : SymbolFlags ) : void {
1014
+ if ( symbol ) {
918
1015
var accessibleSymbolChain = getAccessibleSymbolChain ( symbol , enclosingDeclaration , meaning ) ;
919
1016
920
- var currentSymbolName : string ;
1017
+ if ( ! accessibleSymbolChain ||
1018
+ needsQualification ( accessibleSymbolChain [ 0 ] , enclosingDeclaration , accessibleSymbolChain . length === 1 ? meaning : getQualifiedLeftMeaning ( meaning ) ) ) {
1019
+
1020
+ // Go up and add our parent.
1021
+ walkSymbol (
1022
+ getParentOfSymbol ( accessibleSymbolChain ? accessibleSymbolChain [ 0 ] : symbol ) ,
1023
+ getQualifiedLeftMeaning ( meaning ) ) ;
1024
+ }
1025
+
921
1026
if ( accessibleSymbolChain ) {
922
- currentSymbolName = ts . map ( accessibleSymbolChain , accessibleSymbol => getSymbolName ( accessibleSymbol ) ) . join ( "." ) ;
1027
+ for ( var i = 0 , n = accessibleSymbolChain . length ; i < n ; i ++ ) {
1028
+ if ( needsDot ) {
1029
+ writer . write ( "." , SymbolDisplayPartKind . Punctuation , /*symbol:*/ undefined ) ;
1030
+ }
1031
+
1032
+ writeSymbolName ( accessibleSymbolChain [ i ] ) ;
1033
+ needsDot = true ;
1034
+ }
923
1035
}
924
1036
else {
925
1037
// If we didn't find accessible symbol chain for this symbol, break if this is external module
926
- if ( ! isFirstName && ts . forEach ( symbol . declarations , declaration => hasExternalModuleSymbol ( declaration ) ) ) {
927
- break ;
1038
+ if ( ! needsDot && ts . forEach ( symbol . declarations , declaration => hasExternalModuleSymbol ( declaration ) ) ) {
1039
+ return ;
928
1040
}
929
- currentSymbolName = getSymbolName ( symbol ) ;
930
- }
931
- symbolName = currentSymbolName + ( isFirstName ? "" : ( "." + symbolName ) ) ;
932
- if ( accessibleSymbolChain && ! needsQualification ( accessibleSymbolChain [ 0 ] , enclosingDeclaration , accessibleSymbolChain . length === 1 ? meaning : getQualifiedLeftMeaning ( meaning ) ) ) {
933
- break ;
1041
+
1042
+ if ( needsDot ) {
1043
+ writer . write ( "." , SymbolDisplayPartKind . Punctuation , /*symbol:*/ undefined ) ;
1044
+ }
1045
+
1046
+ writeSymbolName ( symbol ) ;
1047
+ needsDot = true ;
934
1048
}
935
- symbol = getParentOfSymbol ( accessibleSymbolChain ? accessibleSymbolChain [ 0 ] : symbol ) ;
936
- meaning = getQualifiedLeftMeaning ( meaning ) ;
937
1049
}
1050
+ }
1051
+
1052
+ // Get qualified name
1053
+ if ( enclosingDeclaration &&
1054
+ // TypeParameters do not need qualification
1055
+ ! ( symbol . flags & SymbolFlags . TypeParameter ) ) {
938
1056
939
- return symbolName ;
1057
+ walkSymbol ( symbol , meaning ) ;
1058
+ return ;
940
1059
}
941
1060
942
- return getSymbolName ( symbol ) ;
1061
+ return writeSymbolName ( symbol ) ;
943
1062
}
944
1063
945
1064
function writeSymbolToTextWriter ( symbol : Symbol , enclosingDeclaration : Node , meaning : SymbolFlags , writer : TextWriter ) {
0 commit comments