11package checker
22
33import (
4+ "slices"
5+
46 "github.com/microsoft/TypeScript/tsc/internal/ast"
57 "github.com/microsoft/TypeScript/tsc/internal/core"
68 "github.com/microsoft/TypeScript/tsc/internal/debug"
9+ "github.com/microsoft/TypeScript/tsc/internal/jsnum"
710 "github.com/microsoft/TypeScript/tsc/internal/nodebuilder"
11+ "github.com/microsoft/TypeScript/tsc/internal/scanner"
812)
913
10- func cloneNodeBuilderContext (context * NodeBuilderContext ) func () {
14+ func enterTypeParameterNameScope (context * NodeBuilderContext ) func () {
1115 // Make type parameters created within this context not consume the name outside this context
1216 // The symbol serializer ends up creating many sibling scopes that all need "separate" contexts when
1317 // it comes to naming things - within a normal `typeToTypeNode` call, the node builder only ever descends
@@ -50,14 +54,256 @@ func (b *NodeBuilderImpl) addSymbolTypeToContext(symbol *ast.Symbol, t *Type) fu
5054 }
5155}
5256
57+ func (b * NodeBuilderImpl ) serializationTypeId (t * Type ) TypeId {
58+ if b .ch .isArrayOrTupleType (t ) {
59+ // Deferred and regular references share a serialization identity.
60+ return b .ch .createTypeReference (t .Target (), b .ch .getTypeArguments (t )).id
61+ }
62+ return t .id
63+ }
64+
65+ func (b * NodeBuilderImpl ) enterTypeDefinition (t * Type , symbol * ast.Symbol , expanding bool ) func () {
66+ return b .enterDefinition (serializationDefinition {t : t , typeId : b .serializationTypeId (t ), symbol : symbol , expanding : expanding })
67+ }
68+
69+ func (b * NodeBuilderImpl ) enterDefinition (definition serializationDefinition ) func () {
70+ definitions := b .ctx .definitions
71+ definition .depth = b .ctx .deferredTypeDepth
72+ b .ctx .definitions = append (definitions , definition )
73+ return func () { b .ctx .definitions = definitions }
74+ }
75+
76+ // Lexical scopes alone do not guard back-references; only lazy member boundaries do.
77+ func (b * NodeBuilderImpl ) enterDeferredTypeScope () func () {
78+ depth := b .ctx .deferredTypeDepth
79+ b .ctx .deferredTypeDepth ++
80+ return func () { b .ctx .deferredTypeDepth = depth }
81+ }
82+
83+ func (b * NodeBuilderImpl ) enterInferTypeParameterScope (typeParameters []* Type ) func () {
84+ inferTypeParameters := b .ctx .inferTypeParameters
85+ b .ctx .inferTypeParameters = typeParameters
86+ return func () { b .ctx .inferTypeParameters = inferTypeParameters }
87+ }
88+
89+ func (b * NodeBuilderImpl ) isSameSerializationType (t * Type , typeId TypeId , definition serializationDefinition ) bool {
90+ if typeId == definition .typeId {
91+ return true
92+ }
93+ other := definition .t
94+ // Regular and widened objects may have different IDs without changing shape.
95+ // Do not collapse distinct generic instantiations.
96+ return t .objectFlags & (ObjectFlagsAnonymous | ObjectFlagsInstantiated ) == ObjectFlagsAnonymous &&
97+ other .objectFlags & (ObjectFlagsAnonymous | ObjectFlagsInstantiated ) == ObjectFlagsAnonymous &&
98+ t .symbol != nil && t .symbol == other .symbol && b .ch .isTypeIdenticalTo (t , other )
99+ }
100+
101+ func (b * NodeBuilderImpl ) getTypeDefinitionReference (t * Type ) serializationTypeName {
102+ var typeId TypeId
103+ for _ , definition := range b .ctx .definitions {
104+ if b .ctx .deferredTypeDepth <= definition .depth {
105+ continue
106+ }
107+ if signature := definition .signature ; signature != nil {
108+ if t .objectFlags & ObjectFlagsAnonymous == 0 {
109+ continue
110+ }
111+ kind := core .IfElse (signature .flags & SignatureFlagsConstruct != 0 , SignatureKindConstruct , SignatureKindCall )
112+ if ! slices .Contains (b .ch .getSignaturesOfType (t , kind ), signature ) {
113+ continue
114+ }
115+ } else {
116+ if typeId == 0 {
117+ typeId = b .serializationTypeId (t )
118+ }
119+ if ! b .isSameSerializationType (t , typeId , definition ) {
120+ continue
121+ }
122+ }
123+ var name serializationTypeName
124+ if symbol := definition .symbol ; symbol != nil {
125+ if symbol .Flags ()& (ast .SymbolFlagsProperty | ast .SymbolFlagsMethod | ast .SymbolFlagsAccessor ) != 0 {
126+ name = b .getSerializationTypeNameFromDeclaration (t , symbol .ValueDeclaration ())
127+ } else {
128+ name = b .getValueTypeName (t , symbol , nil )
129+ }
130+ } else {
131+ name = b .getSerializationValueName (t )
132+ }
133+ if name .symbol != nil && b .isSerializationTypeNameAccessible (name ) {
134+ return name
135+ }
136+ }
137+ return serializationTypeName {}
138+ }
139+
140+ func (b * NodeBuilderImpl ) getValueTypeName (t * Type , symbol * ast.Symbol , path []* Type ) serializationTypeName {
141+ if symbol == nil || symbol .Flags ()& ast .SymbolFlagsValue == 0 || t .flags & TypeFlagsStructuredOrInstantiable == 0 ||
142+ IsPrivateIdentifierSymbol (symbol ) || b .ctx .flags & nodebuilder .FlagsUseStructuralFallback != 0 && getDeclarationModifierFlagsFromSymbol (symbol )& (ast .ModifierFlagsPrivate | ast .ModifierFlagsProtected ) != 0 ||
143+ ! scanner .IsIdentifierText (symbol .Name (), core .LanguageVariantStandard ) {
144+ return serializationTypeName {}
145+ }
146+ // Formatting a diagnostic must not restart inference for a declaration
147+ // whose type is still being resolved.
148+ namedType := b .ch .valueSymbolLinks .Get (symbol ).resolvedType
149+ if namedType == nil {
150+ return serializationTypeName {}
151+ }
152+ for _ , index := range path {
153+ property := b .ch .getPropertyOfType (namedType , getPropertyNameFromType (index ))
154+ if property != nil {
155+ if IsPrivateIdentifierSymbol (property ) || b .ctx .flags & nodebuilder .FlagsUseStructuralFallback != 0 && getDeclarationModifierFlagsFromSymbol (property )& (ast .ModifierFlagsPrivate | ast .ModifierFlagsProtected ) != 0 ||
156+ b .ch .findResolutionCycleStartIndex (property , TypeSystemPropertyNameType ) >= 0 {
157+ return serializationTypeName {}
158+ }
159+ }
160+ namedType = b .ch .getIndexedAccessType (namedType , index )
161+ }
162+ if b .serializationTypeId (namedType ) != b .serializationTypeId (t ) {
163+ return serializationTypeName {}
164+ }
165+ return serializationTypeName {symbol : symbol , meaning : ast .SymbolFlagsValue , path : path }
166+ }
167+
168+ func (b * NodeBuilderImpl ) getSerializationValueName (t * Type ) serializationTypeName {
169+ if t .objectFlags & ObjectFlagsAnonymous == 0 || t .symbol == nil {
170+ return serializationTypeName {}
171+ }
172+ node := t .symbol .ValueDeclaration ()
173+ if node != nil && (ast .IsExpression (node ) || ast .IsClassElement (node ) || ast .IsPropertyAssignment (node )) {
174+ if name := b .getSerializationTypeNameFromDeclaration (t , node ); name .symbol != nil {
175+ return name
176+ }
177+ }
178+ return b .getValueTypeName (t , t .symbol , nil )
179+ }
180+
181+ func (b * NodeBuilderImpl ) isSerializationTypeNameAccessible (name serializationTypeName ) bool {
182+ if b .ctx .flags & nodebuilder .FlagsForbidIndexedAccessSymbolReferences != 0 &&
183+ (len (name .path ) != 0 || name .symbol .Flags ()& (ast .SymbolFlagsProperty | ast .SymbolFlagsMethod | ast .SymbolFlagsAccessor ) != 0 ) {
184+ return false
185+ }
186+ // Displays may use lexical names whose declarations cannot be exposed in a .d.ts.
187+ if b .ctx .flags & nodebuilder .FlagsUseStructuralFallback == 0 && b .ctx .enclosingDeclaration != nil &&
188+ b .ch .resolveName (b .ctx .enclosingDeclaration , name .symbol .Name (), name .meaning , nil /*nameNotFoundMessage*/ , false /*isUse*/ , false /*excludeGlobals*/ ) == name .symbol {
189+ return true
190+ }
191+ return b .ch .IsValueSymbolAccessible (name .symbol , b .ctx .enclosingDeclaration )
192+ }
193+
194+ func (b * NodeBuilderImpl ) serializationTypeNameToNode (name serializationTypeName ) * ast.TypeNode {
195+ typeArguments := b .mapToTypeNodes (name .typeArguments , false /*isBareList*/ )
196+ if name .meaning == ast .SymbolFlagsType {
197+ if isReservedMemberName (name .symbol .Name ()) && name .symbol .Flags ()& ast .SymbolFlagsClass == 0 {
198+ return b .f .NewTypeReferenceNode (b .f .NewIdentifier ("" ), typeArguments )
199+ }
200+ if typeArguments != nil && len (typeArguments .Nodes ) == 1 && name .symbol == b .ch .globalArrayType .symbol {
201+ return b .f .NewArrayTypeNode (typeArguments .Nodes [0 ])
202+ }
203+ }
204+ node := b .symbolToTypeNode (name .symbol , name .meaning , typeArguments )
205+ restoreFlags := b .saveRestoreFlags ()
206+ b .ctx .flags &^= nodebuilder .FlagsAllowUniqueESSymbolType
207+ for _ , index := range name .path {
208+ b .ctx .approximateLength += 2
209+ node = b .f .NewIndexedAccessTypeNode (node , b .typeToTypeNode (index ))
210+ }
211+ restoreFlags ()
212+ return node
213+ }
214+
215+ func (b * NodeBuilderImpl ) prefersTypeOfFunction (t * Type , name serializationTypeName ) bool {
216+ if name .symbol == nil || name .meaning != ast .SymbolFlagsValue || t .symbol == nil {
217+ return false
218+ }
219+ symbol := t .symbol
220+ if symbol .Flags ()& ast .SymbolFlagsMethod != 0 {
221+ return core .Some (symbol .Declarations (), ast .IsStatic )
222+ }
223+ if symbol .Flags ()& ast .SymbolFlagsFunction == 0 || len (name .path ) != 0 {
224+ return false
225+ }
226+ declaration := name .symbol .ValueDeclaration ()
227+ if declaration == nil || ast .IsVariableDeclaration (declaration ) && declaration == b .ctx .enclosingDeclaration {
228+ return false
229+ }
230+ if ast .IsVariableDeclaration (declaration ) {
231+ if declaration .Parent == nil || ! ast .IsVariableDeclarationList (declaration .Parent ) || declaration .Parent .Parent == nil {
232+ return false
233+ }
234+ declaration = declaration .Parent .Parent
235+ }
236+ return symbol .Parent () != nil || declaration .Parent != nil &&
237+ (declaration .Parent .Kind == ast .KindSourceFile || declaration .Parent .Kind == ast .KindModuleBlock )
238+ }
239+
240+ func (b * NodeBuilderImpl ) getSerializationTypeNameFromDeclaration (t * Type , node * ast.Node ) serializationTypeName {
241+ var path []* Type
242+ for node != nil {
243+ if declaration := getAssignedValueDeclaration (node ); declaration != nil && ! ast .IsStatic (declaration ) {
244+ slices .Reverse (path )
245+ return b .getValueTypeName (t , b .ch .getSymbolOfDeclaration (declaration ), path )
246+ }
247+ parent := walkUpOuterExpressions (node )
248+ if parent == nil {
249+ return serializationTypeName {}
250+ }
251+ switch {
252+ case ast .IsPropertyDeclaration (parent ):
253+ node = parent
254+ case ast .IsPropertyAssignment (parent ):
255+ index := b .ch .getLiteralTypeFromPropertyName (parent .Name ())
256+ if ! isTypeUsableAsPropertyName (index ) {
257+ return serializationTypeName {}
258+ }
259+ path = append (path , index )
260+ node = parent .Parent
261+ case ast .IsObjectLiteralExpression (parent ), ast .IsClassLike (parent ):
262+ if node .Name () == nil {
263+ return serializationTypeName {}
264+ }
265+ index := b .ch .getLiteralTypeFromPropertyName (node .Name ())
266+ if ! isTypeUsableAsPropertyName (index ) {
267+ return serializationTypeName {}
268+ }
269+ path = append (path , index )
270+ if ast .IsClassDeclaration (parent ) {
271+ slices .Reverse (path )
272+ return b .getValueTypeName (t , b .ch .getSymbolOfDeclaration (parent ), path )
273+ }
274+ node = parent
275+ case ast .IsArrayLiteralExpression (parent ):
276+ elements := parent .AsArrayLiteralExpression ().Elements .Nodes
277+ index := slices .IndexFunc (elements , func (element * ast.Node ) bool {
278+ return ast .SkipOuterExpressions (element , ast .OEKAll ) == node
279+ })
280+ if index < 0 || core .Some (elements [:index ], ast .IsSpreadElement ) {
281+ return serializationTypeName {}
282+ }
283+ path = append (path , b .ch .getNumberLiteralType (jsnum .Number (index )))
284+ node = parent
285+ default :
286+ return serializationTypeName {}
287+ }
288+ }
289+ return serializationTypeName {}
290+ }
291+
53292func (b * NodeBuilderImpl ) enterSignatureScope (signature * Signature ) (expandedParams []* ast.Symbol , cleanup func ()) {
293+ restoreDefinition := b .enterDefinition (serializationDefinition {signature : signature })
294+ restoreDeferredTypeScope := b .enterDeferredTypeScope ()
54295 expandedParams = b .ch .getExpandedParameters (signature , true /*skipUnionExpanding*/ )[0 ]
55- cleanup = b .enterNewScope (signature .declaration , expandedParams , signature .typeParameters , signature .parameters , signature .mapper )
296+ restoreScope := b .enterNewScope (signature .declaration , expandedParams , signature .typeParameters , signature .parameters , signature .mapper )
297+ cleanup = func () {
298+ restoreScope ()
299+ restoreDeferredTypeScope ()
300+ restoreDefinition ()
301+ }
56302 return expandedParams , cleanup
57303}
58304
59305func (b * NodeBuilderImpl ) enterNewScope (declaration * ast.Node , expandedParams []* ast.Symbol , typeParameters []* Type , originalParameters []* ast.Symbol , mapper * TypeMapper ) func () {
60- cleanupContext := cloneNodeBuilderContext (b .ctx )
306+ cleanupNames := enterTypeParameterNameScope (b .ctx )
61307 // For regular function/method declarations, the enclosing declaration will already be signature.declaration,
62308 // so this is a no-op, but for arrow functions and function expressions, the enclosing declaration will be
63309 // the declaration that the arrow function / function expression is assigned to.
@@ -77,6 +323,15 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams []
77323 if mapper != nil {
78324 b .ctx .mapper = mapper
79325 }
326+ if mapper := b .ctx .mapper ; mapper != nil && len (typeParameters ) != 0 {
327+ // Bound type parameters shadow inherited substitutions; captured parameters do not.
328+ b .ctx .mapper = newFunctionTypeMapper (func (t * Type ) * Type {
329+ if slices .Contains (typeParameters , t ) {
330+ return t
331+ }
332+ return mapper .Map (t )
333+ })
334+ }
80335 if b .ctx .enclosingDeclaration != nil && declaration != nil {
81336 // As a performance optimization, reuse the same fake scope within this chain.
82337 // This is especially needed when we are working on an excessively deep type;
@@ -244,7 +499,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams []
244499 if cleanupTypeParams != nil {
245500 cleanupTypeParams ()
246501 }
247- cleanupContext ()
502+ cleanupNames ()
248503 b .ctx .enclosingDeclaration = oldEnclosingDecl
249504 b .ctx .mapper = oldMapper
250505 }
0 commit comments