Skip to content

Commit 73e04a5

Browse files
committed
fix: skip SCIP generation of occurrences with empty locations
Sorbet can assign empty locations to synthesized AST nodes, including Minitest `before` hooks inside `test_each`. Passing these locations to `trimColonColonPrefix` triggers an assertion in debug builds and can segfault in release builds as we've seen in production. Skip definitions and references with empty locations before converting them to SCIP ranges, and add a regression test for the Minitest case. Signed-off-by: Emi <emi@sourcegraph.com>
1 parent 1d2972b commit 73e04a5

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

‎scip_indexer/SCIPIndexer.cc‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@ InlinedVector<int32_t, 4> fromSorbetLoc(const core::GlobalState &gs, core::Loc l
119119
}
120120

121121
core::Loc trimColonColonPrefix(const core::GlobalState &gs, core::Loc baseLoc) {
122-
ENFORCE(!baseLoc.empty());
122+
// Sorbet can assign empty locations to synthesized AST nodes. There is no
123+
// source prefix to trim in that case, and callers will skip emitting an
124+
// occurrence because SCIP ranges must be non-empty.
125+
if (!baseLoc.exists() || baseLoc.empty()) {
126+
return baseLoc;
127+
}
123128
auto source = baseLoc.source(gs);
124129
if (!source.has_value()) {
125130
return baseLoc;
@@ -291,6 +296,9 @@ class SCIPState {
291296
const SmallVec<scip::Relationship> &rels,
292297
optional<core::Loc> enclosingLoc = nullopt) {
293298
ENFORCE(!symbolString.empty());
299+
if (!occLoc.exists() || occLoc.empty()) {
300+
return absl::OkStatus();
301+
}
294302
occLoc = trimColonColonPrefix(gs, occLoc);
295303
auto range = sorbet::scip_indexer::fromSorbetLoc(gs, occLoc);
296304
if (range.size() == 4) {
@@ -328,7 +336,11 @@ class SCIPState {
328336
void saveReferenceImpl(const core::GlobalState &gs, core::FileRef file, const string &symbolString,
329337
const SmallVec<string> &overrideDocs, core::LocOffsets occLocOffsets, int32_t symbol_roles) {
330338
ENFORCE(!symbolString.empty());
331-
auto occLoc = trimColonColonPrefix(gs, core::Loc(file, occLocOffsets));
339+
auto occLoc = core::Loc(file, occLocOffsets);
340+
if (!occLoc.exists() || occLoc.empty()) {
341+
return;
342+
}
343+
occLoc = trimColonColonPrefix(gs, occLoc);
332344
scip::Occurrence occurrence;
333345
occurrence.set_symbol(symbolString);
334346
occurrence.set_symbol_roles(symbol_roles);

0 commit comments

Comments
 (0)