Skip to content

findAllReferences inital port #882

New issue

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

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

Already on GitHub? # to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
95 changes: 90 additions & 5 deletions internal/ast/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,25 @@ func IsStatic(node *Node) bool {
return IsClassElement(node) && HasStaticModifier(node) || IsClassStaticBlockDeclaration(node)
}

func CanHaveSymbol(node *Node) bool {
switch node.Kind {
case KindArrowFunction, KindBinaryExpression, KindBindingElement, KindCallExpression, KindCallSignature,
KindClassDeclaration, KindClassExpression, KindClassStaticBlockDeclaration, KindConstructor, KindConstructorType,
KindConstructSignature, KindElementAccessExpression, KindEnumDeclaration, KindEnumMember, KindExportAssignment,
KindExportDeclaration, KindExportSpecifier, KindFunctionDeclaration, KindFunctionExpression, KindFunctionType,
KindGetAccessor, KindImportClause, KindImportEqualsDeclaration, KindImportSpecifier, KindIndexSignature,
KindInterfaceDeclaration, KindJSExportAssignment, KindJSTypeAliasDeclaration, KindCommonJSExport,
KindJsxAttribute, KindJsxAttributes, KindJsxSpreadAttribute, KindMappedType, KindMethodDeclaration,
KindMethodSignature, KindModuleDeclaration, KindNamedTupleMember, KindNamespaceExport, KindNamespaceExportDeclaration,
KindNamespaceImport, KindNewExpression, KindNoSubstitutionTemplateLiteral, KindNumericLiteral, KindObjectLiteralExpression,
KindParameter, KindPropertyAccessExpression, KindPropertyAssignment, KindPropertyDeclaration, KindPropertySignature,
KindSetAccessor, KindShorthandPropertyAssignment, KindSourceFile, KindSpreadAssignment, KindStringLiteral,
KindTypeAliasDeclaration, KindTypeLiteral, KindTypeParameter, KindVariableDeclaration:
return true
}
return false
}

