Skip to content

Commit bcf77a6

Browse files
author
juliamolin
committed
Populate enclosing_range on SCIP definition Occurrences
1 parent 2ee575f commit bcf77a6

58 files changed

Lines changed: 968 additions & 14 deletions

Some content is hidden

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

proto/SCIP.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ message Occurrence {
400400
SyntaxKind syntax_kind = 5;
401401
// (optional) Diagnostics that have been reported for this specific range.
402402
repeated Diagnostic diagnostics = 6;
403+
// (optional) Using the same encoding as the sibling `range` field, half-open
404+
// source range of the nearest non-trivial enclosing AST node. This range must
405+
// enclose the `range` field.
406+
//
407+
// For definition occurrences, the enclosing range should indicate the
408+
// start/end bounds of the entire definition AST node, including
409+
// documentation.
410+
repeated int32 enclosing_range = 7;
403411
}
404412

405413
// Represents a diagnostic, such as a compiler error or warning, which should be

scip_indexer/SCIPIndexer.cc

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

398405
public:
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

872884
public:
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

876888
private:
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
}

test/scip/testdata/alias.snapshot.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@
22

33
class X
44
# ^ definition [..] X#
5+
# enclosing_range 3:1-14:4
56
alias_method :am_aaa, :aaa
67
# ^^^^^^^^^^^^ reference [..] Module#alias_method().
78
alias :a_aaa :aaa
89

910
def aaa
1011
# ^^^ definition [..] X#aaa().
12+
# enclosing_range 7:3-9:6
1113
puts "AAA"
1214
# ^^^^ reference [..] Kernel#puts().
1315
end
1416

1517
def check_alias
1618
# ^^^^^^^^^^^ definition [..] X#check_alias().
19+
# enclosing_range 11:3-13:6
1720
return [am_aaa, a_aaa]
1821
# ^^^^^^ reference [..] X#aaa().
1922
# ^^^^^ reference [..] X#aaa().
@@ -22,15 +25,19 @@ def check_alias
2225

2326
module Mod1
2427
# ^^^^ definition [..] Mod1#
28+
# enclosing_range 16:1-18:4
2529
ABC = 10
2630
# ^^^ definition [..] Mod1#ABC.
31+
# enclosing_range 16:1-16:12
2732
# ^^^^^^^^ reference [..] Mod1#ABC.
2833
end
2934

3035
module Mod2
3136
# ^^^^ definition [..] Mod2#
37+
# enclosing_range 20:1-22:4
3238
FEG = Mod1::ABC
3339
# ^^^ definition [..] Mod2#FEG.
40+
# enclosing_range 20:1-20:12
3441
# relation reference=[..] Mod1#ABC.
3542
# ^^^^ reference [..] Mod1#
3643
# ^^^ reference [..] Mod1#ABC.
@@ -39,7 +46,9 @@ module Mod2
3946

4047
def myfunction(myparam)
4148
# ^^^^^^^^^^ definition [..] Object#myfunction().
49+
# enclosing_range 24:1-26:4
4250
# ^^^^^^^ definition local 1$3083414419
51+
# enclosing_range 24:1-26:4
4352
myparam + Mod2::FEG
4453
# ^^^^^^^ reference local 1$3083414419
4554
# ^^^^ reference [..] Mod2#
@@ -48,43 +57,53 @@ def myfunction(myparam)
4857

4958
class X < T::Enum
5059
# ^ definition [..] X#
60+
# enclosing_range 28:1-36:4
5161
# ^ definition [..] X#serialize().
62+
# enclosing_range 28:1-36:4
5263
# ^ reference [..] T#
5364
# ^^^^ reference [..] Module#public().
5465
# ^^^^ reference [..] String#
5566
# ^^^^ reference [..] T#Enum#
5667
enums do
5768
A = new("A")
5869
# ^ definition [..] X#A.
70+
# enclosing_range 28:1-28:18
5971
# ^^^ reference [..] Class#new().
6072
B = new
6173
# ^ definition [..] X#B.
74+
# enclosing_range 28:1-28:18
6275
# ^^^ reference [..] Class#new().
6376
C = B
6477
# ^ definition [..] X#C.
78+
# enclosing_range 28:1-28:18
6579
# relation reference=[..] X#B.
6680
# ^ reference [..] X#B.
6781
end
6882

