@@ -72,9 +72,9 @@ func (l *LanguageService) getDocumentSymbolInformations(ctx context.Context, fil
7272func (l * LanguageService ) getDocumentSymbolsForChildren (ctx context.Context , node * ast.Node , file * ast.SourceFile ) []* lsproto.DocumentSymbol {
7373 var symbols []* lsproto.DocumentSymbol
7474 expandoTargets := collections.Set [string ]{}
75- addSymbolForNode := func (node * ast.Node , children []* lsproto.DocumentSymbol ) {
75+ addSymbolForNode := func (node * ast.Node , name * ast. Node , children []* lsproto.DocumentSymbol ) {
7676 if node .Flags & ast .NodeFlagsReparsed == 0 || node .Kind == ast .KindJSExportAssignment {
77- symbol := l .newDocumentSymbol (node , children )
77+ symbol := l .newDocumentSymbol (node , name , children )
7878 if symbol != nil {
7979 symbols = append (symbols , symbol )
8080 }
@@ -95,7 +95,7 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
9595 }
9696 return result
9797 }
98- startNode := func (node * ast.Node ) func () {
98+ startNode := func (node * ast.Node , name * ast. Node ) func () {
9999 if node == nil {
100100 return func () {}
101101 }
@@ -107,7 +107,7 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
107107 result := symbols
108108 symbols = saveSymbols
109109 expandoTargets = saveExpandoTargets
110- addSymbolForNode (node , result )
110+ addSymbolForNode (node , name , result )
111111 }
112112 }
113113 getSymbolsForNode := func (node * ast.Node ) []* lsproto.DocumentSymbol {
@@ -131,7 +131,7 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
131131 if tagList := jsdoc .AsJSDoc ().Tags ; tagList != nil {
132132 for _ , tag := range tagList .Nodes {
133133 if ast .IsJSDocTypedefTag (tag ) || ast .IsJSDocCallbackTag (tag ) {
134- addSymbolForNode (tag , nil /*children*/ )
134+ addSymbolForNode (tag , nil /*name*/ , nil /* children*/ )
135135 }
136136 }
137137 }
@@ -143,69 +143,89 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
143143 if ast .IsClassLike (node ) && ast .GetDeclarationName (node ) != "" {
144144 expandoTargets .Add (ast .GetDeclarationName (node ))
145145 }
146- addSymbolForNode (node , getSymbolsForChildren (node ))
146+ addSymbolForNode (node , nil /*name*/ , getSymbolsForChildren (node ))
147147 case ast .KindModuleDeclaration :
148- addSymbolForNode (node , getSymbolsForChildren (getInteriorModule (node )))
148+ addSymbolForNode (node , nil /*name*/ , getSymbolsForChildren (getInteriorModule (node )))
149149 case ast .KindConstructor :
150- addSymbolForNode (node , getSymbolsForChildren (node .Body ()))
150+ addSymbolForNode (node , nil /*name*/ , getSymbolsForChildren (node .Body ()))
151151 for _ , param := range node .Parameters () {
152152 if ast .IsParameterPropertyDeclaration (param , node ) {
153- addSymbolForNode (param , nil /*children*/ )
153+ addSymbolForNode (param , nil /*name*/ , nil /* children*/ )
154154 }
155155 }
156156 case ast .KindFunctionDeclaration , ast .KindFunctionExpression , ast .KindArrowFunction , ast .KindMethodDeclaration , ast .KindGetAccessor ,
157157 ast .KindSetAccessor :
158- name := ast .GetDeclarationName (node )
159- if name != "" {
160- expandoTargets .Add (name )
158+ declName := ast .GetDeclarationName (node )
159+ if declName != "" {
160+ expandoTargets .Add (declName )
161161 }
162- addSymbolForNode (node , getSymbolsForChildren (node .Body ()))
162+ addSymbolForNode (node , nil /*name*/ , getSymbolsForChildren (node .Body ()))
163163 case ast .KindVariableDeclaration , ast .KindBindingElement , ast .KindPropertyAssignment , ast .KindPropertyDeclaration :
164- name := node .Name ()
165- if name != nil {
166- if ast .IsBindingPattern (name ) {
167- visit (name )
164+ nodeName := node .Name ()
165+ if nodeName != nil {
166+ if ast .IsBindingPattern (nodeName ) {
167+ visit (nodeName )
168168 } else {
169- addSymbolForNode (node , getSymbolsForChildren (node .Initializer ()))
169+ addSymbolForNode (node , nil /*name*/ , getSymbolsForChildren (node .Initializer ()))
170170 }
171171 }
172172 case ast .KindSpreadAssignment :
173- addSymbolForNode (node , nil /*children*/ )
173+ addSymbolForNode (node , node . Expression (), nil /*children*/ )
174174 case ast .KindMethodSignature , ast .KindPropertySignature , ast .KindCallSignature , ast .KindConstructSignature , ast .KindIndexSignature ,
175175 ast .KindEnumMember , ast .KindShorthandPropertyAssignment , ast .KindTypeAliasDeclaration , ast .KindImportEqualsDeclaration , ast .KindExportSpecifier :
176- addSymbolForNode (node , nil )
176+ addSymbolForNode (node , nil /*name*/ , nil /*children*/ )
177177 case ast .KindImportClause :
178178 // Handle default import case e.g.:
179179 // import d from "mod";
180180 if node .Name () != nil {
181- addSymbolForNode (node .Name (), nil /*children*/ )
181+ addSymbolForNode (node .Name (), node . Name (), nil /*children*/ )
182182 }
183183 // Handle named bindings in imports e.g.:
184184 // import * as NS from "mod";
185185 // import {a, b as B} from "mod";
186186 if namedBindings := node .AsImportClause ().NamedBindings ; namedBindings != nil {
187187 if namedBindings .Kind == ast .KindNamespaceImport {
188- addSymbolForNode (namedBindings , nil /*children*/ )
188+ addSymbolForNode (namedBindings , nil /*name*/ , nil /* children*/ )
189189 } else {
190190 for _ , element := range namedBindings .Elements () {
191- addSymbolForNode (element , nil /*children*/ )
191+ addSymbolForNode (element , nil /*name*/ , nil /* children*/ )
192192 }
193193 }
194194 }
195- case ast .KindBinaryExpression :
196- binaryExpr := node .AsBinaryExpression ()
195+ case ast .KindBinaryExpression , ast .KindCallExpression :
197196 assignmentKind := ast .GetAssignmentDeclarationKind (node )
198197 switch assignmentKind {
199198 // `module.exports = ...`` should be reparsed into a JSExportAssignment,
200199 // and `exports.a = ...`` into a CommonJSExport.
201200 case ast .JSDeclarationKindNone , ast .JSDeclarationKindThisProperty ,
202- ast .JSDeclarationKindModuleExports , ast .JSDeclarationKindExportsProperty :
201+ ast .JSDeclarationKindModuleExports , ast .JSDeclarationKindExportsProperty ,
202+ ast .JSDeclarationKindObjectDefinePropertyExports :
203203 node .ForEachChild (visit )
204- case ast .JSDeclarationKindProperty :
204+ case ast .JSDeclarationKindProperty , ast .JSDeclarationKindObjectDefinePropertyValue :
205+ var target * ast.Expression
206+ var targetFunction * ast.Expression
207+ var definition * ast.Node
208+ var propertyName * ast.Node
205209 // `A.b = ... ` or `A.prototype.b = ...`
206- target := binaryExpr .Left
207- targetFunction := target .Expression ()
208- if isPrototypeExpando (binaryExpr ) {
210+ if ast .IsBinaryExpression (node ) {
211+ binaryExpr := node .AsBinaryExpression ()
212+ target = binaryExpr .Left
213+ targetFunction = target .Expression ()
214+ definition = binaryExpr .Right
215+ // `A.b` or `A.prototype.b`
216+ if ast .IsPropertyAccessExpression (target ) {
217+ propertyName = target .AsPropertyAccessExpression ().Name ()
218+ } else { // `A["b"]` or `A.prototype["b"]`
219+ propertyName = target .AsElementAccessExpression ().ArgumentExpression
220+ }
221+ } else { // `Object.defineProperty(A, "b", {...})`
222+ args := node .Arguments ()
223+ targetFunction = args [0 ]
224+ target = args [1 ]
225+ propertyName = target
226+ definition = args [2 ]
227+ }
228+ if isPrototypeExpando (targetFunction ) {
209229 targetFunction = targetFunction .Expression ()
210230 // If we see a prototype assignment, start tracking the target as an expando target.
211231 if ast .IsIdentifier (targetFunction ) {
@@ -214,16 +234,16 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
214234 }
215235 if ast .IsIdentifier (targetFunction ) &&
216236 expandoTargets .Has (targetFunction .Text ()) {
217- endNode := startNode (node )
218- addSymbolForNode (target , getSymbolsForNode (binaryExpr . Right ))
237+ endNode := startNode (node , targetFunction )
238+ addSymbolForNode (target , propertyName , getSymbolsForNode (definition ))
219239 endNode ()
220240 } else {
221241 node .ForEachChild (visit )
222242 }
223243 }
224244 case ast .KindExportAssignment , ast .KindJSExportAssignment :
225245 if node .AsExportAssignment ().IsExportEquals {
226- addSymbolForNode (node , getSymbolsForNode (node .Expression ()))
246+ addSymbolForNode (node , nil /*name*/ , getSymbolsForNode (node .Expression ()))
227247 } else {
228248 node .ForEachChild (visit )
229249 }
@@ -236,9 +256,8 @@ func (l *LanguageService) getDocumentSymbolsForChildren(ctx context.Context, nod
236256 return mergeExpandos (symbols )
237257}
238258
239- // Binary expression is `f.prototype.prop`.
240- func isPrototypeExpando (binaryExpr * ast.BinaryExpression ) bool {
241- target := binaryExpr .Left .Expression ()
259+ // Target is `f.prototype`.
260+ func isPrototypeExpando (target * ast.Node ) bool {
242261 if ast .IsAccessExpression (target ) {
243262 accessName := ast .GetElementOrPropertyAccessName (target )
244263 return accessName != nil && accessName .Text () == "prototype"
@@ -248,29 +267,11 @@ func isPrototypeExpando(binaryExpr *ast.BinaryExpression) bool {
248267
249268const maxLength = 150
250269
251- func (l * LanguageService ) newDocumentSymbol (node * ast.Node , children []* lsproto.DocumentSymbol ) * lsproto.DocumentSymbol {
270+ func (l * LanguageService ) newDocumentSymbol (node * ast.Node , name * ast. Node , children []* lsproto.DocumentSymbol ) * lsproto.DocumentSymbol {
252271 result := new (lsproto.DocumentSymbol )
253272 file := ast .GetSourceFileOfNode (node )
254273 nodeStartPos := scanner .SkipTrivia (file .Text (), node .Pos ())
255- var name * ast.Node
256- // Expando properties
257- if ast .IsBinaryExpression (node ) {
258- if isPrototypeExpando (node .AsBinaryExpression ()) { // `f.prototype.prop = ...`
259- name = node .AsBinaryExpression ().Left .Expression ().Expression ()
260- } else { // `f[prop] = ...`
261- name = node .AsBinaryExpression ().Left .Expression ()
262- }
263- } else if ast .IsAccessExpression (node ) {
264- if ast .IsPropertyAccessExpression (node ) {
265- name = node .AsPropertyAccessExpression ().Name ()
266- } else if ast .IsElementAccessExpression (node ) {
267- name = node .AsElementAccessExpression ().ArgumentExpression
268- }
269- } else if ast .IsIdentifier (node ) || ast .IsPrivateIdentifier (node ) {
270- name = node
271- } else if ast .IsSpreadAssignment (node ) && ast .IsIdentifier (node .Expression ()) {
272- name = node .Expression ()
273- } else {
274+ if name == nil {
274275 name = ast .GetNameOfDeclaration (node )
275276 }
276277 var text string
@@ -673,12 +674,15 @@ func getSymbolKindFromNode(node *ast.Node) lsproto.SymbolKind {
673674 return lsproto .SymbolKindProperty
674675 }
675676 return lsproto .SymbolKindVariable
676- case ast .KindBinaryExpression :
677+ case ast .KindBinaryExpression , ast . KindCallExpression :
677678 kind := ast .GetAssignmentDeclarationKind (node )
678679 switch kind {
679- case ast .JSDeclarationKindThisProperty , ast .JSDeclarationKindProperty :
680+ case ast .JSDeclarationKindThisProperty , ast .JSDeclarationKindProperty , ast . JSDeclarationKindObjectDefinePropertyValue :
680681 return lsproto .SymbolKindProperty
681682 }
683+ case ast .KindStringLiteral , ast .KindNoSubstitutionTemplateLiteral , ast .KindNumericLiteral :
684+ // String literals used as property names (e.g., in Object.defineProperty)
685+ return lsproto .SymbolKindProperty
682686 }
683687 return lsproto .SymbolKindVariable
684688}
0 commit comments