10841: Emit moniker in lsif r=Veykril a=HKalbasi

fix #10559 

Co-authored-by: hkalbasi <hamidrezakalbasi@protonmail.com>
Co-authored-by: HKalbasi <45197576+HKalbasi@users.noreply.github.com>
This commit is contained in:
bors[bot] 2021-11-29 11:13:39 +00:00 committed by GitHub
commit 393cbd0982
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 511 additions and 19 deletions

View File

@ -10,9 +10,10 @@
use vfs::{file_set::FileSet, VfsPath};
use crate::{
input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env,
FileId, FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
SourceDatabaseExt, SourceRoot, SourceRootId,
input::{CrateName, CrateOrigin},
Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, FileId, FilePosition,
FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, SourceDatabaseExt,
SourceRoot, SourceRootId,
};
pub const WORKSPACE: SourceRootId = SourceRootId(0);
@ -130,17 +131,18 @@ pub fn parse(ra_fixture: &str) -> ChangeFixture {
current_source_root_kind = *kind;
}
if let Some(krate) = meta.krate {
if let Some((krate, origin, version)) = meta.krate {
let crate_name = CrateName::normalize_dashes(&krate);
let crate_id = crate_graph.add_crate_root(
file_id,
meta.edition,
Some(crate_name.clone().into()),
None,
version,
meta.cfg.clone(),
meta.cfg,
meta.env,
Default::default(),
origin,
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none());
@ -174,6 +176,7 @@ pub fn parse(ra_fixture: &str) -> ChangeFixture {
default_cfg,
Env::default(),
Default::default(),
Default::default(),
);
} else {
for (from, to, prelude) in crate_deps {
@ -209,6 +212,7 @@ pub fn parse(ra_fixture: &str) -> ChangeFixture {
CfgOptions::default(),
Env::default(),
Vec::new(),
CrateOrigin::Lang,
);
for krate in all_crates {
@ -243,6 +247,7 @@ pub fn parse(ra_fixture: &str) -> ChangeFixture {
CfgOptions::default(),
Env::default(),
proc_macro,
CrateOrigin::Lang,
);
for krate in all_crates {
@ -324,7 +329,7 @@ enum SourceRootKind {
#[derive(Debug)]
struct FileMeta {
path: String,
krate: Option<String>,
krate: Option<(String, CrateOrigin, Option<String>)>,
deps: Vec<String>,
extern_prelude: Vec<String>,
cfg: CfgOptions,
@ -333,16 +338,32 @@ struct FileMeta {
introduce_new_source_root: Option<SourceRootKind>,
}
fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
if let Some((a, b)) = crate_str.split_once("@") {
let (version, origin) = match b.split_once(":") {
Some(("CratesIo", data)) => match data.split_once(",") {
Some((version, url)) => {
(version, CrateOrigin::CratesIo { repo: Some(url.to_owned()) })
}
_ => panic!("Bad crates.io parameter: {}", data),
},
_ => panic!("Bad string for crate origin: {}", b),
};
(a.to_owned(), origin, Some(version.to_string()))
} else {
(crate_str, CrateOrigin::Unknown, None)
}
}
impl From<Fixture> for FileMeta {
fn from(f: Fixture) -> FileMeta {
let mut cfg = CfgOptions::default();
f.cfg_atoms.iter().for_each(|it| cfg.insert_atom(it.into()));
f.cfg_key_values.iter().for_each(|(k, v)| cfg.insert_key_value(k.into(), v.into()));
let deps = f.deps;
FileMeta {
path: f.path,
krate: f.krate,
krate: f.krate.map(parse_crate),
extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()),
deps,
cfg,

View File

@ -112,6 +112,24 @@ fn deref(&self) -> &str {
}
}
/// Origin of the crates. It is used in emitting monikers.
#[derive(Debug, Clone)]
pub enum CrateOrigin {
/// Crates that are from crates.io official registry,
CratesIo { repo: Option<String> },
/// Crates that are provided by the language, like std, core, proc-macro, ...
Lang,
/// Crates that we don't know their origin.
// Idealy this enum should cover all cases, and then we remove this variant.
Unknown,
}
impl Default for CrateOrigin {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CrateDisplayName {
// The name we use to display various paths (with `_`).
@ -205,6 +223,7 @@ pub struct CrateData {
pub env: Env,
pub dependencies: Vec<Dependency>,
pub proc_macro: Vec<ProcMacro>,
pub origin: CrateOrigin,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -256,6 +275,7 @@ pub fn add_crate_root(
potential_cfg_options: CfgOptions,
env: Env,
proc_macro: Vec<ProcMacro>,
origin: CrateOrigin,
) -> CrateId {
let data = CrateData {
root_file_id: file_id,
@ -267,6 +287,7 @@ pub fn add_crate_root(
env,
proc_macro,
dependencies: Vec::new(),
origin,
};
let crate_id = CrateId(self.arena.len() as u32);
let prev = self.arena.insert(crate_id, data);
@ -571,6 +592,7 @@ fn detect_cyclic_dependency_indirect() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -581,6 +603,7 @@ fn detect_cyclic_dependency_indirect() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@ -591,6 +614,7 @@ fn detect_cyclic_dependency_indirect() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -615,6 +639,7 @@ fn detect_cyclic_dependency_direct() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -625,6 +650,7 @@ fn detect_cyclic_dependency_direct() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -646,6 +672,7 @@ fn it_works() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -656,6 +683,7 @@ fn it_works() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@ -666,6 +694,7 @@ fn it_works() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -687,6 +716,7 @@ fn dashes_are_normalized() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -697,6 +727,7 @@ fn dashes_are_normalized() {
CfgOptions::default(),
Env::default(),
Default::default(),
Default::default(),
);
assert!(graph
.add_dep(

View File

@ -11,9 +11,9 @@
pub use crate::{
change::Change,
input::{
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env,
ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroId, ProcMacroKind,
SourceRoot, SourceRootId,
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
Edition, Env, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroId,
ProcMacroKind, SourceRoot, SourceRootId,
},
};
pub use salsa::{self, Cancelled};

View File

@ -34,7 +34,7 @@
use std::{iter, ops::ControlFlow, sync::Arc};
use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, Edition, FileId};
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId};
use either::Either;
use hir_def::{
adt::{ReprKind, VariantData},
@ -144,6 +144,10 @@ pub struct CrateDependency {
}
impl Crate {
pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
db.crate_graph()[self.id].origin.clone()
}
pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
db.crate_graph()[self.id]
.dependencies

View File

@ -41,6 +41,7 @@ macro_rules! eprintln {
mod join_lines;
mod markdown_remove;
mod matching_brace;
mod moniker;
mod move_item;
mod parent_module;
mod references;
@ -83,6 +84,7 @@ macro_rules! eprintln {
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
join_lines::JoinLinesConfig,
markup::Markup,
moniker::{MonikerKind, MonikerResult, PackageInformation},
move_item::Direction,
navigation_target::NavigationTarget,
prime_caches::PrimeCachesProgress,
@ -225,6 +227,7 @@ pub fn from_single_file(text: String) -> (Analysis, FileId) {
cfg_options,
Env::default(),
Default::default(),
Default::default(),
);
change.change_file(file_id, Some(Arc::new(text)));
change.set_crate_graph(crate_graph);
@ -425,6 +428,14 @@ pub fn hover(
self.with_db(|db| hover::hover(db, range, config))
}
/// Returns moniker of symbol at position.
pub fn moniker(
&self,
position: FilePosition,
) -> Cancellable<Option<RangeInfo<Vec<moniker::MonikerResult>>>> {
self.with_db(|db| moniker::moniker(db, position))
}
/// Return URL(s) for the documentation of the symbol under the cursor.
pub fn external_docs(
&self,

233
crates/ide/src/moniker.rs Normal file
View File

@ -0,0 +1,233 @@
//! This module generates [moniker](https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/#exportsImports)
//! for LSIF and LSP.
use hir::{db::DefDatabase, Crate, Name, Semantics};
use ide_db::{
base_db::{CrateOrigin, FileId, FileLoader, FilePosition},
defs::Definition,
helpers::pick_best_token,
RootDatabase,
};
use itertools::Itertools;
use syntax::{AstNode, SyntaxKind::*, T};
use crate::{doc_links::token_as_doc_comment, RangeInfo};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MonikerIdentifier {
crate_name: String,
path: Vec<Name>,
}
impl ToString for MonikerIdentifier {
fn to_string(&self) -> String {
match self {
MonikerIdentifier { path, crate_name } => {
format!("{}::{}", crate_name, path.iter().map(|x| x.to_string()).join("::"))
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum MonikerKind {
Import,
Export,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MonikerResult {
pub identifier: MonikerIdentifier,
pub kind: MonikerKind,
pub package_information: PackageInformation,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PackageInformation {
pub name: String,
pub repo: String,
pub version: String,
}
pub(crate) fn crate_for_file(db: &RootDatabase, file_id: FileId) -> Option<Crate> {
for &krate in db.relevant_crates(file_id).iter() {
let crate_def_map = db.crate_def_map(krate);
for (_, data) in crate_def_map.modules() {
if data.origin.file_id() == Some(file_id) {
return Some(krate.into());
}
}
}
None
}
pub(crate) fn moniker(
db: &RootDatabase,
FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<MonikerResult>>> {
let sema = &Semantics::new(db);
let file = sema.parse(file_id).syntax().clone();
let current_crate = crate_for_file(db, file_id)?;
let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] | COMMENT => 2,
kind if kind.is_trivia() => 0,
_ => 1,
})?;
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, _| {
let m = def_to_moniker(db, def, current_crate)?;
Some(RangeInfo::new(original_token.text_range(), vec![m]))
});
}
let navs = sema
.descend_into_macros(original_token.clone())
.into_iter()
.map(|token| {
Definition::from_token(sema, &token)
.into_iter()
.flat_map(|def| def_to_moniker(sema.db, def, current_crate))
.collect::<Vec<_>>()
})
.flatten()
.unique()
.collect::<Vec<_>>();
Some(RangeInfo::new(original_token.text_range(), navs))
}
pub(crate) fn def_to_moniker(
db: &RootDatabase,
def: Definition,
from_crate: Crate,
) -> Option<MonikerResult> {
if matches!(def, Definition::GenericParam(_) | Definition::SelfType(_) | Definition::Local(_)) {
return None;
}
let module = def.module(db)?;
let krate = module.krate();
let mut path = vec![];
path.extend(module.path_to_root(db).into_iter().filter_map(|x| x.name(db)));
if let Definition::Field(it) = def {
path.push(it.parent_def(db).name(db));
}
path.push(def.name(db)?);
Some(MonikerResult {
identifier: MonikerIdentifier {
crate_name: krate.display_name(db)?.crate_name().to_string(),
path,
},
kind: if krate == from_crate { MonikerKind::Export } else { MonikerKind::Import },
package_information: {
let name = krate.display_name(db)?.to_string();
let (repo, version) = match krate.origin(db) {
CrateOrigin::CratesIo { repo } => (repo?, krate.version(db)?),
CrateOrigin::Lang => (
"https://github.com/rust-lang/rust/".to_string(),
"compiler_version".to_string(),
),
CrateOrigin::Unknown => return None,
};
PackageInformation { name, repo, version }
},
})
}
#[cfg(test)]
mod tests {
use crate::fixture;
use super::MonikerKind;
#[track_caller]
fn no_moniker(ra_fixture: &str) {
let (analysis, position) = fixture::position(ra_fixture);
if let Some(x) = analysis.moniker(position).unwrap() {
assert_eq!(x.info.len(), 0, "Moniker founded but no moniker expected: {:?}", x);
}
}
#[track_caller]
fn check_moniker(ra_fixture: &str, identifier: &str, package: &str, kind: MonikerKind) {
let (analysis, position) = fixture::position(ra_fixture);
let x = analysis.moniker(position).unwrap().expect("no moniker found").info;
assert_eq!(x.len(), 1);
let x = x.into_iter().next().unwrap();
assert_eq!(identifier, x.identifier.to_string());
assert_eq!(package, format!("{:?}", x.package_information));
assert_eq!(kind, x.kind);
}
#[test]
fn basic() {
check_moniker(
r#"
//- /lib.rs crate:main deps:foo
use foo::module::func;
fn main() {
func$0();
}
//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
pub mod module {
pub fn func() {}
}
"#,
"foo::module::func",
r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
MonikerKind::Import,
);
check_moniker(
r#"
//- /lib.rs crate:main deps:foo
use foo::module::func;
fn main() {
func();
}
//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
pub mod module {
pub fn func$0() {}
}
"#,
"foo::module::func",
r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
MonikerKind::Export,
);
}
#[test]
fn moniker_for_field() {
check_moniker(
r#"
//- /lib.rs crate:main deps:foo
use foo::St;
fn main() {
let x = St { a$0: 2 };
}
//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
pub struct St {
pub a: i32,
}
"#,
"foo::St::a",
r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#,
MonikerKind::Import,
);
}
#[test]
fn no_moniker_for_local() {
no_moniker(
r#"
//- /lib.rs crate:main deps:foo
use foo::module::func;
fn main() {
func();
}
//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
pub mod module {
pub fn func() {
let x$0 = 2;
}
}
"#,
);
}
}

View File

@ -12,6 +12,7 @@
use rustc_hash::FxHashSet;
use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
use crate::moniker::{crate_for_file, def_to_moniker, MonikerResult};
use crate::{
hover::hover_for_definition, Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult,
InlayHint, InlayHintsConfig, TryToNav,
@ -40,6 +41,7 @@ pub struct TokenStaticData {
pub hover: Option<HoverResult>,
pub definition: Option<FileRange>,
pub references: Vec<ReferenceData>,
pub moniker: Option<MonikerResult>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -97,6 +99,7 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
impl StaticIndex<'_> {
fn add_file(&mut self, file_id: FileId) {
let current_crate = crate_for_file(self.db, file_id);
let folds = self.analysis.folding_ranges(file_id).unwrap();
let inlay_hints = self
.analysis
@ -143,6 +146,7 @@ fn add_file(&mut self, file_id: FileId) {
.try_to_nav(self.db)
.map(|x| FileRange { file_id: x.file_id, range: x.focus_or_full_range() }),
references: vec![],
moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
});
self.def_map.insert(def, x);
x
@ -206,6 +210,7 @@ mod tests {
use crate::{fixture, StaticIndex};
use ide_db::base_db::FileRange;
use std::collections::HashSet;
use syntax::TextSize;
fn check_all_ranges(ra_fixture: &str) {
let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
@ -231,6 +236,10 @@ fn check_definitions(ra_fixture: &str) {
let mut range_set: HashSet<_> = ranges.iter().map(|x| x.0).collect();
for (_, t) in s.tokens.iter() {
if let Some(x) = t.definition {
if x.range.start() == TextSize::from(0) {
// ignore definitions that are whole of file
continue;
}
if !range_set.contains(&x) {
panic!("additional definition {:?}", x);
}
@ -262,6 +271,28 @@ enum E { X(Foo) }
);
}
#[test]
fn multi_crate() {
check_definitions(
r#"
//- /main.rs crate:main deps:foo
use foo::func;
fn main() {
//^^^^
func();
}
//- /foo/lib.rs crate:foo
pub func() {
}
"#,
);
}
#[test]
fn derives() {
check_all_ranges(

View File

@ -130,6 +130,8 @@ pub struct PackageData {
pub version: semver::Version,
/// Name as given in the `Cargo.toml`
pub name: String,
/// Repository as given in the `Cargo.toml`
pub repository: Option<String>,
/// Path containing the `Cargo.toml`
pub manifest: ManifestPath,
/// Targets provided by the crate (lib, bin, example, test, ...)
@ -146,9 +148,9 @@ pub struct PackageData {
pub features: FxHashMap<String, Vec<String>>,
/// List of features enabled on this package
pub active_features: Vec<String>,
// String representation of package id
/// String representation of package id
pub id: String,
// The contents of [package.metadata.rust-analyzer]
/// The contents of [package.metadata.rust-analyzer]
pub metadata: RustAnalyzerPackageMetaData,
}
@ -302,7 +304,14 @@ pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
for meta_pkg in &meta.packages {
let cargo_metadata::Package {
id, edition, name, manifest_path, version, metadata, ..
id,
edition,
name,
manifest_path,
version,
metadata,
repository,
..
} = meta_pkg;
let meta = from_value::<PackageMetadata>(metadata.clone()).unwrap_or_default();
let edition = edition.parse::<Edition>().unwrap_or_else(|err| {
@ -323,6 +332,7 @@ pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
is_local,
is_member,
edition,
repository: repository.clone(),
dependencies: Vec::new(),
features: meta_pkg.features.clone().into_iter().collect(),
active_features: Vec::new(),

View File

@ -39,6 +39,7 @@ pub struct Crate {
pub(crate) include: Vec<AbsPathBuf>,
pub(crate) exclude: Vec<AbsPathBuf>,
pub(crate) is_proc_macro: bool,
pub(crate) repository: Option<String>,
}
impl ProjectJson {
@ -99,6 +100,7 @@ pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
include,
exclude,
is_proc_macro: crate_data.is_proc_macro,
repository: crate_data.repository,
}
})
.collect::<Vec<_>>(),
@ -142,6 +144,8 @@ struct CrateData {
source: Option<CrateSource>,
#[serde(default)]
is_proc_macro: bool,
#[serde(default)]
repository: Option<String>,
}
#[derive(Deserialize, Debug, Clone)]

View File

@ -173,6 +173,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
5,
@ -242,6 +245,11 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
2,
@ -311,6 +319,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
4,
@ -370,6 +381,11 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
1,
@ -439,6 +455,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
6,
@ -498,6 +517,11 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
3,
@ -567,6 +591,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
},
}"#]],
@ -651,6 +678,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
5,
@ -720,6 +750,11 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
2,
@ -791,6 +826,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
4,
@ -850,6 +888,11 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
1,
@ -921,6 +964,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
6,
@ -980,6 +1026,11 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
3,
@ -1051,6 +1102,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
},
}"#]],
@ -1126,6 +1180,9 @@ fn cargo_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
5,
@ -1197,6 +1254,11 @@ fn cargo_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
2,
@ -1268,6 +1330,9 @@ fn cargo_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
4,
@ -1329,6 +1394,11 @@ fn cargo_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
1,
@ -1400,6 +1470,9 @@ fn cargo_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
6,
@ -1461,6 +1534,11 @@ fn cargo_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: CratesIo {
repo: Some(
"https://github.com/rust-lang/libc",
),
},
},
CrateId(
3,
@ -1532,6 +1610,9 @@ fn cargo_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
},
}"#]],
@ -1583,6 +1664,7 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
},
CrateId(
10,
@ -1611,6 +1693,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
7,
@ -1639,6 +1722,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
4,
@ -1677,6 +1761,7 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
},
CrateId(
1,
@ -1705,6 +1790,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
11,
@ -1770,6 +1856,9 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: CratesIo {
repo: None,
},
},
CrateId(
8,
@ -1798,6 +1887,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
5,
@ -1826,6 +1916,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
2,
@ -1854,6 +1945,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
9,
@ -1882,6 +1974,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
CrateId(
6,
@ -1992,6 +2085,7 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
},
CrateId(
3,
@ -2020,6 +2114,7 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
},
},
}"#]],

View File

@ -6,7 +6,8 @@
use anyhow::{format_err, Context, Result};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacro,
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
FileId, ProcMacro,
};
use cfg::{CfgDiff, CfgOptions};
use paths::{AbsPath, AbsPathBuf};
@ -473,6 +474,11 @@ fn project_json_to_crate_graph(
cfg_options,
env,
proc_macro.unwrap_or_default(),
if krate.display_name.is_some() {
CrateOrigin::CratesIo { repo: krate.repository.clone() }
} else {
CrateOrigin::Unknown
},
),
)
})
@ -681,6 +687,7 @@ fn detached_files_to_crate_graph(
cfg_options.clone(),
Env::default(),
Vec::new(),
CrateOrigin::Unknown,
);
public_deps.add(detached_file_crate, &mut crate_graph);
@ -821,7 +828,6 @@ fn add_target_crate_root(
.iter()
.map(|feat| CfgFlag::KeyValue { key: "feature".into(), value: feat.0.into() }),
);
crate_graph.add_crate_root(
file_id,
edition,
@ -831,6 +837,7 @@ fn add_target_crate_root(
potential_cfg_options,
env,
proc_macro,
CrateOrigin::CratesIo { repo: pkg.repository.clone() },
)
}
@ -874,6 +881,7 @@ fn sysroot_to_crate_graph(
cfg_options.clone(),
env,
proc_macro,
CrateOrigin::Lang,
);
Some((krate, crate_id))
})

View File

@ -5,8 +5,8 @@
use std::time::Instant;
use ide::{
Analysis, FileId, FileRange, RootDatabase, StaticIndex, StaticIndexedFile, TokenId,
TokenStaticData,
Analysis, FileId, FileRange, MonikerKind, PackageInformation, RootDatabase, StaticIndex,
StaticIndexedFile, TokenId, TokenStaticData,
};
use ide_db::LineIndexDatabase;
@ -36,6 +36,7 @@ struct LsifManager<'a> {
token_map: HashMap<TokenId, Id>,
range_map: HashMap<FileRange, Id>,
file_map: HashMap<FileId, Id>,
package_map: HashMap<PackageInformation, Id>,
analysis: &'a Analysis,
db: &'a RootDatabase,
vfs: &'a Vfs,
@ -57,6 +58,7 @@ fn new<'a>(analysis: &'a Analysis, db: &'a RootDatabase, vfs: &'a Vfs) -> LsifMa
token_map: HashMap::default(),
range_map: HashMap::default(),
file_map: HashMap::default(),
package_map: HashMap::default(),
analysis,
db,
vfs,
@ -92,6 +94,28 @@ fn get_token_id(&mut self, id: TokenId) -> Id {
result_set_id
}
fn get_package_id(&mut self, package_information: PackageInformation) -> Id {
if let Some(x) = self.package_map.get(&package_information) {
return *x;
}
let pi = package_information.clone();
let result_set_id =
self.add_vertex(lsif::Vertex::PackageInformation(lsif::PackageInformation {
name: pi.name,
manager: "cargo".to_string(),
uri: None,
content: None,
repository: Some(lsif::Repository {
url: pi.repo,
r#type: "git".to_string(),
commit_id: None,
}),
version: Some(pi.version),
}));
self.package_map.insert(package_information, result_set_id);
result_set_id
}
fn get_range_id(&mut self, id: FileRange) -> Id {
if let Some(x) = self.range_map.get(&id) {
return *x;
@ -146,6 +170,26 @@ fn add_token(&mut self, id: TokenId, token: TokenStaticData) {
out_v: result_set_id.into(),
}));
}
if let Some(moniker) = token.moniker {
let package_id = self.get_package_id(moniker.package_information);
let moniker_id = self.add_vertex(lsif::Vertex::Moniker(lsp_types::Moniker {
scheme: "rust-analyzer".to_string(),
identifier: moniker.identifier.to_string(),
unique: lsp_types::UniquenessLevel::Scheme,
kind: Some(match moniker.kind {
MonikerKind::Import => lsp_types::MonikerKind::Import,
MonikerKind::Export => lsp_types::MonikerKind::Export,
}),
}));
self.add_edge(lsif::Edge::PackageInformation(lsif::EdgeData {
in_v: package_id.into(),
out_v: moniker_id.into(),
}));
self.add_edge(lsif::Edge::Moniker(lsif::EdgeData {
in_v: moniker_id.into(),
out_v: result_set_id.into(),
}));
}
if let Some(def) = token.definition {
let result_id = self.add_vertex(lsif::Vertex::DefinitionResult);
let def_vertex = self.get_range_id(def);