6983
All = T.let([A, B], T::Array[X])
7084
# ^^^ definition [..] X#All.
85+
# enclosing_range 28:1-28:18
7186
# ^ reference [..] X#A.
7287
# ^ reference [..] X#B.
7388
# ^^^^^^^^ definition local 4$119448696
89+
# enclosing_range 28:1-28:18
7490
# ^ reference [..] X#
7591
end
7692

7793
# Adding more cases like this is not supported (c.f. isTEnum),
7894
# but let's at least add a test.
7995
class Y < X
8096
# ^ definition [..] Y#
97+
# enclosing_range 40:1-45:4
8198
# ^ reference [..] X#
8299
enums do
83100
D = new
84101
# ^ definition [..] Y#D.
102+
# enclosing_range 40:1-40:12
85103
# ^^^ reference [..] Class#new().
86104
E = B
87105
# ^ definition [..] Y#E.
106+
# enclosing_range 40:1-40:12
88107
# relation reference=[..] X#B.
89108
# ^^^^^ reference [..] Y#E.
90109
# ^ reference [..] X#B.

test/scip/testdata/args.snapshot.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
def args(x, y)
44
# ^^^^ definition [..] Object#args().
5+
# enclosing_range 3:1-11:4
56
# ^ definition local 1$2634721084
7+
# enclosing_range 3:1-11:4
68
# ^ definition local 2$2634721084
9+
# enclosing_range 3:1-11:4
710
z = x + y
811
# ^ definition local 3$2634721084
12+
# enclosing_range 3:1-11:4
913
# ^ reference local 1$2634721084
1014
# ^ reference local 2$2634721084
1115
if x == 2
@@ -27,9 +31,13 @@ def args(x, y)
2731

2832
def keyword_args(w:, x: 3, y: [], **kwargs)
2933
# ^^^^^^^^^^^^ definition [..] Object#keyword_args().
34+
# enclosing_range 13:1-17:4
3035
# ^^ definition local 1$3526982640
36+
# enclosing_range 13:1-17:4
3137
# ^^ definition local 2$3526982640
38+
# enclosing_range 13:1-17:4
3239
# ^^ definition local 3$3526982640
40+
# enclosing_range 13:1-17:4
3341
y << w + x
3442
# ^ reference local 3$3526982640
3543
# ^ reference local 1$3526982640
@@ -41,8 +49,10 @@ def keyword_args(w:, x: 3, y: [], **kwargs)
4149

4250
def use_kwargs
4351
# ^^^^^^^^^^ definition [..] Object#use_kwargs().
52+
# enclosing_range 19:1-24:4
4453
h = { a: 3 }
4554
# ^ definition local 1$571973038
55+
# enclosing_range 19:1-24:4
4656
keyword_args(w: 0, **h)
4757
# ^^^^^^^^^^^^ reference [..] Object#keyword_args().
4858
# ^ reference local 1$571973038

test/scip/testdata/arrays.snapshot.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
def arrays(a, i)
44
# ^^^^^^ definition [..] Object#arrays().
5+
# enclosing_range 3:1-9:4
56
# ^ definition local 1$513334479
7+
# enclosing_range 3:1-9:4
68
# ^ definition local 2$513334479
9+
# enclosing_range 3:1-9:4
710
a[0] = 0
811
# ^ reference local 1$513334479
912
a[1] = a[2]
@@ -16,6 +19,7 @@ def arrays(a, i)
1619
# ^ reference local 2$513334479
1720
b = a[2..-1]
1821
# ^ definition local 3$513334479
22+
# enclosing_range 3:1-9:4
1923
# ^ reference local 1$513334479
2024
a << a[-1]
2125
# ^ reference local 1$513334479

0 commit comments

Comments
 (0)