Auto merge of #16559 - Wilfred:scip_documentation_field, r=lnicola

Set documentation field in SCIP from doc comment

Previously, the documentation field was the same as the text shown to users when they hover over that symbol. The documentation should really just be the doc comment, and as of #16179 the signature is already stored in the signatureDocumentation field.
This commit is contained in:
bors 2024-02-15 09:07:29 +00:00
commit 8443305015
2 changed files with 44 additions and 10 deletions

View File

@ -1,14 +1,16 @@
//! This module provides `StaticIndex` which is used for powering //! This module provides `StaticIndex` which is used for powering
//! read-only code browsers and emitting LSIF //! read-only code browsers and emitting LSIF
use hir::{db::HirDatabase, Crate, HirFileIdExt, Module}; use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics};
use ide_db::{ use ide_db::{
base_db::{FileId, FileRange, SourceDatabaseExt}, base_db::{FileId, FileRange, SourceDatabaseExt},
defs::Definition, defs::Definition,
documentation::Documentation,
famous_defs::FamousDefs,
helpers::get_definition, helpers::get_definition,
FxHashMap, FxHashSet, RootDatabase, FxHashMap, FxHashSet, RootDatabase,
}; };
use syntax::{AstNode, SyntaxKind::*, TextRange, T}; use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T};
use crate::inlay_hints::InlayFieldsToResolve; use crate::inlay_hints::InlayFieldsToResolve;
use crate::navigation_target::UpmappingResult; use crate::navigation_target::UpmappingResult;
@ -22,7 +24,7 @@ use crate::{
/// A static representation of fully analyzed source code. /// A static representation of fully analyzed source code.
/// ///
/// The intended use-case is powering read-only code browsers and emitting LSIF /// The intended use-case is powering read-only code browsers and emitting LSIF/SCIP.
#[derive(Debug)] #[derive(Debug)]
pub struct StaticIndex<'a> { pub struct StaticIndex<'a> {
pub files: Vec<StaticIndexedFile>, pub files: Vec<StaticIndexedFile>,
@ -40,6 +42,7 @@ pub struct ReferenceData {
#[derive(Debug)] #[derive(Debug)]
pub struct TokenStaticData { pub struct TokenStaticData {
pub documentation: Option<Documentation>,
pub hover: Option<HoverResult>, pub hover: Option<HoverResult>,
pub definition: Option<FileRange>, pub definition: Option<FileRange>,
pub references: Vec<ReferenceData>, pub references: Vec<ReferenceData>,
@ -103,6 +106,19 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
modules modules
} }
fn documentation_for_definition(
sema: &Semantics<'_, RootDatabase>,
def: Definition,
scope_node: &SyntaxNode,
) -> Option<Documentation> {
let famous_defs = match &def {
Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(scope_node)?.krate())),
_ => None,
};
def.docs(sema.db, famous_defs.as_ref())
}
impl StaticIndex<'_> { impl StaticIndex<'_> {
fn add_file(&mut self, file_id: FileId) { fn add_file(&mut self, file_id: FileId) {
let current_crate = crates_for(self.db, file_id).pop().map(Into::into); let current_crate = crates_for(self.db, file_id).pop().map(Into::into);
@ -169,6 +185,7 @@ impl StaticIndex<'_> {
*it *it
} else { } else {
let it = self.tokens.insert(TokenStaticData { let it = self.tokens.insert(TokenStaticData {
documentation: documentation_for_definition(&sema, def, &node),
hover: hover_for_definition(&sema, file_id, def, &node, &hover_config), hover: hover_for_definition(&sema, file_id, def, &node, &hover_config),
definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| { definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| {
FileRange { file_id: it.file_id, range: it.focus_or_full_range() } FileRange { file_id: it.file_id, range: it.focus_or_full_range() }

View File

@ -135,12 +135,11 @@ impl flags::Scip {
} }
if symbols_emitted.insert(id) { if symbols_emitted.insert(id) {
let documentation = token let documentation = match &token.documentation {
.hover Some(doc) => vec![doc.as_str().to_owned()],
.as_ref() None => vec![],
.map(|hover| hover.markup.as_str()) };
.filter(|it| !it.is_empty())
.map(|it| vec![it.to_owned()]);
let position_encoding = let position_encoding =
scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into(); scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into();
let signature_documentation = let signature_documentation =
@ -153,7 +152,7 @@ impl flags::Scip {
}); });
let symbol_info = scip_types::SymbolInformation { let symbol_info = scip_types::SymbolInformation {
symbol: symbol.clone(), symbol: symbol.clone(),
documentation: documentation.unwrap_or_default(), documentation,
relationships: Vec::new(), relationships: Vec::new(),
special_fields: Default::default(), special_fields: Default::default(),
kind: symbol_kind(token.kind).into(), kind: symbol_kind(token.kind).into(),
@ -599,4 +598,22 @@ pub mod example_mod {
"rust-analyzer cargo main . MyTypeAlias#", "rust-analyzer cargo main . MyTypeAlias#",
); );
} }
#[test]
fn documentation_matches_doc_comment() {
let s = "/// foo\nfn bar() {}";
let mut host = AnalysisHost::default();
let change_fixture = ChangeFixture::parse(s);
host.raw_database_mut().apply_change(change_fixture.change);
let analysis = host.analysis();
let si = StaticIndex::compute(&analysis);
let file = si.files.first().unwrap();
let (_, token_id) = file.tokens.first().unwrap();
let token = si.tokens.get(*token_id).unwrap();
assert_eq!(token.documentation.as_ref().map(|d| d.as_str()), Some("foo"));
}
} }