Skip to content

Commit 84681cd

Browse files
authored
Add getSymbolAtLocation (#158)
1 parent 3e1b064 commit 84681cd

File tree

9 files changed

+957
-98
lines changed

9 files changed

+957
-98
lines changed

internal/ast/ast.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,31 @@ func (n *Node) Initializer() *Node {
373373
panic("Unhandled case in Node.Initializer")
374374
}
375375

376+
func (n *Node) TagName() *Node {
377+
switch n.Kind {
378+
case KindJsxOpeningElement:
379+
return n.AsJsxOpeningElement().TagName
380+
case KindJsxClosingElement:
381+
return n.AsJsxClosingElement().TagName
382+
case KindJsxSelfClosingElement:
383+
return n.AsJsxSelfClosingElement().TagName
384+
// !!! JSDoc tags
385+
}
386+
panic("Unhandled case in Node.TagName: " + n.Kind.String())
387+
}
388+
389+
func (n *Node) PropertyName() *Node {
390+
switch n.Kind {
391+
case KindImportSpecifier:
392+
return n.AsImportSpecifier().PropertyName
393+
case KindExportSpecifier:
394+
return n.AsExportSpecifier().PropertyName
395+
case KindBindingElement:
396+
return n.AsBindingElement().PropertyName
397+
}
398+
panic("Unhandled case in Node.PropertyName: " + n.Kind.String())
399+
}
400+
376401
// Node casts
377402

378403
func (n *Node) AsIdentifier() *Identifier {
@@ -1033,6 +1058,7 @@ type ImportAttributeName = Node // Identifier | StringLiteral
10331058
type LeftHandSideExpression = Node // subset of Expression
10341059
type JSDocComment = Node // JSDocText | JSDocLink | JSDocLinkCode | JSDocLinkPlain;
10351060
type JSDocTag = Node // Node with JSDocTagBase
1061+
type SignatureDeclaration = Node // CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction;
10361062

10371063
// Aliases for node singletons
10381064

@@ -4134,6 +4160,10 @@ func (node *ImportAttributes) ForEachChild(v Visitor) bool {
41344160
return visitNodeList(v, node.Attributes)
41354161
}
41364162

4163+
func IsImportAttributes(node *Node) bool {
4164+
return node.Kind == KindImportAttributes
4165+
}
4166+
41374167
// TypeQueryNode
41384168

41394169
type TypeQueryNode struct {
@@ -5386,7 +5416,6 @@ type JSDocNameReference struct {
53865416
name *EntityName
53875417
}
53885418

5389-
// JSDocMemberName
53905419
func NewJSDocNameReference(name *EntityName) *JSDocNameReference {
53915420
data := &JSDocNameReference{}
53925421
data.name = name

internal/ast/utilities.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,3 +842,158 @@ func IsImportMeta(node *Node) bool {
842842
}
843843
return false
844844
}
845+
846+
func IsInJSFile(node *Node) bool {
847+
return node != nil && node.Flags&NodeFlagsJavaScriptFile != 0
848+
}
849+
850+
func IsDeclaration(node *Node) bool {
851+
if node.Kind == KindTypeParameter {
852+
return node.Parent != nil
853+
}
854+
return IsDeclarationNode(node)
855+
}
856+
857+
// True if `name` is the name of a declaration node
858+
func IsDeclarationName(name *Node) bool {
859+
return !IsSourceFile(name) && !IsBindingPattern(name) && IsDeclaration(name.Parent)
860+
}
861+
862+
// Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`.
863+
func IsDeclarationNameOrImportPropertyName(name *Node) bool {
864+
switch name.Parent.Kind {
865+
case KindImportSpecifier, KindExportSpecifier:
866+
return IsIdentifier(name) || name.Kind == KindStringLiteral
867+
default:
868+
return IsDeclarationName(name)
869+
}
870+
}
871+
872+
func IsLiteralComputedPropertyDeclarationName(node *Node) bool {
873+
return IsStringOrNumericLiteralLike(node) &&
874+
node.Parent.Kind == KindComputedPropertyName &&
875+
IsDeclaration(node.Parent.Parent)
876+
}
877+
878+
func IsExternalModuleImportEqualsDeclaration(node *Node) bool {
879+
return node.Kind == KindImportEqualsDeclaration && node.AsImportEqualsDeclaration().ModuleReference.Kind == KindExternalModuleReference
880+
}
881+
882+
func IsLiteralImportTypeNode(node *Node) bool {
883+
return IsImportTypeNode(node) && IsLiteralTypeNode(node.AsImportTypeNode().Argument) && IsStringLiteral(node.AsImportTypeNode().Argument.AsLiteralTypeNode().Literal)
884+
}
885+
886+
func IsEntityNameExpression(node *Node) bool {
887+
return node.Kind == KindIdentifier || isPropertyAccessEntityNameExpression(node)
888+
}
889+
890+
func isPropertyAccessEntityNameExpression(node *Node) bool {
891+
if node.Kind == KindPropertyAccessExpression {
892+
expr := node.AsPropertyAccessExpression()
893+
return expr.Name().Kind == KindIdentifier && IsEntityNameExpression(expr.Expression)
894+
}
895+
return false
896+
}
897+
898+
func IsJsxTagName(node *Node) bool {
899+
parent := node.Parent
900+
switch parent.Kind {
901+
case KindJsxOpeningElement, KindJsxClosingElement, KindJsxSelfClosingElement:
902+
return parent.TagName() == node
903+
}
904+
return false
905+
}
906+
907+
func IsImportOrExportSpecifier(node *Node) bool {
908+
return IsImportSpecifier(node) || IsExportSpecifier(node)
909+
}
910+
911+
func IsDynamicName(name *Node) bool {
912+
var expr *Node
913+
switch name.Kind {
914+
case KindComputedPropertyName:
915+
expr = name.AsComputedPropertyName().Expression
916+
case KindElementAccessExpression:
917+
expr = SkipParentheses(name.AsElementAccessExpression().ArgumentExpression)
918+
default:
919+
return false
920+
}
921+
return !IsStringOrNumericLiteralLike(expr) && !IsSignedNumericLiteral(expr)
922+
}
923+
924+
func IsSignedNumericLiteral(node *Node) bool {
925+
if node.Kind == KindPrefixUnaryExpression {
926+
node := node.AsPrefixUnaryExpression()
927+
return (node.Operator == KindPlusToken || node.Operator == KindMinusToken) && IsNumericLiteral(node.Operand)
928+
}
929+
return false
930+
}
931+
932+
func IsAssignmentExpression(node *Node, excludeCompoundAssignment bool) bool {
933+
if node.Kind == KindBinaryExpression {
934+
expr := node.AsBinaryExpression()
935+
return (expr.OperatorToken.Kind == KindEqualsToken || !excludeCompoundAssignment && IsAssignmentOperator(expr.OperatorToken.Kind)) &&
936+
IsLeftHandSideExpression(expr.Left)
937+
}
938+
return false
939+
}
940+
941+
func GetRightMostAssignedExpression(node *Node) *Node {
942+
for IsAssignmentExpression(node, true /*excludeCompoundAssignment*/) {
943+
node = node.AsBinaryExpression().Right
944+
}
945+
return node
946+
}
947+
948+
func isVoidZero(node *Node) bool {
949+
return IsVoidExpression(node) && IsNumericLiteral(node.Expression()) && node.Expression().Text() == "0"
950+
}
951+
952+
func IsVoidExpression(node *Node) bool {
953+
return node.Kind == KindVoidExpression
954+
}
955+
956+
func IsExportsIdentifier(node *Node) bool {
957+
return IsIdentifier(node) && node.Text() == "exports"
958+
}
959+
960+
func IsModuleIdentifier(node *Node) bool {
961+
return IsIdentifier(node) && node.Text() == "module"
962+
}
963+
964+
// Does not handle signed numeric names like `a[+0]` - handling those would require handling prefix unary expressions
965+
// throughout late binding handling as well, which is awkward (but ultimately probably doable if there is demand)
966+
func GetElementOrPropertyAccessArgumentExpressionOrName(node *Node) *Node {
967+
switch node.Kind {
968+
case KindPropertyAccessExpression:
969+
return node.Name()
970+
case KindElementAccessExpression:
971+
arg := SkipParentheses(node.AsElementAccessExpression().ArgumentExpression)
972+
if IsStringOrNumericLiteralLike(arg) {
973+
return arg
974+
}
975+
return node
976+
}
977+
panic("Unhandled case in GetElementOrPropertyAccessArgumentExpressionOrName")
978+
}
979+
980+
func IsExpressionWithTypeArgumentsInClassExtendsClause(node *Node) bool {
981+
return TryGetClassExtendingExpressionWithTypeArguments(node) != nil
982+
}
983+
984+
func TryGetClassExtendingExpressionWithTypeArguments(node *Node) *ClassLikeDeclaration {
985+
cls, isImplements := TryGetClassImplementingOrExtendingExpressionWithTypeArguments(node)
986+
if cls != nil && !isImplements {
987+
return cls
988+
}
989+
return nil
990+
}
991+
992+
func TryGetClassImplementingOrExtendingExpressionWithTypeArguments(node *Node) (class *ClassLikeDeclaration, isImplements bool) {
993+
if IsExpressionWithTypeArguments(node) {
994+
if IsHeritageClause(node.Parent) && IsClassLike(node.Parent.Parent) {
995+
return node.Parent.Parent, node.Parent.AsHeritageClause().Token == KindImplementsKeyword
996+
}
997+
}
998+
return nil, false
999+
}

internal/compiler/binder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ func (b *Binder) getDeclarationName(node *ast.Node) string {
301301
if ast.IsStringOrNumericLiteralLike(nameExpression) {
302302
return nameExpression.Text()
303303
}
304-
if isSignedNumericLiteral(nameExpression) {
304+
if ast.IsSignedNumericLiteral(nameExpression) {
305305
unaryExpression := nameExpression.AsPrefixUnaryExpression()
306306
return scanner.TokenToString(unaryExpression.Operator) + unaryExpression.Operand.Text()
307307
}
@@ -2673,7 +2673,7 @@ func isNarrowableReference(node *ast.Node) bool {
26732673
case ast.KindElementAccessExpression:
26742674
expr := node.AsElementAccessExpression()
26752675
return ast.IsStringOrNumericLiteralLike(expr.ArgumentExpression) ||
2676-
isEntityNameExpression(expr.ArgumentExpression) && isNarrowableReference(expr.Expression)
2676+
ast.IsEntityNameExpression(expr.ArgumentExpression) && isNarrowableReference(expr.Expression)
26772677
case ast.KindBinaryExpression:
26782678
expr := node.AsBinaryExpression()
26792679
return expr.OperatorToken.Kind == ast.KindCommaToken && isNarrowableReference(expr.Right) ||

0 commit comments

Comments
 (0)