Skip to content

Commit b7b09d2

Browse files
authored
Merge pull request #19062 from darichey/scip-fix-module-names
Fix scip indexing of module names
2 parents f3998f7 + a81712b commit b7b09d2

File tree

4 files changed

+133
-100
lines changed

4 files changed

+133
-100
lines changed

crates/ide/src/moniker.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,10 @@ fn def_to_non_local_moniker(
289289
definition: Definition,
290290
from_crate: Crate,
291291
) -> Option<Moniker> {
292-
let module = definition.module(db)?;
292+
let module = match definition {
293+
Definition::Module(module) if module.is_crate_root() => module,
294+
_ => definition.module(db)?,
295+
};
293296
let krate = module.krate();
294297
let edition = krate.edition(db);
295298

@@ -322,12 +325,18 @@ fn def_to_non_local_moniker(
322325
name: name.display(db, edition).to_string(),
323326
desc: def_to_kind(db, def).into(),
324327
});
325-
} else if reverse_description.is_empty() {
326-
// Don't allow the last descriptor to be absent.
327-
return None;
328328
} else {
329329
match def {
330-
Definition::Module(module) if module.is_crate_root() => {}
330+
Definition::Module(module) if module.is_crate_root() => {
331+
// only include `crate` namespace by itself because we prefer
332+
// `rust-analyzer cargo foo . bar/` over `rust-analyzer cargo foo . crate/bar/`
333+
if reverse_description.is_empty() {
334+
reverse_description.push(MonikerDescriptor {
335+
name: "crate".to_owned(),
336+
desc: MonikerDescriptorKind::Namespace,
337+
});
338+
}
339+
}
331340
_ => {
332341
tracing::error!(?def, "Encountered enclosing definition with no name");
333342
}
@@ -340,6 +349,9 @@ fn def_to_non_local_moniker(
340349
};
341350
def = next_def;
342351
}
352+
if reverse_description.is_empty() {
353+
return None;
354+
}
343355
reverse_description.reverse();
344356
let description = reverse_description;
345357

crates/ide/src/static_index.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,10 @@ impl StaticIndex<'_> {
169169
.unwrap();
170170
// hovers
171171
let sema = hir::Semantics::new(self.db);
172-
let tokens_or_nodes = sema.parse_guess_edition(file_id).syntax().clone();
172+
let root = sema.parse_guess_edition(file_id).syntax().clone();
173173
let edition =
174174
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
175-
let tokens = tokens_or_nodes.descendants_with_tokens().filter_map(|it| match it {
175+
let tokens = root.descendants_with_tokens().filter_map(|it| match it {
176176
syntax::NodeOrToken::Node(_) => None,
177177
syntax::NodeOrToken::Token(it) => Some(it),
178178
});
@@ -194,24 +194,19 @@ impl StaticIndex<'_> {
194194
)
195195
});
196196
let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] };
197-
for token in tokens {
198-
let range = token.text_range();
199-
let node = token.parent().unwrap();
200-
let def = match get_definition(&sema, token.clone()) {
201-
Some(it) => it,
202-
None => continue,
203-
};
197+
198+
let mut add_token = |def: Definition, range: TextRange, scope_node: &SyntaxNode| {
204199
let id = if let Some(it) = self.def_map.get(&def) {
205200
*it
206201
} else {
207202
let it = self.tokens.insert(TokenStaticData {
208-
documentation: documentation_for_definition(&sema, def, &node),
203+
documentation: documentation_for_definition(&sema, def, scope_node),
209204
hover: Some(hover_for_definition(
210205
&sema,
211206
file_id,
212207
def,
213208
None,
214-
&node,
209+
scope_node,
215210
None,
216211
false,
217212
&hover_config,
@@ -240,6 +235,22 @@ impl StaticIndex<'_> {
240235
},
241236
});
242237
result.tokens.push((range, id));
238+
};
239+
240+
if let Some(module) = sema.file_to_module_def(file_id) {
241+
let def = Definition::Module(module);
242+
let range = root.text_range();
243+
add_token(def, range, &root);
244+
}
245+
246+
for token in tokens {
247+
let range = token.text_range();
248+
let node = token.parent().unwrap();
249+
let def = match get_definition(&sema, token.clone()) {
250+
Some(it) => it,
251+
None => continue,
252+
};
253+
add_token(def, range, &node);
243254
}
244255
self.files.push(result);
245256
}
@@ -300,6 +311,10 @@ mod tests {
300311
let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect();
301312
for f in s.files {
302313
for (range, _) in f.tokens {
314+
if range.start() == TextSize::from(0) {
315+
// ignore whole file range corresponding to module definition
316+
continue;
317+
}
303318
let it = FileRange { file_id: f.file_id, range };
304319
if !range_set.contains(&it) {
305320
panic!("additional range {it:?}");

crates/rust-analyzer/src/cli/scip.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -444,14 +444,14 @@ impl SymbolGenerator {
444444
MonikerResult::Moniker(moniker) => TokenSymbols {
445445
symbol: scip::symbol::format_symbol(moniker_to_symbol(moniker)),
446446
enclosing_symbol: None,
447-
is_inherent_impl: moniker
448-
.identifier
449-
.description
450-
.get(moniker.identifier.description.len() - 2)
451-
.is_some_and(|descriptor| {
447+
is_inherent_impl: match &moniker.identifier.description[..] {
448+
// inherent impls are represented as impl#[SelfType]
449+
[.., descriptor, _] => {
452450
descriptor.desc == MonikerDescriptorKind::Type
453451
&& descriptor.name == "impl"
454-
}),
452+
}
453+
_ => false,
454+
},
455455
},
456456
MonikerResult::Local { enclosing_moniker } => {
457457
let local_symbol = scip::types::Symbol::new_local(local_count);
@@ -549,7 +549,9 @@ mod test {
549549
continue;
550550
}
551551
for &(range, id) in &file.tokens {
552-
if range.contains(offset - TextSize::from(1)) {
552+
// check if cursor is within token, ignoring token for the module defined by the file (whose range is the whole file)
553+
if range.start() != TextSize::from(0) && range.contains(offset - TextSize::from(1))
554+
{
553555
let token = si.tokens.get(id).unwrap();
554556
found_symbol = match token.moniker.as_ref() {
555557
None => None,
@@ -885,7 +887,7 @@ pub mod example_mod {
885887
);
886888

887889
let file = si.files.first().unwrap();
888-
let (_, token_id) = file.tokens.first().unwrap();
890+
let (_, token_id) = file.tokens.get(1).unwrap(); // first token is file module, second is `bar`
889891
let token = si.tokens.get(*token_id).unwrap();
890892

891893
assert_eq!(token.documentation.as_ref().map(|d| d.as_str()), Some("foo"));

0 commit comments

Comments
 (0)