@@ -65,6 +65,8 @@ const Builder = struct {
6565 locations : std .ArrayListUnmanaged (types .Location ) = .empty ,
6666 /// this is the declaration we are searching for
6767 decl_handle : Analyser.DeclWithHandle ,
68+ /// the decl is local to a function, block, etc
69+ local_only_decl : bool ,
6870 /// Whether the `decl_handle` has been added
6971 did_add_decl_handle : bool = false ,
7072 analyser : * Analyser ,
@@ -104,6 +106,10 @@ const Builder = struct {
104106 fn referenceNode (self : * const Context , tree : Ast , node : Ast.Node.Index ) error {OutOfMemory }! void {
105107 const builder = self .builder ;
106108 const handle = self .handle ;
109+ const decl_name = offsets .identifierTokenToNameSlice (
110+ builder .decl_handle .handle .tree ,
111+ builder .decl_handle .nameToken (),
112+ );
107113
108114 switch (tree .nodeTag (node )) {
109115 .identifier ,
@@ -119,6 +125,7 @@ const Builder = struct {
119125 else = > unreachable ,
120126 };
121127 const name = offsets .identifierTokenToNameSlice (tree , name_token );
128+ if (! std .mem .eql (u8 , name , decl_name )) return ;
122129
123130 const child = try builder .analyser .lookupSymbolGlobal (
124131 handle ,
@@ -131,15 +138,18 @@ const Builder = struct {
131138 }
132139 },
133140 .field_access = > {
134- const lhs_node , const field_name = tree .nodeData (node ).node_and_token ;
141+ if (builder .local_only_decl ) return ;
142+ const lhs_node , const field_token = tree .nodeData (node ).node_and_token ;
143+ const name = offsets .identifierTokenToNameSlice (tree , field_token );
144+ if (! std .mem .eql (u8 , name , decl_name )) return ;
145+
135146 const lhs = try builder .analyser .resolveTypeOfNode (.of (lhs_node , handle )) orelse return ;
136147 const deref_lhs = try builder .analyser .resolveDerefType (lhs ) orelse lhs ;
137148
138- const symbol = offsets .identifierTokenToNameSlice (tree , field_name );
139- const child = try deref_lhs .lookupSymbol (builder .analyser , symbol ) orelse return ;
149+ const child = try deref_lhs .lookupSymbol (builder .analyser , name ) orelse return ;
140150
141151 if (builder .decl_handle .eql (child )) {
142- try builder .add (handle , field_name );
152+ try builder .add (handle , field_token );
143153 }
144154 },
145155 .struct_init_one ,
@@ -151,23 +161,28 @@ const Builder = struct {
151161 .struct_init_dot_two ,
152162 .struct_init_dot_two_comma ,
153163 = > {
164+ if (builder .local_only_decl ) return ;
154165 var buffer : [2 ]Ast.Node.Index = undefined ;
155166 const struct_init = tree .fullStructInit (& buffer , node ).? ;
156167 for (struct_init .ast .fields ) | value_node | { // the node of `value` in `.name = value`
157168 const name_token = tree .firstToken (value_node ) - 2 ; // math our way two token indexes back to get the `name`
158169 const name_loc = offsets .tokenToLoc (tree , name_token );
159170 const name = offsets .locToSlice (tree .source , name_loc );
171+ if (! std .mem .eql (u8 , name , decl_name )) continue ;
160172
161173 const lookup = try builder .analyser .lookupSymbolFieldInit (handle , name , node , &.{}) orelse continue ;
162174
163175 if (builder .decl_handle .eql (lookup )) {
164176 try builder .add (handle , name_token );
177+ return ;
165178 }
166179 }
167180 },
168181 .enum_literal = > {
182+ if (builder .local_only_decl ) return ;
169183 const name_token = tree .nodeMainToken (node );
170184 const name = offsets .identifierTokenToNameSlice (handle .tree , name_token );
185+ if (! std .mem .eql (u8 , name , decl_name )) return ;
171186 const lookup = try builder .analyser .getSymbolEnumLiteral (handle , tree .tokenStart (name_token ), name ) orelse return ;
172187
173188 if (builder .decl_handle .eql (lookup )) {
@@ -242,48 +257,61 @@ fn symbolReferences(
242257
243258 std .debug .assert (decl_handle .decl != .label ); // use `labelReferences` instead
244259
245- var builder = Builder {
246- .allocator = allocator ,
247- .analyser = analyser ,
248- .decl_handle = decl_handle ,
249- .encoding = encoding ,
250- };
251- errdefer builder .deinit ();
252-
253- const curr_handle = decl_handle .handle ;
254- if (include_decl ) try builder .add (curr_handle , decl_handle .nameToken ());
255-
256- switch (decl_handle .decl ) {
257- .ast_node = > {
258- try builder .collectReferences (curr_handle , .root );
259-
260- const source_index = decl_handle .handle .tree .tokenStart (decl_handle .nameToken ());
261- // highlight requests only pertain to the current document, otherwise we can try to narrow things down
262- const workspace = if (request == .highlight ) false else blk : {
263- const doc_scope = try curr_handle .getDocumentScope ();
264- const scope_index = Analyser .innermostScopeAtIndex (doc_scope , source_index );
265- break :blk switch (doc_scope .getScopeTag (scope_index )) {
266- .function , .block = > false ,
267- .container , .container_usingnamespace = > decl_handle .isPublic (),
268- .other = > true ,
269- };
270- };
271- if (workspace ) {
272- try gatherReferences (allocator , analyser , curr_handle , skip_std_references , include_decl , & builder , .get );
273- }
260+ const doc_scope = try decl_handle .handle .getDocumentScope ();
261+ const source_index = decl_handle .handle .tree .tokenStart (decl_handle .nameToken ());
262+ const scope_index = Analyser .innermostScopeAtIndexWithTag (doc_scope , source_index , .init (.{
263+ .block = true ,
264+ .container = true ,
265+ .container_usingnamespace = true ,
266+ .function = false ,
267+ .other = false ,
268+ })).unwrap ().? ;
269+ const scope_node = doc_scope .getScopeAstNode (scope_index ).? ;
270+
271+ // If `local_node != null`, references to the declaration can only be
272+ // found inside of the given ast node.
273+ const local_node : ? Ast.Node.Index = switch (decl_handle .decl ) {
274+ .ast_node = > switch (doc_scope .getScopeTag (scope_index )) {
275+ .block = > scope_node ,
276+ .container , .container_usingnamespace = > null ,
277+ .function , .other = > unreachable ,
274278 },
275279 .optional_payload ,
276280 .error_union_payload ,
277281 .error_union_error ,
278282 .for_loop_payload ,
279283 .assign_destructure ,
280- .switch_payload ,
281- = > {
282- try builder .collectReferences (curr_handle , .root );
283- },
284- .function_parameter = > | payload | try builder .collectReferences (curr_handle , payload .func ),
284+ = > scope_node ,
285+ .switch_payload = > | payload | payload .node ,
286+ .function_parameter = > | payload | payload .func ,
285287 .label = > unreachable , // handled separately by labelReferences
286- .error_token = > {},
288+ .error_token = > return .empty ,
289+ };
290+
291+ var builder : Builder = .{
292+ .allocator = allocator ,
293+ .analyser = analyser ,
294+ .decl_handle = decl_handle ,
295+ .local_only_decl = local_node != null ,
296+ .encoding = encoding ,
297+ };
298+ errdefer builder .deinit ();
299+
300+ if (include_decl ) try builder .add (decl_handle .handle , decl_handle .nameToken ());
301+
302+ try builder .collectReferences (decl_handle .handle , local_node orelse .root );
303+
304+ const workspace = local_node == null and request != .highlight and decl_handle .isPublic ();
305+ if (workspace ) {
306+ try gatherReferences (
307+ allocator ,
308+ analyser ,
309+ decl_handle .handle ,
310+ skip_std_references ,
311+ include_decl ,
312+ & builder ,
313+ .get ,
314+ );
287315 }
288316
289317 return builder .locations ;
0 commit comments