package checker import ( "fmt" "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/jsnum" "github.com/microsoft/typescript-go/internal/nodebuilder" "github.com/microsoft/typescript-go/internal/scanner" ) // isExpanding returns whether the node builder context is operating in hover-expansion mode. func isExpanding(ctx *NodeBuilderContext) bool { return ctx.maxExpansionDepth != -1 } // expandSymbolForHover produces declaration nodes (class, interface, enum, module) for a symbol // for expandable hover. This is a focused alternative to the full symbolTableToDeclarationStatements // machinery used by declaration emit — it directly builds the declaration nodes hover needs // without the declaration-emit scaffolding (deferred privates, symbol name remapping, export // modifier computation, alias resolution, visited symbols tracking). func (b *NodeBuilderImpl) expandSymbolForHover(symbol *ast.Symbol) []*ast.Node { var results []*ast.Node if symbol.Flags&ast.SymbolFlagsEnum != 0 { if node := b.expandEnumDecl(symbol); node != nil { results = append(results, node) } } if symbol.Flags&ast.SymbolFlagsClass != 0 { if node := b.expandClassDecl(symbol); node != nil { results = append(results, node) } } // Module/namespace before interface (matching Strada ordering for merged declarations) if symbol.Flags&(ast.SymbolFlagsValueModule|ast.SymbolFlagsNamespaceModule) != 0 { if node := b.expandModuleDecl(symbol); node != nil { results = append(results, node) } } if symbol.Flags&ast.SymbolFlagsInterface != 0 && symbol.Flags&ast.SymbolFlagsClass == 0 { if node := b.expandInterfaceDecl(symbol); node != nil { results = append(results, node) } } return results } // expandEnumDecl produces an EnumDeclaration node with all members. func (b *NodeBuilderImpl) expandEnumDecl(symbol *ast.Symbol) *ast.Node { name := ast.SymbolName(symbol) b.ctx.approximateLength += 9 + len(name) memberProps := core.Filter(b.ch.getPropertiesOfType(b.ch.getTypeOfSymbol(symbol)), func(p *ast.Symbol) bool { return p.Flags&ast.SymbolFlagsEnumMember != 0 }) var members []*ast.Node for i, p := range memberProps { if b.checkTruncationLengthIfExpanding() && i+3 < len(memberProps)-1 { b.ctx.expansionTruncated = true members = append(members, b.f.NewEnumMember(b.f.NewStringLiteral(fmt.Sprintf(" ... %d more ... ", len(memberProps)-i-1), 0), nil)) last := memberProps[len(memberProps)-1] members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(last.Name), b.enumMemberInitializer(last))) break } memberDecl := core.Find(p.Declarations, ast.IsEnumMember) var initializer *ast.Node if memberDecl != nil && memberDecl.AsEnumMember().Initializer != nil { initializer = b.f.DeepCloneNode(memberDecl.AsEnumMember().Initializer) } else { initializer = b.enumMemberInitializer(p) } b.ctx.approximateLength += 4 + len(p.Name) if initializer != nil { b.ctx.approximateLength += 5 // " = " + value estimate } members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(p.Name), initializer)) } constModifier := ast.ModifierFlagsNone if isConstEnumSymbol(symbol) { constModifier = ast.ModifierFlagsConst } var mods *ast.ModifierList if constModifier != 0 { mods = b.f.NewModifierList(ast.CreateModifiersFromModifierFlags(constModifier, b.f.NewModifier)) } return b.f.NewEnumDeclaration(mods, b.f.NewIdentifier(name), b.f.NewNodeList(members)) } func (b *NodeBuilderImpl) enumMemberInitializer(p *ast.Symbol) *ast.Node { memberDecl := core.Find(p.Declarations, ast.IsEnumMember) if memberDecl == nil { return nil } val := b.ch.GetConstantValue(memberDecl) if val == nil { return nil } switch v := val.(type) { case string: return b.f.NewStringLiteral(v, 0) case jsnum.Number: return b.f.NewNumericLiteral(v.String(), 0) } return nil } // expandClassDecl produces a ClassDeclaration node with heritage clauses and members. func (b *NodeBuilderImpl) expandClassDecl(symbol *ast.Symbol) *ast.Node { name := ast.SymbolName(symbol) b.ctx.approximateLength += 9 + len(name) classLikeDeclarations := core.Filter(symbol.Declarations, ast.IsClassLike) originalDecl := core.FirstOrNil(classLikeDeclarations) oldEnclosing := b.ctx.enclosingDeclaration if originalDecl != nil { b.ctx.enclosingDeclaration = originalDecl } defer func() { b.ctx.enclosingDeclaration = oldEnclosing }() localParams := b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) typeParamDecls := core.Map(localParams, func(p *Type) *ast.Node { return b.typeParameterToDeclaration(p) }) declaredType := b.ch.getDeclaredTypeOfClassOrInterface(symbol) classType := b.ch.getTypeWithThisArgument(declaredType, nil, false) baseTypes := b.ch.getBaseTypes(b.ch.getTargetType(classType)) staticType := b.ch.getTypeOfSymbol(symbol) isClass := staticType.symbol != nil && staticType.symbol.ValueDeclaration != nil && ast.IsClassLike(staticType.symbol.ValueDeclaration) var staticBaseType *Type if isClass { staticBaseType = b.ch.getBaseConstructorTypeOfClass(declaredType) } else { staticBaseType = b.ch.anyType } // Heritage clauses heritageClauses := b.hoverHeritageClauses(classLikeDeclarations) // Instance members via addPropertyToElementList (reusing existing serialization), // then convert TypeElements to ClassElements and add class-specific modifiers allProps := b.ch.getPropertiesOfType(classType) symbolProps := b.filterInheritedProperties(classType, baseTypes, allProps) publicProps := core.Filter(symbolProps, func(s *ast.Symbol) bool { return !isHashPrivate(s) }) hasPrivate := core.Some(symbolProps, isHashPrivate) var instanceMembers []*ast.Node instanceMembers = b.serializePropertiesWithTruncation(publicProps, instanceMembers) instanceMembers = typeElementsToClassElements(b.f, instanceMembers) instanceMembers = b.addClassModifiers(instanceMembers, false) // Static members staticProps := core.Filter(b.ch.getPropertiesOfType(staticType), func(p *ast.Symbol) bool { return p.Flags&ast.SymbolFlagsPrototype == 0 && p.Name != "prototype" && !b.isNamespaceMember(p) }) var staticMembers []*ast.Node staticMembers = b.serializePropertiesWithTruncation(staticProps, staticMembers) staticMembers = typeElementsToClassElements(b.f, staticMembers) staticMembers = b.addClassModifiers(staticMembers, true) // Hash-private members var privateMembers []*ast.Node if hasPrivate { privateMembers = b.serializePropertiesWithTruncation(core.Filter(symbolProps, isHashPrivate), privateMembers) privateMembers = typeElementsToClassElements(b.f, privateMembers) } // Constructors constructors := b.serializeConstructors(staticType, staticBaseType, isClass, symbol) // Index signatures indexSigs := b.serializeIndexSignaturesOfType(classType, core.FirstOrNil(baseTypes)) allMembers := make([]*ast.Node, 0, len(indexSigs)+len(staticMembers)+len(constructors)+len(instanceMembers)+len(privateMembers)) allMembers = append(allMembers, indexSigs...) allMembers = append(allMembers, staticMembers...) allMembers = append(allMembers, constructors...) allMembers = append(allMembers, instanceMembers...) allMembers = append(allMembers, privateMembers...) return b.f.NewClassDeclaration(nil, b.f.NewIdentifier(name), b.f.NewNodeList(typeParamDecls), b.f.NewNodeList(heritageClauses), b.f.NewNodeList(allMembers)) } // addClassModifiers post-processes class member nodes to add class-specific modifiers // (private, protected, public, abstract, static) based on the original symbol declarations. func (b *NodeBuilderImpl) addClassModifiers(members []*ast.Node, isStatic bool) []*ast.Node { for i, m := range members { // Find the symbol for this member by matching the property name var memberSymbol *ast.Symbol memberName := m.Name() if memberName != nil { if sym, ok := b.idToSymbol[memberName]; ok { memberSymbol = sym } } if memberSymbol == nil { continue } modFlags := getDeclarationModifierFlagsFromSymbol(memberSymbol) &^ ast.ModifierFlagsAsync if isStatic { modFlags |= ast.ModifierFlagsStatic } if modFlags != 0 && ast.CanHaveModifiers(m) { existing := m.ModifierFlags() if modFlags != existing { members[i] = ast.ReplaceModifiers(b.f, m, b.f.NewModifierList(ast.CreateModifiersFromModifierFlags(modFlags|existing, b.f.NewModifier))) } } } return members } // typeElementsToClassElements converts TypeElement nodes (PropertySignature, MethodSignature) // to their ClassElement equivalents (PropertyDeclaration, MethodDeclaration) so they can be // used as members of a ClassDeclaration. Nodes that are already ClassElements pass through unchanged. func typeElementsToClassElements(f *ast.NodeFactory, members []*ast.Node) []*ast.Node { for i, m := range members { switch m.Kind { case ast.KindPropertySignature: ps := m.AsPropertySignatureDeclaration() members[i] = f.NewPropertyDeclaration(m.Modifiers(), ps.Name(), ps.QuestionToken(), ps.Type, nil) case ast.KindMethodSignature: ms := m.AsMethodSignatureDeclaration() members[i] = f.NewMethodDeclaration(m.Modifiers(), nil, ms.Name(), ms.QuestionToken(), ms.TypeParameters, ms.Parameters, ms.Type, nil, nil) } } return members } // expandInterfaceDecl produces an InterfaceDeclaration with members. // Reuses addPropertyToElementList for property serialization and // signatureToSignatureDeclarationHelper for signatures. func (b *NodeBuilderImpl) expandInterfaceDecl(symbol *ast.Symbol) *ast.Node { name := ast.SymbolName(symbol) b.ctx.approximateLength += 14 + len(name) interfaceType := b.ch.getDeclaredTypeOfClassOrInterface(symbol) interfaceDeclarations := core.Filter(symbol.Declarations, ast.IsInterfaceDeclaration) localParams := b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) typeParamDecls := core.Map(localParams, func(p *Type) *ast.Node { return b.typeParameterToDeclaration(p) }) baseTypes := b.ch.getBaseTypes(interfaceType) var baseType *Type if len(baseTypes) > 0 { baseType = b.ch.getIntersectionType(baseTypes) } // Members: reuse existing serialization functions resolved := b.ch.resolveStructuredTypeMembers(interfaceType) var members []*ast.Node // Index signatures, filtering those identical to base members = append(members, b.serializeIndexSignaturesOfType(interfaceType, baseType)...) // Construct signatures (skip abstract) for _, sig := range resolved.ConstructSignatures() { if sig.flags&SignatureFlagsAbstract != 0 { continue } members = append(members, b.signatureToSignatureDeclarationHelper(sig, ast.KindConstructSignature, nil)) } // Call signatures for _, sig := range resolved.CallSignatures() { members = append(members, b.signatureToSignatureDeclarationHelper(sig, ast.KindCallSignature, nil)) } // Properties, filtering inherited filteredProps := b.filterInheritedProperties(interfaceType, baseTypes, resolved.properties) members = b.serializePropertiesWithTruncation(filteredProps, members) // Heritage clauses heritageClauses := b.hoverHeritageClauses(interfaceDeclarations) return b.f.NewInterfaceDeclaration(nil, b.f.NewIdentifier(name), b.f.NewNodeList(typeParamDecls), b.f.NewNodeList(heritageClauses), b.f.NewNodeList(members)) } func (b *NodeBuilderImpl) hoverHeritageClauses(declarations []*ast.Node) []*ast.Node { var extendsTypes []*ast.Node var implementsTypes []*ast.Node for _, declaration := range declarations { for _, heritageElement := range ast.GetExtendsHeritageClauseElements(declaration) { extendsTypes = append(extendsTypes, b.f.DeepCloneNode(heritageElement.AsNode())) } for _, heritageElement := range ast.GetImplementsHeritageClauseElements(declaration) { implementsTypes = append(implementsTypes, b.f.DeepCloneNode(heritageElement.AsNode())) } } var heritageClauses []*ast.Node if len(extendsTypes) > 0 { heritageClauses = append(heritageClauses, b.f.NewHeritageClause(ast.KindExtendsKeyword, b.f.NewNodeList(extendsTypes))) } if len(implementsTypes) > 0 { heritageClauses = append(heritageClauses, b.f.NewHeritageClause(ast.KindImplementsKeyword, b.f.NewNodeList(implementsTypes))) } return heritageClauses } // serializePropertiesWithTruncation iterates properties using addPropertyToElementList, // with truncation checks matching Strada's createTypeNodesFromResolvedType behavior. func (b *NodeBuilderImpl) serializePropertiesWithTruncation(properties []*ast.Symbol, elements []*ast.Node) []*ast.Node { properties = core.Filter(properties, func(p *ast.Symbol) bool { return p.Flags&ast.SymbolFlagsPrototype == 0 }) for i, p := range properties { if b.checkTruncationLengthIfExpanding() && (i+3 < len(properties)-1) { b.ctx.expansionTruncated = true text := fmt.Sprintf("... %d more ...", len(properties)-i-1) elements = append(elements, b.f.NewPropertySignatureDeclaration(nil, b.f.NewIdentifier(text), nil, nil, nil)) elements = b.addPropertyToElementList(properties[len(properties)-1], elements) break } elements = b.addPropertyToElementList(p, elements) } return elements } // serializeConstructors builds constructor signature(s) for a class, with base type filtering. func (b *NodeBuilderImpl) serializeConstructors(staticType *Type, staticBaseType *Type, isClass bool, symbol *ast.Symbol) []*ast.Node { isNonConstructable := !isClass && symbol.ValueDeclaration != nil && ast.IsInJSFile(symbol.ValueDeclaration) && len(b.ch.getSignaturesOfType(staticType, SignatureKindConstruct)) == 0 if isNonConstructable { b.ctx.approximateLength += 21 modifiers := ast.CreateModifiersFromModifierFlags(ast.ModifierFlagsPrivate, b.f.NewModifier) return []*ast.Node{b.f.NewConstructorDeclaration(b.f.NewModifierList(modifiers), nil, b.f.NewNodeList(nil), nil, nil, nil)} } signatures := b.ch.getSignaturesOfType(staticType, SignatureKindConstruct) if staticBaseType != nil { baseSigs := b.ch.getSignaturesOfType(staticBaseType, SignatureKindConstruct) if len(baseSigs) == 0 && core.Every(signatures, func(sig *Signature) bool { return len(sig.parameters) == 0 }) { return nil } if len(baseSigs) == len(signatures) { allMatch := true for i := range baseSigs { if b.ch.compareSignaturesIdentical(signatures[i], baseSigs[i], false, false, true, b.ch.compareTypesIdentical) != TernaryTrue { allMatch = false break } } if allMatch { return nil } } var privateProtected ast.ModifierFlags for _, sig := range signatures { if sig.declaration != nil { privateProtected |= sig.declaration.ModifierFlags() & (ast.ModifierFlagsPrivate | ast.ModifierFlagsProtected) } } if privateProtected != 0 { return []*ast.Node{b.f.NewConstructorDeclaration( b.f.NewModifierList(ast.CreateModifiersFromModifierFlags(privateProtected, b.f.NewModifier)), nil, b.f.NewNodeList(nil), nil, nil, nil, )} } } else if core.Every(signatures, func(sig *Signature) bool { return len(sig.parameters) == 0 }) { return nil } var result []*ast.Node for _, sig := range signatures { b.ctx.approximateLength++ result = append(result, b.signatureToSignatureDeclarationHelper(sig, ast.KindConstructor, nil)) } return result } // serializeIndexSignaturesOfType builds index signature declarations, filtering those identical to baseType. func (b *NodeBuilderImpl) serializeIndexSignaturesOfType(input *Type, baseType *Type) []*ast.Node { var result []*ast.Node for _, info := range b.ch.getIndexInfosOfType(input) { if baseType != nil { baseInfo := b.ch.getIndexInfoOfType(baseType, info.keyType) if baseInfo != nil && b.ch.isTypeIdenticalTo(info.valueType, baseInfo.valueType) { continue } } result = append(result, b.indexInfoToIndexSignatureDeclarationHelper(info, nil)) } return result } // serializeNamespaceMember produces the appropriate declaration node for a namespace member // based on its symbol flags (type alias, enum, class, interface, nested namespace, or variable). func (b *NodeBuilderImpl) serializeNamespaceMember(resolved *ast.Symbol, name string) *ast.Node { switch { case resolved.Flags&ast.SymbolFlagsTypeAlias != 0: return b.serializeTypeAliasForNamespace(resolved, name) case resolved.Flags&ast.SymbolFlagsEnum != 0: return b.expandEnumDecl(resolved) case resolved.Flags&ast.SymbolFlagsClass != 0: return b.expandClassDecl(resolved) case resolved.Flags&ast.SymbolFlagsInterface != 0: return b.expandInterfaceDecl(resolved) case resolved.Flags&(ast.SymbolFlagsValueModule|ast.SymbolFlagsNamespaceModule) != 0: return b.expandModuleDecl(resolved) default: t := b.ch.getWidenedType(b.ch.getTypeOfSymbol(resolved)) b.ctx.approximateLength += len(name) + 5 return b.f.NewVariableStatement( nil, b.f.NewVariableDeclarationList( b.f.NewNodeList([]*ast.Node{ b.f.NewVariableDeclaration(b.f.NewIdentifier(name), nil, b.serializeTypeForDeclaration(nil, t, resolved, true), nil), }), ast.NodeFlagsLet, ), ) } } // expandModuleDecl produces a ModuleDeclaration with exported members. func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { exports := b.ch.getExportsOfSymbol(symbol) var members []*ast.Symbol for _, sym := range exports { // Filter to namespace-relevant members if !b.isNamespaceMember(sym) { continue } if !scanner.IsIdentifierText(sym.Name, core.LanguageVariantStandard) { continue } members = append(members, sym) } b.ch.sortSymbols(members) b.ctx.approximateLength += 14 // Use the same name as symbol display. oldFlags := b.ctx.flags defer func() { b.ctx.flags = oldFlags }() b.ctx.flags |= nodebuilder.FlagsWriteTypeParametersInQualifiedName | nodebuilder.Flags(SymbolFormatFlagsUseOnlyExternalAliasing) localName := b.symbolToNode(symbol, ast.SymbolFlagsAll) b.ctx.flags = oldFlags type hoverStatement struct { node *ast.Node isLocal bool // local declarations (e.g. alias targets) should not get export modifier } var bodyStmts []hoverStatement var emittedLocals collections.Set[*ast.Symbol] for i := 0; i < len(members); i++ { m := members[i] if b.checkTruncationLengthIfExpanding() && i+3 < len(members)-1 { b.ctx.expansionTruncated = true bodyStmts = append(bodyStmts, hoverStatement{node: b.f.NewExpressionStatement(b.f.NewIdentifier(fmt.Sprintf("... (%d more) ...", len(members)-i-1)))}) i = len(members) - 2 // skip to last member after i++ at end of iteration continue } // Handle alias/re-export symbols if m.Flags&ast.SymbolFlagsAlias != 0 { aliasDecl := b.ch.getDeclarationOfAliasSymbol(m) target := b.ch.getMergedSymbol(b.ch.getTargetOfAliasDeclaration(aliasDecl)) if target != nil { // If the alias target is a local symbol (not itself an export), emit its declaration first if target.Flags&(ast.SymbolFlagsBlockScopedVariable|ast.SymbolFlagsFunctionScopedVariable|ast.SymbolFlagsProperty) != 0 { if emittedLocals.AddIfAbsent(target) { localType := b.ch.getWidenedType(b.ch.getTypeOfSymbol(target)) b.ctx.approximateLength += len(target.Name) + 5 localStmt := b.f.NewVariableStatement(nil, b.f.NewVariableDeclarationList(b.f.NewNodeList([]*ast.Node{ b.f.NewVariableDeclaration(b.f.NewIdentifier(target.Name), nil, b.serializeTypeForDeclaration(nil, localType, target, true), nil), }), ast.NodeFlagsLet)) bodyStmts = append(bodyStmts, hoverStatement{node: localStmt, isLocal: true}) } } targetName := target.Name b.ctx.approximateLength += 16 + len(m.Name) var propertyName *ast.Node if m.Name != targetName { propertyName = b.f.NewIdentifier(targetName) } stmt := b.f.NewExportDeclaration( nil, false, b.f.NewNamedExports(b.f.NewNodeList([]*ast.Node{ b.f.NewExportSpecifier(false, propertyName, b.f.NewIdentifier(m.Name)), })), nil, nil, ) bodyStmts = append(bodyStmts, hoverStatement{node: stmt}) continue } } resolved := b.ch.resolveSymbol(m) // Handle functions as function declarations if resolved.Flags&(ast.SymbolFlagsFunction|ast.SymbolFlagsMethod) != 0 { t := b.ch.getTypeOfSymbol(resolved) sigs := b.ch.getSignaturesOfType(t, SignatureKindCall) for _, sig := range sigs { b.ctx.approximateLength++ decl := b.signatureToSignatureDeclarationHelper(sig, ast.KindFunctionDeclaration, &SignatureToSignatureDeclarationOptions{ name: b.f.NewIdentifier(m.Name), }) bodyStmts = append(bodyStmts, hoverStatement{node: decl}) } // If the function also has namespace characteristics, emit an empty namespace. merged := b.ch.getMergedSymbol(resolved) hasModuleExports := merged.Flags&(ast.SymbolFlagsValueModule|ast.SymbolFlagsNamespaceModule) != 0 && merged.Exports != nil && len(merged.Exports) != 0 if !hasModuleExports { bodyStmts = append(bodyStmts, hoverStatement{node: b.f.NewModuleDeclaration(nil, ast.KindNamespaceKeyword, b.f.NewIdentifier(m.Name), b.f.NewModuleBlock(b.f.NewNodeList(nil)))}) } continue } // Handle remaining member kinds (type alias, enum, class, interface, namespace, variable) if node := b.serializeNamespaceMember(resolved, m.Name); node != nil { bodyStmts = append(bodyStmts, hoverStatement{node: node}) } } // Add export modifier to exported statements (skip local declarations and ExportDeclarations). for i := range bodyStmts { s := &bodyStmts[i] if s.isLocal || ast.IsExportDeclaration(s.node) { continue } if ast.CanHaveModifiers(s.node) { mf := s.node.ModifierFlags() | ast.ModifierFlagsExport s.node = ast.ReplaceModifiers(b.f, s.node, b.f.NewModifierList(ast.CreateModifiersFromModifierFlags(mf, b.f.NewModifier))) } } // Collect nodes, stripping export if all statements are exported. bodyStatements := make([]*ast.Node, len(bodyStmts)) for i := range bodyStmts { bodyStatements[i] = bodyStmts[i].node } allExported := len(bodyStatements) > 0 && core.Every(bodyStatements, func(d *ast.Node) bool { return ast.HasSyntacticModifier(d, ast.ModifierFlagsExport) }) if allExported { for i, stmt := range bodyStatements { if ast.CanHaveModifiers(stmt) { mf := stmt.ModifierFlags() &^ ast.ModifierFlagsExport bodyStatements[i] = ast.ReplaceModifiers(b.f, stmt, b.f.NewModifierList(ast.CreateModifiersFromModifierFlags(mf, b.f.NewModifier))) } } } keyword := ast.KindNamespaceKeyword if !ast.IsIdentifier(localName) { keyword = ast.KindModuleKeyword } return b.f.NewModuleDeclaration(nil, keyword, localName, b.f.NewModuleBlock(b.f.NewNodeList(bodyStatements))) } // serializeTypeAliasForNamespace produces a TypeAliasDeclaration for a type alias inside a namespace body. func (b *NodeBuilderImpl) serializeTypeAliasForNamespace(symbol *ast.Symbol, name string) *ast.Node { aliasType := b.ch.getDeclaredTypeOfTypeAlias(symbol) typeParams := b.ch.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) typeParamDecls := core.Map(typeParams, func(p *Type) *ast.Node { return b.typeParameterToDeclaration(p) }) restoreFlags := b.saveRestoreFlags() b.ctx.flags |= nodebuilder.FlagsInTypeAlias typeNode := b.typeToTypeNode(aliasType) restoreFlags() b.ctx.approximateLength += 8 + len(name) return b.f.NewTypeAliasDeclaration(nil, b.f.NewIdentifier(name), b.f.NewNodeList(typeParamDecls), typeNode) } // filterInheritedProperties removes properties already present in base types. func (b *NodeBuilderImpl) filterInheritedProperties(t *Type, baseTypes []*Type, properties []*ast.Symbol) []*ast.Symbol { if len(baseTypes) == 0 { return properties } // Build a lookup from property name to symbol for parent-identity comparison. propsByName := make(map[string]*ast.Symbol, len(properties)) for _, p := range properties { propsByName[p.Name] = p } // Collect names of properties inherited unchanged from base types. var inherited collections.Set[string] for _, base := range baseTypes { baseWithThis := b.ch.getTypeWithThisArgument(base, b.ch.getTargetType(t).AsInterfaceType().thisType, false) for _, prop := range b.ch.getPropertiesOfType(baseWithThis) { if existing, ok := propsByName[prop.Name]; ok && prop.Parent == existing.Parent { inherited.Add(prop.Name) } } } if inherited.Len() == 0 { return properties } return core.Filter(properties, func(p *ast.Symbol) bool { return !inherited.Has(p.Name) }) } func (b *NodeBuilderImpl) isNamespaceMember(p *ast.Symbol) bool { return p.Flags&(ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias) != 0 || !(p.Flags&ast.SymbolFlagsPrototype != 0 || p.Name == "prototype" || (p.ValueDeclaration != nil && ast.HasStaticModifier(p.ValueDeclaration) && ast.IsClassLike(p.ValueDeclaration.Parent))) } func isHashPrivate(s *ast.Symbol) bool { return s.ValueDeclaration != nil && s.ValueDeclaration.Name() != nil && ast.IsPrivateIdentifier(s.ValueDeclaration.Name()) }