Unnamed repository; edit this file 'description' to name the repository.
feature: Set enclosing_range field on SCIP output
Previously we didn't set the enclosing position on definitions, so SCIP consumers didn't know the position of the entire definition that provides the symbol.
Wilfred Hughes 5 months ago
parent 3a0d3d5 · commit dacc74f
-rw-r--r--crates/ide/src/static_index.rs12
-rw-r--r--crates/rust-analyzer/src/cli/scip.rs38
2 files changed, 49 insertions, 1 deletions
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 052de0f38e..52b201df96 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -44,7 +44,15 @@ pub struct ReferenceData {
pub struct TokenStaticData {
pub documentation: Option<Documentation>,
pub hover: Option<HoverResult>,
+ /// The position of the token itself.
+ ///
+ /// For example, in `fn foo() {}` this is the position of `foo`.
pub definition: Option<FileRange>,
+ /// The position of the entire definition that this token belongs to.
+ ///
+ /// For example, in `fn foo() {}` this is the position from `fn`
+ /// to the closing brace.
+ pub definition_body: Option<FileRange>,
pub references: Vec<ReferenceData>,
pub moniker: Option<MonikerResult>,
pub display_name: Option<String>,
@@ -248,6 +256,10 @@ impl StaticIndex<'_> {
definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map(|it| {
FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
}),
+ definition_body: def
+ .try_to_nav(&sema)
+ .map(UpmappingResult::call_site)
+ .map(|it| FileRange { file_id: it.file_id, range: it.full_range }),
references: vec![],
moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
display_name: def
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index 37f83f6dee..f822efb53d 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -189,6 +189,13 @@ impl flags::Scip {
symbol_roles |= scip_types::SymbolRole::Definition as i32;
}
+ let enclosing_range = match token.definition_body {
+ Some(def_body) if def_body.file_id == file_id => {
+ text_range_to_scip_range(&line_index, def_body.range)
+ }
+ _ => Vec::new(),
+ };
+
occurrences.push(scip_types::Occurrence {
range: text_range_to_scip_range(&line_index, text_range),
symbol,
@@ -197,7 +204,7 @@ impl flags::Scip {
syntax_kind: Default::default(),
diagnostics: Vec::new(),
special_fields: Default::default(),
- enclosing_range: Vec::new(),
+ enclosing_range,
});
}
@@ -508,6 +515,7 @@ fn moniker_descriptors(identifier: &MonikerIdentifier) -> Vec<scip_types::Descri
#[cfg(test)]
mod test {
use super::*;
+ use hir::FileRangeWrapper;
use ide::{FilePosition, TextSize};
use test_fixture::ChangeFixture;
use vfs::VfsPath;
@@ -887,4 +895,32 @@ pub mod example_mod {
assert_eq!(token.documentation.as_ref().map(|d| d.as_str()), Some("foo"));
}
+
+ #[test]
+ fn function_has_enclosing_range() {
+ let s = "fn foo() {}";
+
+ let mut host = AnalysisHost::default();
+ let change_fixture = ChangeFixture::parse(host.raw_database(), s);
+ host.raw_database_mut().apply_change(change_fixture.change);
+
+ let analysis = host.analysis();
+ let si = StaticIndex::compute(
+ &analysis,
+ VendoredLibrariesConfig::Included {
+ workspace_root: &VfsPath::new_virtual_path("/workspace".to_owned()),
+ },
+ );
+
+ let file = si.files.first().unwrap();
+ let (_, token_id) = file.tokens.get(1).unwrap(); // first token is file module, second is `foo`
+ let token = si.tokens.get(*token_id).unwrap();
+
+ let expected_range = FileRangeWrapper {
+ file_id: FileId::from_raw(0),
+ range: TextRange::new(0.into(), 11.into()),
+ };
+
+ assert_eq!(token.definition_body, Some(expected_range));
+ }
}