@@ -288,7 +288,8 @@ class SCIPState {
288288
289289 absl::Status saveDefinitionImpl (const core::GlobalState &gs, core::FileRef file, const string &symbolString,
290290 core::Loc occLoc, const SmallVec<string> &docs,
291- const SmallVec<scip::Relationship> &rels) {
291+ const SmallVec<scip::Relationship> &rels,
292+ optional<core::Loc> enclosingLoc = nullopt ) {
292293 ENFORCE (!symbolString.empty ());
293294 occLoc = trimColonColonPrefix (gs, occLoc);
294295 auto range = sorbet::scip_indexer::fromSorbetLoc (gs, occLoc);
@@ -305,6 +306,12 @@ class SCIPState {
305306 for (auto val : range) {
306307 occurrence.add_range (val);
307308 }
309+ if (enclosingLoc.has_value () && !enclosingLoc->empty ()) {
310+ auto encRange = sorbet::scip_indexer::fromSorbetLoc (gs, enclosingLoc.value ());
311+ for (auto val : encRange) {
312+ occurrence.add_enclosing_range (val);
313+ }
314+ }
308315 switch (emitted) {
309316 case Emitted::Now:
310317 break ;
@@ -396,7 +403,8 @@ class SCIPState {
396403 }
397404
398405public:
399- absl::Status saveDefinition (const core::GlobalState &gs, core::FileRef file, OwnedLocal occ, core::TypePtr type) {
406+ absl::Status saveDefinition (const core::GlobalState &gs, core::FileRef file, OwnedLocal occ, core::TypePtr type,
407+ optional<core::Loc> enclosingLoc = nullopt ) {
400408 if (this ->cacheOccurrence (gs, file, occ, scip::SymbolRole::Definition)) {
401409 return absl::OkStatus ();
402410 }
@@ -407,7 +415,7 @@ class SCIPState {
407415 ENFORCE (var.has_value (), " Failed to find source text for definition of local variable" );
408416 docStrings.push_back (fmt::format (" ```ruby\n {} ({})\n ```" , var.value (), type.show (gs)));
409417 }
410- return this ->saveDefinitionImpl (gs, file, occ.toSCIPString (gs, file), loc, docStrings, {});
418+ return this ->saveDefinitionImpl (gs, file, occ.toSCIPString (gs, file), loc, docStrings, {}, enclosingLoc );
411419 }
412420
413421 void saveAliasRelationship (const core::GlobalState &gs, UntypedGenericSymbolRef aliasedSymbol,
@@ -423,7 +431,8 @@ class SCIPState {
423431 // TODO(varun): Should we always pass in the location instead of sometimes only?
424432 absl::Status saveDefinition (const core::GlobalState &gs, core::FileRef file, GenericSymbolRef symRef,
425433 optional<UntypedGenericSymbolRef> aliasedSymbol,
426- optional<core::LocOffsets> loc = nullopt ) {
434+ optional<core::LocOffsets> loc = nullopt ,
435+ optional<core::Loc> enclosingLoc = nullopt ) {
427436 // In practice, there doesn't seem to be any situation which triggers
428437 // a duplicate definition being emitted, so skip calling cacheOccurrence here.
429438 auto occLoc = loc.has_value () ? core::Loc (file, loc.value ()) : symRef.symbolLoc (gs);
@@ -452,7 +461,7 @@ class SCIPState {
452461 this ->saveAliasRelationship (gs, aliasedSymbol.value (), rels);
453462 }
454463
455- return this ->saveDefinitionImpl (gs, file, symbolString, occLoc, docs, rels);
464+ return this ->saveDefinitionImpl (gs, file, symbolString, occLoc, docs, rels, enclosingLoc );
456465 }
457466
458467 absl::Status saveReference (const core::GlobalState &gs, core::FileRef file, OwnedLocal occ,
@@ -868,10 +877,13 @@ class CFGTraversal final {
868877 uint32_t counter = 0 ;
869878 SCIPState &scipState;
870879 core::Context ctx;
880+ // The enclosing range for all occurrences emitted during this traversal
881+ // (i.e. the method definition's full source range).
882+ optional<core::Loc> enclosingLoc;
871883
872884public:
873- CFGTraversal (SCIPState &scipState, core::Context ctx)
874- : blockLocals(), functionLocals(), aliasMap(), scipState(scipState), ctx(ctx) {}
885+ CFGTraversal (SCIPState &scipState, core::Context ctx, optional<core::Loc> enclosingLoc = nullopt )
886+ : blockLocals(), functionLocals(), aliasMap(), scipState(scipState), ctx(ctx), enclosingLoc(enclosingLoc) {}
875887
876888private:
877889 uint32_t addLocal (const cfg::BasicBlock *bb, cfg::LocalRef localRef) {
@@ -976,7 +988,7 @@ class CFGTraversal final {
976988 defRefData.aliasRHS ->toString (gs, cfg), file.data (gs).path ());
977989 }
978990 }
979- status = this ->scipState .saveDefinition (gs, file, namedSym, aliasedSymbol, loc);
991+ status = this ->scipState .saveDefinition (gs, file, namedSym, aliasedSymbol, loc, this -> enclosingLoc );
980992 } else {
981993 auto overrideType = computeOverrideType (namedSym.definitionType (), type);
982994 status = this ->scipState .saveReference (ctx, namedSym, overrideType, loc, referenceRole);
@@ -995,7 +1007,8 @@ class CFGTraversal final {
9951007 }
9961008 }
9971009 if (isDefinition) {
998- status = this ->scipState .saveDefinition (gs, file, OwnedLocal{this ->ctx .owner , localId, loc}, type);
1010+ status = this ->scipState .saveDefinition (gs, file, OwnedLocal{this ->ctx .owner , localId, loc}, type,
1011+ this ->enclosingLoc );
9991012 } else {
10001013 status = this ->scipState .saveReference (gs, file, OwnedLocal{this ->ctx .owner , localId, loc},
10011014 overrideType, referenceRole);
@@ -1059,7 +1072,8 @@ class CFGTraversal final {
10591072 absl::Status status;
10601073 string kind;
10611074 if (isDefinition) {
1062- status = this ->scipState .saveDefinition (gs, file, namedSym, /* aliasedSymbol*/ nullopt , arg.loc );
1075+ status = this ->scipState .saveDefinition (gs, file, namedSym, /* aliasedSymbol*/ nullopt , arg.loc ,
1076+ this ->enclosingLoc );
10631077 kind = " definition" ;
10641078 } else {
10651079 status = this ->scipState .saveReference (ctx, namedSym, nullopt , arg.loc , 0 );
@@ -1255,7 +1269,8 @@ class CFGTraversal final {
12551269 if (isMethodClassStaticInit && namedSym.isEnumConstant (gs)) {
12561270 // Enum constants don't have references in the <static-init> of the owner
12571271 // class, but they do have alias instructions, so record those as definitions.
1258- status = this ->scipState .saveDefinition (ctx, file, namedSym, /* aliasSymbol*/ nullopt , loc);
1272+ status = this ->scipState .saveDefinition (ctx, file, namedSym, /* aliasSymbol*/ nullopt , loc,
1273+ this ->enclosingLoc );
12591274 } else {
12601275 status = this ->scipState .saveReference (ctx, namedSym, nullopt , loc, 0 );
12611276 }
@@ -1491,7 +1506,8 @@ class SCIPSemanticExtension : public SemanticExtension {
14911506
14921507 auto scipState = this ->getSCIPState ();
14931508 auto sym = scip_indexer::GenericSymbolRef::classOrModule (klass.symbol );
1494- auto status = scipState->saveDefinition (gs, file, sym, /* aliasedSymbol*/ nullopt , nameLoc);
1509+ auto klassLoc = core::Loc (file, klass.loc );
1510+ auto status = scipState->saveDefinition (gs, file, sym, /* aliasedSymbol*/ nullopt , nameLoc, klassLoc);
14951511 ENFORCE (status.ok ());
14961512 auto *expr = &klass.name ;
14971513 if (auto *constantLit = ast::cast_tree<ast::ConstantLit>(*expr)) {
@@ -1513,9 +1529,10 @@ class SCIPSemanticExtension : public SemanticExtension {
15131529 return ;
15141530 }
15151531 auto scipState = this ->getSCIPState ();
1532+ auto methodLoc = core::Loc (file, methodDef.loc );
15161533 if (methodDef.name != core::Names::staticInit ()) {
15171534 auto sym = scip_indexer::GenericSymbolRef::method (methodDef.symbol );
1518- auto status = scipState->saveDefinition (gs, file, sym, /* aliasedSymbol*/ nullopt );
1535+ auto status = scipState->saveDefinition (gs, file, sym, /* aliasedSymbol*/ nullopt , /* loc */ nullopt , methodLoc );
15191536 ENFORCE (status.ok ());
15201537 }
15211538
@@ -1534,7 +1551,7 @@ class SCIPSemanticExtension : public SemanticExtension {
15341551 // information repeatedly for each occurrence.
15351552
15361553 auto &scipStateRef = *scipState.get ();
1537- sorbet::scip_indexer::CFGTraversal traversal (scipStateRef, core::Context (gs, methodDef.symbol , file));
1554+ sorbet::scip_indexer::CFGTraversal traversal (scipStateRef, core::Context (gs, methodDef.symbol , file), methodLoc );
15381555 traversal.traverse (cfg);
15391556 scipStateRef.clearFunctionLocalCaches ();
15401557 }
0 commit comments