Skip to content

Commit 96c0688

Browse files
authored
Deep clone JSDoc (#1412)
1 parent 4fd6eb1 commit 96c0688

File tree

147 files changed

+785
-747
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+785
-747
lines changed

internal/ast/ast.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9067,7 +9067,6 @@ func (node *JSDocLinkCode) Name() *DeclarationName {
90679067

90689068
type JSDocTypeExpression struct {
90699069
TypeNodeBase
9070-
Host *Node
90719070
Type *TypeNode
90729071
}
90739072

@@ -9325,7 +9324,6 @@ type JSDocTemplateTag struct {
93259324
JSDocTagBase
93269325
Constraint *Node
93279326
TypeParameters *TypeParameterList
9328-
Host *Node
93299327
}
93309328

93319329
func (f *NodeFactory) NewJSDocTemplateTag(tagName *IdentifierNode, constraint *Node, typeParameters *TypeParameterList, comment *NodeList) *Node {
@@ -9820,10 +9818,9 @@ func (node *JSDocThisTag) Clone(f NodeFactoryCoercible) *Node {
98209818
// JSDocImportTag
98219819
type JSDocImportTag struct {
98229820
JSDocTagBase
9823-
JSImportDeclaration *ImportDeclaration
9824-
ImportClause *Declaration
9825-
ModuleSpecifier *Expression
9826-
Attributes *Node
9821+
ImportClause *Declaration
9822+
ModuleSpecifier *Expression
9823+
Attributes *Node
98279824
}
98289825

98299826
func (f *NodeFactory) NewJSDocImportTag(tagName *IdentifierNode, importClause *Declaration, moduleSpecifier *Node, attributes *Node, comment *NodeList) *Node {

internal/ast/deepclone.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package ast
33
import "github.com/microsoft/typescript-go/internal/core"
44

55
// Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory
6-
func getDeepCloneVisitor(f *NodeFactory) *NodeVisitor {
6+
func getDeepCloneVisitor(f *NodeFactory, syntheticLocation bool) *NodeVisitor {
77
var visitor *NodeVisitor
88
visitor = NewNodeVisitor(
99
func(node *Node) *Node {
@@ -15,7 +15,9 @@ func getDeepCloneVisitor(f *NodeFactory) *NodeVisitor {
1515
// In strada, `factory.cloneNode` was dynamic and did _not_ clone positions for any "special cases", meanwhile
1616
// Node.Clone in corsa reliably uses `Update` calls for all nodes and so copies locations by default.
1717
// Deep clones are done to copy a node across files, so here, we explicitly make the location range synthetic on all cloned nodes
18-
c.Loc = core.NewTextRange(-1, -1)
18+
if syntheticLocation {
19+
c.Loc = core.NewTextRange(-1, -1)
20+
}
1921
return c
2022
},
2123
f,
@@ -46,5 +48,18 @@ func getDeepCloneVisitor(f *NodeFactory) *NodeVisitor {
4648
}
4749

4850
func (f *NodeFactory) DeepCloneNode(node *Node) *Node {
49-
return getDeepCloneVisitor(f).VisitNode(node)
51+
return getDeepCloneVisitor(f, true /*syntheticLocation*/).VisitNode(node)
52+
}
53+
54+
func (f *NodeFactory) DeepCloneReparse(node *Node) *Node {
55+
if node != nil {
56+
node = getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitNode(node)
57+
SetParentInChildren(node)
58+
node.Flags |= NodeFlagsReparsed
59+
}
60+
return node
61+
}
62+
63+
func (f *NodeFactory) DeepCloneReparseModifiers(modifiers *ModifierList) *ModifierList {
64+
return getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitModifiers(modifiers)
5065
}

internal/ast/utilities.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -867,17 +867,6 @@ func WalkUpParenthesizedTypes(node *TypeNode) *Node {
867867
return node
868868
}
869869

870-
func GetEffectiveTypeParent(parent *Node) *Node {
871-
if parent != nil && IsInJSFile(parent) {
872-
if parent.Kind == KindJSDocTypeExpression && parent.AsJSDocTypeExpression().Host != nil {
873-
parent = parent.AsJSDocTypeExpression().Host
874-
} else if parent.Kind == KindJSDocTemplateTag && parent.AsJSDocTemplateTag().Host != nil {
875-
parent = parent.AsJSDocTemplateTag().Host
876-
}
877-
}
878-
return parent
879-
}
880-
881870
// Walks up the parents of a node to find the containing SourceFile
882871
func GetSourceFileOfNode(node *Node) *SourceFile {
883872
for node != nil {
@@ -1466,6 +1455,8 @@ func getAssignedName(node *Node) *Node {
14661455
}
14671456
}
14681457
}
1458+
case KindCommonJSExport:
1459+
return parent.AsCommonJSExport().Name()
14691460
case KindVariableDeclaration:
14701461
name := parent.AsVariableDeclaration().Name()
14711462
if IsIdentifier(name) {

internal/binder/binder.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,8 +1651,6 @@ func (b *Binder) bindChildren(node *ast.Node) {
16511651
case ast.KindObjectLiteralExpression, ast.KindArrayLiteralExpression, ast.KindPropertyAssignment, ast.KindSpreadElement:
16521652
b.inAssignmentPattern = saveInAssignmentPattern
16531653
b.bindEachChild(node)
1654-
case ast.KindJSExportAssignment, ast.KindCommonJSExport:
1655-
// Reparsed nodes do not double-bind children, which are not reparsed
16561654
default:
16571655
b.bindEachChild(node)
16581656
}

internal/binder/nameresolver.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ loop:
289289
lastSelfReferenceLocation = location
290290
}
291291
lastLocation = location
292-
location = ast.GetEffectiveTypeParent(location.Parent)
292+
location = location.Parent
293293
}
294294
// We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`.
295295
// If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself.
@@ -483,9 +483,6 @@ func isTypeParameterSymbolDeclaredInContainer(symbol *ast.Symbol, container *ast
483483
for _, decl := range symbol.Declarations {
484484
if decl.Kind == ast.KindTypeParameter {
485485
parent := decl.Parent
486-
if parent.Kind == ast.KindJSDocTemplateTag {
487-
parent = parent.AsJSDocTemplateTag().Host
488-
}
489486
if parent == container {
490487
return true
491488
}

internal/checker/checker.go

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,7 +2903,7 @@ func (c *Checker) checkTypePredicate(node *ast.Node) {
29032903
}
29042904

29052905
func (c *Checker) getTypePredicateParent(node *ast.Node) *ast.SignatureDeclaration {
2906-
parent := ast.GetEffectiveTypeParent(node.Parent)
2906+
parent := node.Parent
29072907
switch parent.Kind {
29082908
case ast.KindArrowFunction, ast.KindCallSignature, ast.KindFunctionDeclaration, ast.KindFunctionExpression, ast.KindFunctionType,
29092909
ast.KindMethodDeclaration, ast.KindMethodSignature:
@@ -13971,9 +13971,6 @@ func (c *Checker) getTargetOfImportSpecifier(node *ast.Node, dontResolveAlias bo
1397113971
}
1397213972
}
1397313973
root := node.Parent.Parent.Parent // ImportDeclaration
13974-
if root.Kind == ast.KindJSDocImportTag {
13975-
root = root.AsJSDocImportTag().JSImportDeclaration.AsNode()
13976-
}
1397713974
if ast.IsBindingElement(node) {
1397813975
root = ast.GetRootDeclaration(node)
1397913976
}
@@ -14344,8 +14341,6 @@ func (c *Checker) getModuleSpecifierForImportOrExport(node *ast.Node) *ast.Node
1434414341

1434514342
func getModuleSpecifierFromNode(node *ast.Node) *ast.Node {
1434614343
switch node.Kind {
14347-
case ast.KindJSDocImportTag:
14348-
return node.AsJSDocImportTag().JSImportDeclaration.ModuleSpecifier
1434914344
case ast.KindImportDeclaration, ast.KindJSImportDeclaration:
1435014345
return node.AsImportDeclaration().ModuleSpecifier
1435114346
case ast.KindExportDeclaration:
@@ -14449,12 +14444,6 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri
1444914444
contextSpecifier = location.AsVariableDeclaration().Initializer.AsCallExpression().Arguments.Nodes[0]
1445014445
} else {
1445114446
var ancestor *ast.Node
14452-
if location.Flags&ast.NodeFlagsJSDoc != 0 {
14453-
ancestor = ast.FindAncestor(location, ast.IsJSDocImportTag)
14454-
if ancestor != nil {
14455-
contextSpecifier = ancestor.AsJSDocImportTag().JSImportDeclaration.ModuleSpecifier
14456-
}
14457-
}
1445814447
if ancestor == nil {
1445914448
ancestor = ast.FindAncestor(location, ast.IsImportCall)
1446014449
if ancestor != nil {
@@ -22039,7 +22028,6 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type {
2203922028
}
2204022029

2204122030
func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type {
22042-
node = ast.GetEffectiveTypeParent(node)
2204322031
if isValidESSymbolDeclaration(node) {
2204422032
symbol := c.getSymbolOfNode(node)
2204522033
if symbol != nil {
@@ -22710,9 +22698,9 @@ func (c *Checker) getAliasForTypeNode(node *ast.Node) *TypeAlias {
2271022698
}
2271122699

2271222700
func (c *Checker) getAliasSymbolForTypeNode(node *ast.Node) *ast.Symbol {
22713-
host := ast.GetEffectiveTypeParent(node.Parent)
22701+
host := node.Parent
2271422702
for ast.IsParenthesizedTypeNode(host) || ast.IsTypeOperatorNode(host) && host.AsTypeOperatorNode().Operator == ast.KindReadonlyKeyword {
22715-
host = ast.GetEffectiveTypeParent(host.Parent)
22703+
host = host.Parent
2271622704
}
2271722705
if isTypeAlias(host) {
2271822706
return c.getSymbolOfDeclaration(host)
@@ -22748,7 +22736,7 @@ func (c *Checker) getOuterTypeParametersOfClassOrInterface(symbol *ast.Symbol) [
2274822736
// Return the outer type parameters of a node or undefined if the node has no outer type parameters.
2274922737
func (c *Checker) getOuterTypeParameters(node *ast.Node, includeThisTypes bool) []*Type {
2275022738
for {
22751-
node = ast.GetEffectiveTypeParent(node.Parent)
22739+
node = node.Parent
2275222740
if node == nil {
2275322741
return nil
2275422742
}

internal/checker/grammarchecks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ func (c *Checker) checkGrammarTypeOperatorNode(node *ast.TypeOperatorNode) bool
13941394
if innerType.Kind != ast.KindSymbolKeyword {
13951395
return c.grammarErrorOnNode(innerType, diagnostics.X_0_expected, scanner.TokenToString(ast.KindSymbolKeyword))
13961396
}
1397-
parent := ast.GetEffectiveTypeParent(ast.WalkUpParenthesizedTypes(node.Parent))
1397+
parent := ast.WalkUpParenthesizedTypes(node.Parent)
13981398
switch parent.Kind {
13991399
case ast.KindVariableDeclaration:
14001400
decl := parent.AsVariableDeclaration()

internal/checker/utilities.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,9 +1842,6 @@ func getAnyImportSyntax(node *ast.Node) *ast.Node {
18421842
default:
18431843
return nil
18441844
}
1845-
if importNode.Kind == ast.KindJSDocImportTag {
1846-
return importNode.AsJSDocImportTag().JSImportDeclaration.AsNode()
1847-
}
18481845
return importNode
18491846
}
18501847

internal/ls/hover_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,92 @@ function myFunction() {
5050
},
5151
},
5252
},
53+
{
54+
title: "JSDocParamHoverFunctionDeclaration",
55+
input: `
56+
// @filename: index.js
57+
/**
58+
* @param {string} param - the greatest of days
59+
*/
60+
function /*marker*/myFunction(param) {
61+
return "test" + param;
62+
}
63+
64+
myFunction();`,
65+
expected: map[string]*lsproto.Hover{
66+
"marker": {
67+
Contents: lsproto.MarkupContentOrMarkedStringOrMarkedStrings{
68+
MarkupContent: &lsproto.MarkupContent{
69+
Kind: lsproto.MarkupKindMarkdown,
70+
Value: "```tsx\nfunction myFunction(param: string): string\n```\n\n\n*@param* `param` - the greatest of days\n",
71+
},
72+
},
73+
},
74+
},
75+
},
76+
{
77+
title: "JSDocParamHoverFunctionCall",
78+
input: `
79+
// @filename: index.js
80+
/**
81+
* @param {string} param - the greatest of days
82+
*/
83+
function myFunction(param) {
84+
return "test" + param;
85+
}
86+
87+
/*marker*/myFunction();`,
88+
expected: map[string]*lsproto.Hover{
89+
"marker": {
90+
Contents: lsproto.MarkupContentOrMarkedStringOrMarkedStrings{
91+
MarkupContent: &lsproto.MarkupContent{
92+
Kind: lsproto.MarkupKindMarkdown,
93+
Value: "```tsx\nfunction myFunction(param: string): string\n```\n\n\n*@param* `param` - the greatest of days\n",
94+
},
95+
},
96+
},
97+
},
98+
},
99+
{
100+
title: "JSDocParamHoverParameter",
101+
input: `
102+
// @filename: index.js
103+
/**
104+
* @param {string} param - the greatest of days
105+
*/
106+
function myFunction(/*marker*/param) {
107+
return "test" + param;
108+
}
109+
110+
myFunction();`,
111+
expected: map[string]*lsproto.Hover{
112+
"marker": {
113+
Contents: lsproto.MarkupContentOrMarkedStringOrMarkedStrings{
114+
MarkupContent: &lsproto.MarkupContent{
115+
Kind: lsproto.MarkupKindMarkdown,
116+
Value: "```tsx\n(parameter) param: string\n```\n- the greatest of days\n",
117+
},
118+
},
119+
},
120+
},
121+
},
122+
{
123+
title: "JSDocParamHoverTagIdentifier",
124+
input: `
125+
// @filename: index.js
126+
/**
127+
* @param {string} /*marker*/param - the greatest of days
128+
*/
129+
function myFunction(param) {
130+
return "test" + param;
131+
}
132+
133+
myFunction();`,
134+
expected: map[string]*lsproto.Hover{
135+
// TODO: Should have same result as hovering on the parameter itself.
136+
"marker": nil,
137+
},
138+
},
53139
}
54140

55141
for _, testCase := range testCases {

0 commit comments

Comments
 (0)