func CanHaveIllegalDecorators(node *Node) bool {
switch node.Kind {
case KindPropertyAssignment, KindShorthandPropertyAssignment,
Expand Down Expand Up @@ -1255,6 +1274,10 @@ func IsExternalModuleImportEqualsDeclaration(node *Node) bool {
return node.Kind == KindImportEqualsDeclaration && node.AsImportEqualsDeclaration().ModuleReference.Kind == KindExternalModuleReference
}

func IsModuleOrEnumDeclaration(node *Node) bool {
return node.Kind == KindModuleDeclaration || node.Kind == KindEnumDeclaration
}

func IsLiteralImportTypeNode(node *Node) bool {
return IsImportTypeNode(node) && IsLiteralTypeNode(node.AsImportTypeNode().Argument) && IsStringLiteral(node.AsImportTypeNode().Argument.AsLiteralTypeNode().Literal)
}
Expand Down Expand Up @@ -1296,6 +1319,27 @@ func IsThisParameter(node *Node) bool {
return IsParameter(node) && node.Name() != nil && IsThisIdentifier(node.Name())
}

func IsBindableStaticAccessExpression(node *Node, excludeThisKeyword bool) bool {
return IsPropertyAccessExpression(node) &&
(!excludeThisKeyword && node.Expression().Kind == KindThisKeyword || IsIdentifier(node.Name()) && IsBindableStaticNameExpression(node.Expression() /*excludeThisKeyword*/, true)) ||
IsBindableStaticElementAccessExpression(node, excludeThisKeyword)
}

func IsBindableStaticElementAccessExpression(node *Node, excludeThisKeyword bool) bool {
return IsLiteralLikeElementAccess(node) &&
((!excludeThisKeyword && node.Expression().Kind == KindThisKeyword) ||
IsEntityNameExpression(node.Expression()) ||
IsBindableStaticAccessExpression(node.Expression() /*excludeThisKeyword*/, true))
}

func IsLiteralLikeElementAccess(node *Node) bool {
return IsElementAccessExpression(node) && IsStringOrNumericLiteralLike(node.AsElementAccessExpression().ArgumentExpression)
}

func IsBindableStaticNameExpression(node *Node, excludeThisKeyword bool) bool {
return IsEntityNameExpression(node) || IsBindableStaticAccessExpression(node, excludeThisKeyword)
}

// Does not handle signed numeric names like `a[+0]` - handling those would require handling prefix unary expressions
// throughout late binding handling as well, which is awkward (but ultimately probably doable if there is demand)
func GetElementOrPropertyAccessName(node *Node) *Node {
Expand All @@ -1314,6 +1358,13 @@ func GetElementOrPropertyAccessName(node *Node) *Node {
panic("Unhandled case in GetElementOrPropertyAccessName")
}

func GetInitializerOfBinaryExpression(expr *BinaryExpression) *Expression {
for IsBinaryExpression(expr.Right) {
expr = expr.Right.AsBinaryExpression()
}
return expr.Right.Expression()
}

func IsExpressionWithTypeArgumentsInClassExtendsClause(node *Node) bool {
return TryGetClassExtendingExpressionWithTypeArguments(node) != nil
}
Expand Down Expand Up @@ -1657,6 +1708,40 @@ func GetThisContainer(node *Node, includeArrowFunctions bool, includeClassComput
}
}

func GetSuperContainer(node *Node, stopOnFunctions bool) *Node {
for {
node = node.Parent
if node == nil {
return nil
}
switch node.Kind {
case KindComputedPropertyName:
node = node.Parent
break
case KindFunctionDeclaration, KindFunctionExpression, KindArrowFunction:
if !stopOnFunctions {
continue
}
// falls through

case KindPropertyDeclaration, KindPropertySignature, KindMethodDeclaration, KindMethodSignature, KindConstructor, KindGetAccessor, KindSetAccessor, KindClassStaticBlockDeclaration:
return node
case KindDecorator:
// Decorators are always applied outside of the body of a class or method.
if node.Parent.Kind == KindParameter && IsClassElement(node.Parent.Parent) {
// If the decorator's parent is a Parameter, we resolve the this container from
// the grandparent class declaration.
node = node.Parent.Parent
} else if IsClassElement(node.Parent) {
// If the decorator's parent is a class element, we resolve the 'this' container
// from the parent class declaration.
node = node.Parent
}
break
}
}
}

func GetImmediatelyInvokedFunctionExpression(fn *Node) *Node {
if IsFunctionExpressionOrArrowFunction(fn) {
prev := fn
Expand Down Expand Up @@ -1765,13 +1850,13 @@ func IsExpressionNode(node *Node) bool {
for node.Parent.Kind == KindQualifiedName {
node = node.Parent
}
return IsTypeQueryNode(node.Parent) || isJSDocLinkLike(node.Parent) || isJSXTagName(node)
return IsTypeQueryNode(node.Parent) || IsJSDocLinkLike(node.Parent) || isJSXTagName(node)
case KindJSDocMemberName:
return IsTypeQueryNode(node.Parent) || isJSDocLinkLike(node.Parent) || isJSXTagName(node)
return IsTypeQueryNode(node.Parent) || IsJSDocLinkLike(node.Parent) || isJSXTagName(node)
case KindPrivateIdentifier:
return IsBinaryExpression(node.Parent) && node.Parent.AsBinaryExpression().Left == node && node.Parent.AsBinaryExpression().OperatorToken.Kind == KindInKeyword
case KindIdentifier:
if IsTypeQueryNode(node.Parent) || isJSDocLinkLike(node.Parent) || isJSXTagName(node) {
if IsTypeQueryNode(node.Parent) || IsJSDocLinkLike(node.Parent) || isJSXTagName(node) {
return true
}
fallthrough
Expand Down Expand Up @@ -1914,7 +1999,7 @@ func isPartOfTypeExpressionWithTypeArguments(node *Node) bool {
return IsHeritageClause(parent) && (!IsClassLike(parent.Parent) || parent.AsHeritageClause().Token == KindImplementsKeyword)
}

func isJSDocLinkLike(node *Node) bool {
func IsJSDocLinkLike(node *Node) bool {
return NodeKindIs(node, KindJSDocLink, KindJSDocLinkCode, KindJSDocLinkPlain)
}

Expand Down Expand Up @@ -1977,7 +2062,7 @@ func IsJSDocCommentContainingNode(node *Node) bool {
node.Kind == KindJSDocText ||
node.Kind == KindJSDocTypeLiteral ||
node.Kind == KindJSDocSignature ||
isJSDocLinkLike(node) ||
IsJSDocLinkLike(node) ||
IsJSDocTag(node)
}

Expand Down
4 changes: 4 additions & 0 deletions internal/astnav/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ func GetTouchingPropertyName(sourceFile *ast.SourceFile, position int) *ast.Node
})
}

func GetTouchingToken(sourceFile *ast.SourceFile, position int) *ast.Node {
return getTokenAtPosition(sourceFile, position, false /*allowPositionInLeadingTrivia*/, nil)
}

func GetTokenAtPosition(sourceFile *ast.SourceFile, position int) *ast.Node {
return getTokenAtPosition(sourceFile, position, true /*allowPositionInLeadingTrivia*/, nil)
}
Expand Down
10 changes: 3 additions & 7 deletions internal/binder/nameresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ loop:
// (it refers to the constant type of the expression instead)
return nil
}
if isModuleOrEnumDeclaration(location) && lastLocation != nil && location.Name() == lastLocation {
if ast.IsModuleOrEnumDeclaration(location) && lastLocation != nil && location.Name() == lastLocation {
// If lastLocation is the name of a namespace or enum, skip the parent since it will have is own locals that could
// conflict.
lastLocation = location
Expand Down Expand Up @@ -99,7 +99,7 @@ loop:
// name of that export default matches.
result = moduleExports[ast.InternalSymbolNameDefault]
if result != nil {
localSymbol := getLocalSymbolForExportDefault(result)
localSymbol := GetLocalSymbolForExportDefault(result)
if localSymbol != nil && result.Flags&meaning != 0 && localSymbol.Name == name {
break loop
}
Expand Down Expand Up @@ -448,11 +448,7 @@ func (r *NameResolver) argumentsSymbol() *ast.Symbol {
return r.ArgumentsSymbol
}

func isModuleOrEnumDeclaration(node *ast.Node) bool {
return node.Kind == ast.KindModuleDeclaration || node.Kind == ast.KindEnumDeclaration
}

func getLocalSymbolForExportDefault(symbol *ast.Symbol) *ast.Symbol {
func GetLocalSymbolForExportDefault(symbol *ast.Symbol) *ast.Symbol {
if !isExportDefaultSymbol(symbol) || len(symbol.Declarations) == 0 {
return nil
}
Expand Down
28 changes: 14 additions & 14 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1822,12 +1822,12 @@ func (c *Checker) isBlockScopedNameDeclaredBeforeUse(declaration *ast.Node, usag
switch {
case declaration.Kind == ast.KindBindingElement:
// still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2])
errorBindingElement := getAncestor(usage, ast.KindBindingElement)
errorBindingElement := GetAncestor(usage, ast.KindBindingElement)
if errorBindingElement != nil {
return ast.FindAncestor(errorBindingElement, ast.IsBindingElement) != ast.FindAncestor(declaration, ast.IsBindingElement) || declaration.Pos() < errorBindingElement.Pos()
}
// or it might be illegal if usage happens before parent variable is declared (eg var [a] = a)
return c.isBlockScopedNameDeclaredBeforeUse(getAncestor(declaration, ast.KindVariableDeclaration), usage)
return c.isBlockScopedNameDeclaredBeforeUse(GetAncestor(declaration, ast.KindVariableDeclaration), usage)
case declaration.Kind == ast.KindVariableDeclaration:
// still might be illegal if usage is in the initializer of the variable declaration (eg var a = a)
return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage, declContainer)
Expand Down Expand Up @@ -4185,7 +4185,7 @@ func (c *Checker) checkBaseTypeAccessibility(t *Type, node *ast.Node) {
signatures := c.getSignaturesOfType(t, SignatureKindConstruct)
if len(signatures) != 0 {
declaration := signatures[0].declaration
if declaration != nil && hasModifier(declaration, ast.ModifierFlagsPrivate) {
if declaration != nil && HasModifier(declaration, ast.ModifierFlagsPrivate) {
typeClassDeclaration := ast.GetClassLikeDeclarationOfSymbol(t.symbol)
if !c.isNodeWithinClass(node, typeClassDeclaration) {
c.error(node, diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, c.getFullyQualifiedName(t.symbol, nil))
Expand Down Expand Up @@ -5625,7 +5625,7 @@ func (c *Checker) checkVarDeclaredNamesNotShadowed(node *ast.Node) {
localDeclarationSymbol := c.resolveName(node, name.Text(), ast.SymbolFlagsVariable, nil /*nameNotFoundMessage*/, false /*isUse*/, false)
if localDeclarationSymbol != nil && localDeclarationSymbol != symbol && localDeclarationSymbol.Flags&ast.SymbolFlagsBlockScopedVariable != 0 {
if c.getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol)&ast.NodeFlagsBlockScoped != 0 {
varDeclList := getAncestor(localDeclarationSymbol.ValueDeclaration, ast.KindVariableDeclarationList)
varDeclList := GetAncestor(localDeclarationSymbol.ValueDeclaration, ast.KindVariableDeclarationList)
var container *ast.Node
if ast.IsVariableStatement(varDeclList.Parent) && varDeclList.Parent.Parent != nil {
container = varDeclList.Parent.Parent
Expand Down Expand Up @@ -6360,7 +6360,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) {
name := node.PropertyNameOrName().Text()
c.addTypeOnlyDeclarationRelatedInfo(c.error(node, message, name), core.IfElse(isType, nil, typeOnlyAlias), name)
}
if isType && node.Kind == ast.KindImportEqualsDeclaration && hasModifier(node, ast.ModifierFlagsExport) {
if isType && node.Kind == ast.KindImportEqualsDeclaration && HasModifier(node, ast.ModifierFlagsExport) {
c.error(node, diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_0_is_enabled, c.getIsolatedModulesLikeFlagName())
}
case ast.KindExportSpecifier:
Expand Down Expand Up @@ -6646,7 +6646,7 @@ func (c *Checker) checkUnusedClassMembers(node *ast.Node) {
break // Already would have reported an error on the getter.
}
symbol := c.getSymbolOfDeclaration(member)
if !c.isReferenced(symbol) && (hasModifier(member, ast.ModifierFlagsPrivate) || member.Name() != nil && ast.IsPrivateIdentifier(member.Name())) && member.Flags&ast.NodeFlagsAmbient == 0 {
if !c.isReferenced(symbol) && (HasModifier(member, ast.ModifierFlagsPrivate) || member.Name() != nil && ast.IsPrivateIdentifier(member.Name())) && member.Flags&ast.NodeFlagsAmbient == 0 {
c.reportUnused(member, UnusedKindLocal, NewDiagnosticForNode(member.Name(), diagnostics.X_0_is_declared_but_its_value_is_never_read, c.symbolToString(symbol)))
}
case ast.KindConstructor:
Expand Down Expand Up @@ -8201,7 +8201,7 @@ func (c *Checker) resolveNewExpression(node *ast.Node, candidatesOutArray *[]*Si
}
if expressionType.symbol != nil {
valueDecl := ast.GetClassLikeDeclarationOfSymbol(expressionType.symbol)
if valueDecl != nil && hasModifier(valueDecl, ast.ModifierFlagsAbstract) {
if valueDecl != nil && HasModifier(valueDecl, ast.ModifierFlagsAbstract) {
c.error(node, diagnostics.Cannot_create_an_instance_of_an_abstract_class)
return c.resolveErrorCall(node)
}
Expand Down Expand Up @@ -13692,7 +13692,7 @@ func (c *Checker) getSymbolOfPartOfRightHandSideOfImportEquals(entityName *ast.N
// import a = |b|; // Namespace
// import a = |b.c|; // Value, type, namespace
// import a = |b.c|.d; // Namespace
if entityName.Kind == ast.KindIdentifier && isRightSideOfQualifiedNameOrPropertyAccess(entityName) {
if entityName.Kind == ast.KindIdentifier && IsRightSideOfQualifiedNameOrPropertyAccess(entityName) {
entityName = entityName.Parent // QualifiedName
}
// Check for case 1 and 3 in the above example
Expand Down Expand Up @@ -15201,7 +15201,7 @@ func (c *Checker) GetTypeOfSymbolAtLocation(symbol *ast.Symbol, location *ast.No
// of the expression (which will reflect control flow analysis). If the expression indeed
// resolved to the given symbol, return the narrowed type.
if ast.IsIdentifier(location) || ast.IsPrivateIdentifier(location) {
if isRightSideOfQualifiedNameOrPropertyAccess(location) {
if IsRightSideOfQualifiedNameOrPropertyAccess(location) {
location = location.Parent
}
if ast.IsExpressionNode(location) && (!ast.IsAssignmentTarget(location) || isWriteAccess(location)) {
Expand Down Expand Up @@ -18237,7 +18237,7 @@ func (c *Checker) getIndexInfosOfIndexSymbol(indexSymbol *ast.Symbol, siblingSym
}
forEachType(c.getTypeFromTypeNode(typeNode), func(keyType *Type) {
if c.isValidIndexKeyType(keyType) && findIndexInfo(indexInfos, keyType) == nil {
indexInfo := c.newIndexInfo(keyType, valueType, hasModifier(declaration, ast.ModifierFlagsReadonly), declaration)
indexInfo := c.newIndexInfo(keyType, valueType, HasModifier(declaration, ast.ModifierFlagsReadonly), declaration)
indexInfos = append(indexInfos, indexInfo)
}
})
Expand Down Expand Up @@ -26000,7 +26000,7 @@ func (c *Checker) markPropertyAsReferenced(prop *ast.Symbol, nodeForCheckWriteOn
if prop.Flags&ast.SymbolFlagsClassMember == 0 || prop.ValueDeclaration == nil {
return
}
hasPrivateModifier := hasModifier(prop.ValueDeclaration, ast.ModifierFlagsPrivate)
hasPrivateModifier := HasModifier(prop.ValueDeclaration, ast.ModifierFlagsPrivate)
hasPrivateIdentifier := prop.ValueDeclaration.Name() != nil && ast.IsPrivateIdentifier(prop.ValueDeclaration.Name())
if !hasPrivateModifier && !hasPrivateIdentifier {
return
Expand Down Expand Up @@ -29666,7 +29666,7 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast
}
} else if ast.IsEntityName(name) && isInRightSideOfImportOrExportAssignment(name) {
// Since we already checked for ExportAssignment, this really could only be an Import
importEqualsDeclaration := getAncestor(name, ast.KindImportEqualsDeclaration)
importEqualsDeclaration := GetAncestor(name, ast.KindImportEqualsDeclaration)
if importEqualsDeclaration == nil {
panic("ImportEqualsDeclaration should be defined")
}
Expand All @@ -29682,7 +29682,7 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast
}
}

for isRightSideOfQualifiedNameOrPropertyAccess(name) {
for IsRightSideOfQualifiedNameOrPropertyAccess(name) {
name = name.Parent
}

Expand Down Expand Up @@ -29975,7 +29975,7 @@ func (c *Checker) getApplicableIndexSymbol(t *Type, keyType *Type) *ast.Symbol {
}

func (c *Checker) getRegularTypeOfExpression(expr *ast.Node) *Type {
if isRightSideOfQualifiedNameOrPropertyAccess(expr) {
if IsRightSideOfQualifiedNameOrPropertyAccess(expr) {
expr = expr.Parent
}
return c.getRegularTypeOfLiteralType(c.getTypeOfExpression(expr))
Expand Down
12 changes: 12 additions & 0 deletions internal/checker/exports.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"github.com/microsoft/typescript-go/internal/diagnostics"
)

func (c *Checker) GetStringType() *Type {
return c.stringType
}

func (c *Checker) GetUnknownSymbol() *ast.Symbol {
return c.unknownSymbol
}
Expand All @@ -18,6 +22,10 @@ func (c *Checker) GetGlobalSymbol(name string, meaning ast.SymbolFlags, diagnost
return c.getGlobalSymbol(name, meaning, diagnostic)
}

func (c *Checker) GetMergedSymbol(symbol *ast.Symbol) *ast.Symbol {
return c.getMergedSymbol(symbol)
}

func (c *Checker) GetTypeFromTypeNode(node *ast.Node) *Type {
return c.getTypeFromTypeNode(node)
}
Expand All @@ -30,6 +38,10 @@ func (c *Checker) GetPropertiesOfType(t *Type) []*ast.Symbol {
return c.getPropertiesOfType(t)
}

func (c *Checker) GetPropertyOfType(t *Type, name string) *ast.Symbol {
return c.getPropertyOfType(t, name)
}

func (c *Checker) TypeHasCallOrConstructSignatures(t *Type) bool {
return c.typeHasCallOrConstructSignatures(t)
}
Expand Down
Loading