Skip to content

Port global completions #858

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions internal/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,57 @@ func (n *Node) ModuleSpecifier() *Expression {
panic("Unhandled case in Node.ModuleSpecifier: " + n.Kind.String())
}

func (n *Node) Statement() *Statement {
switch n.Kind {
case KindDoStatement:
return n.AsDoStatement().Statement
case KindWhileStatement:
return n.AsWhileStatement().Statement
case KindForStatement:
return n.AsForStatement().Statement
case KindForInStatement, KindForOfStatement:
return n.AsForInOrOfStatement().Statement
}
panic("Unhandled case in Node.Statement: " + n.Kind.String())
}

func (n *Node) PropertyList() *NodeList {
switch n.Kind {
case KindObjectLiteralExpression:
return n.AsObjectLiteralExpression().Properties
case KindJsxAttributes:
return n.AsJsxAttributes().Properties
}
panic("Unhandled case in Node.PropertyList: " + n.Kind.String())
}

func (n *Node) Properties() []*Node {
list := n.PropertyList()
if list != nil {
return list.Nodes
}
return nil
}

func (n *Node) ElementList() *NodeList {
switch n.Kind {
case KindNamedImports:
return n.AsNamedImports().Elements
case KindNamedExports:
return n.AsNamedExports().Elements
}

panic("Unhandled case in Node.ElementList: " + n.Kind.String())
}

func (n *Node) Elements() []*Node {
list := n.ElementList()
if list != nil {
return list.Nodes
}
return nil
}

// Determines if `n` contains `descendant` by walking up the `Parent` pointers from `descendant`. This method panics if
// `descendant` or one of its ancestors is not parented except when that node is a `SourceFile`.
func (n *Node) Contains(descendant *Node) bool {
Expand Down Expand Up @@ -1693,6 +1744,11 @@ type (
AnyValidImportOrReExport = Node // (ImportDeclaration | ExportDeclaration | JSDocImportTag) & { moduleSpecifier: StringLiteral } | ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteral }} | RequireOrImportCall | ValidImportTypeNode
ValidImportTypeNode = Node // ImportTypeNode & { argument: LiteralTypeNode & { literal: StringLiteral } }
NumericOrStringLikeLiteral = Node // StringLiteralLike | NumericLiteral
TypeOnlyImportDeclaration = Node // ImportClause | ImportEqualsDeclaration | ImportSpecifier | NamespaceImport with isTypeOnly: true
ObjectLiteralLike = Node // ObjectLiteralExpression | ObjectBindingPattern
ObjectTypeDeclaration = Node // ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode
JsxOpeningLikeElement = Node // JsxOpeningElement | JsxSelfClosingElement
NamedImportsOrExports = Node // NamedImports | NamedExports
)

// Aliases for node singletons
Expand Down Expand Up @@ -1735,6 +1791,10 @@ type (
JsxClosingFragmentNode = Node
SourceFileNode = Node
PropertyAccessExpressionNode = Node
TypeLiteral = Node
ObjectLiteralExpressionNode = Node
ConstructorDeclarationNode = Node
NamedExportsNode = Node
)

type (
Expand Down Expand Up @@ -6939,6 +6999,10 @@ func (node *IntersectionTypeNode) Clone(f NodeFactoryCoercible) *Node {
return cloneNode(f.AsNodeFactory().NewIntersectionTypeNode(node.Types), node.AsNode(), f.AsNodeFactory().hooks)
}

func IsIntersectionTypeNode(node *Node) bool {
return node.Kind == KindIntersectionType
}

// ConditionalTypeNode

type ConditionalTypeNode struct {
Expand Down
138 changes: 135 additions & 3 deletions internal/ast/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -1527,14 +1527,14 @@ func GetExtendsHeritageClauseElement(node *Node) *ExpressionWithTypeArgumentsNod
}

func GetExtendsHeritageClauseElements(node *Node) []*ExpressionWithTypeArgumentsNode {
return getHeritageElements(node, KindExtendsKeyword)
return GetHeritageElements(node, KindExtendsKeyword)
}

func GetImplementsHeritageClauseElements(node *Node) []*ExpressionWithTypeArgumentsNode {
return getHeritageElements(node, KindImplementsKeyword)
return GetHeritageElements(node, KindImplementsKeyword)
}

func getHeritageElements(node *Node, kind Kind) []*Node {
func GetHeritageElements(node *Node, kind Kind) []*Node {
clause := getHeritageClause(node, kind)
if clause != nil {
return clause.AsHeritageClause().Types.Nodes
Expand Down Expand Up @@ -2793,3 +2793,135 @@ func ForEachChildAndJSDoc(node *Node, sourceFile *SourceFile, v Visitor) bool {
}
return node.ForEachChild(v)
}

func IsTypeReferenceType(node *Node) bool {
return node.Kind == KindTypeReference || node.Kind == KindExpressionWithTypeArguments
}

func IsVariableLike(node *Node) bool {
switch node.Kind {
case KindBindingElement, KindEnumMember, KindParameter, KindPropertyAssignment, KindPropertyDeclaration,
KindPropertySignature, KindShorthandPropertyAssignment, KindVariableDeclaration:
return true
}
return false
}

func HasInitializer(node *Node) bool {
switch node.Kind {
case KindVariableDeclaration, KindParameter, KindBindingElement, KindPropertyDeclaration,
KindPropertyAssignment, KindEnumMember, KindForStatement, KindForInStatement, KindForOfStatement,
KindJsxAttribute:
return node.Initializer() != nil
default:
return false
}
}

func GetTypeAnnotationNode(node *Node) *TypeNode {
switch node.Kind {
case KindVariableDeclaration, KindParameter, KindPropertySignature, KindPropertyDeclaration,
KindTypePredicate, KindParenthesizedType, KindTypeOperator, KindMappedType, KindTypeAssertionExpression,
KindAsExpression, KindSatisfiesExpression, KindTypeAliasDeclaration, KindJSTypeAliasDeclaration,
KindNamedTupleMember, KindOptionalType, KindRestType, KindTemplateLiteralTypeSpan, KindJSDocTypeExpression,
KindJSDocPropertyTag, KindJSDocNullableType, KindJSDocNonNullableType, KindJSDocOptionalType:
return node.Type()
default:
funcLike := node.FunctionLikeData()
if funcLike != nil {
return funcLike.Type
}
return nil
}
}

func IsObjectTypeDeclaration(node *Node) bool {
return IsClassLike(node) || IsInterfaceDeclaration(node) || IsTypeLiteralNode(node)
}

func IsClassOrTypeElement(node *Node) bool {
return IsClassElement(node) || IsTypeElement(node)
}

func GetClassExtendsHeritageElement(node *Node) *ExpressionWithTypeArgumentsNode {
heritageElements := GetHeritageElements(node, KindExtendsKeyword)
if len(heritageElements) > 0 {
return heritageElements[0]
}
return nil
}

func GetImplementsTypeNodes(node *Node) []*ExpressionWithTypeArgumentsNode {
return GetHeritageElements(node, KindImplementsKeyword)
}

func IsTypeKeywordToken(node *Node) bool {
return node.Kind == KindTypeKeyword
}

// If node is a single comment JSDoc, we do not visit the comment node list.
func IsJSDocSingleCommentNodeList(parent *Node, nodeList *NodeList) bool {
return IsJSDocSingleCommentNode(parent) && nodeList == parent.AsJSDoc().Comment
}

func IsJSDocSingleCommentNode(node *Node) bool {
return node.Kind == KindJSDoc && node.AsJSDoc().Comment != nil && len(node.AsJSDoc().Comment.Nodes) == 1
}

func IsValidTypeOnlyAliasUseSite(useSite *Node) bool {
return useSite.Flags&NodeFlagsAmbient != 0 ||
IsPartOfTypeQuery(useSite) ||
isIdentifierInNonEmittingHeritageClause(useSite) ||
isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) ||
!(IsExpressionNode(useSite) || isShorthandPropertyNameUseSite(useSite))
}

func isIdentifierInNonEmittingHeritageClause(node *Node) bool {
if !IsIdentifier(node) {
return false
}
parent := node.Parent
for IsPropertyAccessExpression(parent) || IsExpressionWithTypeArguments(parent) {
parent = parent.Parent
}
return IsHeritageClause(parent) && (parent.AsHeritageClause().Token == KindImplementsKeyword || IsInterfaceDeclaration(parent.Parent))
}

func isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(node *Node) bool {
for NodeKindIs(node, KindIdentifier, KindPropertyAccessExpression) {
node = node.Parent
}
if node.Kind != KindComputedPropertyName {
return false
}
if HasSyntacticModifier(node.Parent, ModifierFlagsAbstract) {
return true
}
return NodeKindIs(node.Parent.Parent, KindInterfaceDeclaration, KindTypeLiteral)
}

func isShorthandPropertyNameUseSite(useSite *Node) bool {
return IsIdentifier(useSite) && IsShorthandPropertyAssignment(useSite.Parent) && useSite.Parent.AsShorthandPropertyAssignment().Name() == useSite
}

func GetPropertyNameForPropertyNameNode(name *Node) string {
switch name.Kind {
case KindIdentifier, KindPrivateIdentifier, KindStringLiteral, KindNoSubstitutionTemplateLiteral,
KindNumericLiteral, KindBigIntLiteral, KindJsxNamespacedName:
return name.Text()
case KindComputedPropertyName:
nameExpression := name.AsComputedPropertyName().Expression
if IsStringOrNumericLiteralLike(nameExpression) {
return nameExpression.Text()
}
if IsSignedNumericLiteral(nameExpression) {
text := nameExpression.AsPrefixUnaryExpression().Operand.Text()
if nameExpression.AsPrefixUnaryExpression().Operator == KindMinusToken {
text = "-" + text
}
return text
}
return InternalSymbolNameMissing
}
panic("Unhandled case in getPropertyNameForPropertyNameNode")
}
Loading