Skip to content

Commit b2bf37c

Browse files
committed
Auto merge of rust-lang#12976 - tjdevries:scip, r=Veykril
feat: emit SCIP from rust-analyzer hi rust-analyzer team I'm one of the engineers at Sourcegraph (and have done a few small changes related to the LSIF work done in rust-analyzer). Recently, we've moved to a new protocol as the primary way to interact with Sourcegraph (LSIF is still possible to upload, so existing jobs will not stop working any time soon). This new protocol is SCIP (I linked a blog post below with more information). I've implemented SCIP support (based largely on the existing LSIF support). In addition to supporting the existing features that `rust-analyzer`'s LSIF support does, this PR adds the ability to move between crates on sourcegraph.com. So if both your project and a dependency are indexed, you would be able to hop to the particular version and view the source code. I'd be happy to record a demo of that on my local instance if you're interested. There are a few TODO's left in the code (some that you might have insights on) which I'm happy to fix in this PR, but I just wanted to open this up for discussion first. Thanks for your time :) TJ - [announcing scip](https://about.sourcegraph.com/blog/announcing-scip)
2 parents 6711ded + 50ecb09 commit b2bf37c

File tree

8 files changed

+630
-14
lines changed

8 files changed

+630
-14
lines changed

Cargo.lock

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ide/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub use crate::{
8787
},
8888
join_lines::JoinLinesConfig,
8989
markup::Markup,
90-
moniker::{MonikerKind, MonikerResult, PackageInformation},
90+
moniker::{MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation},
9191
move_item::Direction,
9292
navigation_target::NavigationTarget,
9393
prime_caches::ParallelPrimeCachesProgress,

crates/ide/src/moniker.rs

Lines changed: 118 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,39 @@ use syntax::{AstNode, SyntaxKind::*, T};
1313

1414
use crate::{doc_links::token_as_doc_comment, RangeInfo};
1515

16+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17+
pub enum MonikerDescriptorKind {
18+
Namespace,
19+
Type,
20+
Term,
21+
Method,
22+
TypeParameter,
23+
Parameter,
24+
Macro,
25+
Meta,
26+
}
27+
28+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29+
pub struct MonikerDescriptor {
30+
pub name: Name,
31+
pub desc: MonikerDescriptorKind,
32+
}
33+
1634
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1735
pub struct MonikerIdentifier {
18-
crate_name: String,
19-
path: Vec<Name>,
36+
pub crate_name: String,
37+
pub description: Vec<MonikerDescriptor>,
2038
}
2139

2240
impl ToString for MonikerIdentifier {
2341
fn to_string(&self) -> String {
2442
match self {
25-
MonikerIdentifier { path, crate_name } => {
26-
format!("{}::{}", crate_name, path.iter().map(|x| x.to_string()).join("::"))
43+
MonikerIdentifier { description, crate_name } => {
44+
format!(
45+
"{}::{}",
46+
crate_name,
47+
description.iter().map(|x| x.name.to_string()).join("::")
48+
)
2749
}
2850
}
2951
}
@@ -42,6 +64,12 @@ pub struct MonikerResult {
4264
pub package_information: PackageInformation,
4365
}
4466

67+
impl MonikerResult {
68+
pub fn from_def(db: &RootDatabase, def: Definition, from_crate: Crate) -> Option<Self> {
69+
def_to_moniker(db, def, from_crate)
70+
}
71+
}
72+
4573
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4674
pub struct PackageInformation {
4775
pub name: String,
@@ -105,13 +133,23 @@ pub(crate) fn def_to_moniker(
105133
def: Definition,
106134
from_crate: Crate,
107135
) -> Option<MonikerResult> {
108-
if matches!(def, Definition::GenericParam(_) | Definition::SelfType(_) | Definition::Local(_)) {
136+
if matches!(
137+
def,
138+
Definition::GenericParam(_)
139+
| Definition::Label(_)
140+
| Definition::DeriveHelper(_)
141+
| Definition::BuiltinAttr(_)
142+
| Definition::ToolModule(_)
143+
) {
109144
return None;
110145
}
146+
111147
let module = def.module(db)?;
112148
let krate = module.krate();
113-
let mut path = vec![];
114-
path.extend(module.path_to_root(db).into_iter().filter_map(|x| x.name(db)));
149+
let mut description = vec![];
150+
description.extend(module.path_to_root(db).into_iter().filter_map(|x| {
151+
Some(MonikerDescriptor { name: x.name(db)?, desc: MonikerDescriptorKind::Namespace })
152+
}));
115153

116154
// Handle associated items within a trait
117155
if let Some(assoc) = def.as_assoc_item(db) {
@@ -120,31 +158,98 @@ pub(crate) fn def_to_moniker(
120158
AssocItemContainer::Trait(trait_) => {
121159
// Because different traits can have functions with the same name,
122160
// we have to include the trait name as part of the moniker for uniqueness.
123-
path.push(trait_.name(db));
161+
description.push(MonikerDescriptor {
162+
name: trait_.name(db),
163+
desc: MonikerDescriptorKind::Type,
164+
});
124165
}
125166
AssocItemContainer::Impl(impl_) => {
126167
// Because a struct can implement multiple traits, for implementations
127168
// we add both the struct name and the trait name to the path
128169
if let Some(adt) = impl_.self_ty(db).as_adt() {
129-
path.push(adt.name(db));
170+
description.push(MonikerDescriptor {
171+
name: adt.name(db),
172+
desc: MonikerDescriptorKind::Type,
173+
});
130174
}
131175

132176
if let Some(trait_) = impl_.trait_(db) {
133-
path.push(trait_.name(db));
177+
description.push(MonikerDescriptor {
178+
name: trait_.name(db),
179+
desc: MonikerDescriptorKind::Type,
180+
});
134181
}
135182
}
136183
}
137184
}
138185

139186
if let Definition::Field(it) = def {
140-
path.push(it.parent_def(db).name(db));
187+
description.push(MonikerDescriptor {
188+
name: it.parent_def(db).name(db),
189+
desc: MonikerDescriptorKind::Type,
190+
});
141191
}
142192

143-
path.push(def.name(db)?);
193+
let name_desc = match def {
194+
// These are handled by top-level guard (for performance).
195+
Definition::GenericParam(_)
196+
| Definition::Label(_)
197+
| Definition::DeriveHelper(_)
198+
| Definition::BuiltinAttr(_)
199+
| Definition::ToolModule(_) => return None,
200+
201+
Definition::Local(local) => {
202+
if !local.is_param(db) {
203+
return None;
204+
}
205+
206+
MonikerDescriptor { name: local.name(db), desc: MonikerDescriptorKind::Parameter }
207+
}
208+
Definition::Macro(m) => {
209+
MonikerDescriptor { name: m.name(db), desc: MonikerDescriptorKind::Macro }
210+
}
211+
Definition::Function(f) => {
212+
MonikerDescriptor { name: f.name(db), desc: MonikerDescriptorKind::Method }
213+
}
214+
Definition::Variant(v) => {
215+
MonikerDescriptor { name: v.name(db), desc: MonikerDescriptorKind::Type }
216+
}
217+
Definition::Const(c) => {
218+
MonikerDescriptor { name: c.name(db)?, desc: MonikerDescriptorKind::Term }
219+
}
220+
Definition::Trait(trait_) => {
221+
MonikerDescriptor { name: trait_.name(db), desc: MonikerDescriptorKind::Type }
222+
}
223+
Definition::TypeAlias(ta) => {
224+
MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::TypeParameter }
225+
}
226+
Definition::Module(m) => {
227+
MonikerDescriptor { name: m.name(db)?, desc: MonikerDescriptorKind::Namespace }
228+
}
229+
Definition::BuiltinType(b) => {
230+
MonikerDescriptor { name: b.name(), desc: MonikerDescriptorKind::Type }
231+
}
232+
Definition::SelfType(imp) => MonikerDescriptor {
233+
name: imp.self_ty(db).as_adt()?.name(db),
234+
desc: MonikerDescriptorKind::Type,
235+
},
236+
Definition::Field(it) => {
237+
MonikerDescriptor { name: it.name(db), desc: MonikerDescriptorKind::Term }
238+
}
239+
Definition::Adt(adt) => {
240+
MonikerDescriptor { name: adt.name(db), desc: MonikerDescriptorKind::Type }
241+
}
242+
Definition::Static(s) => {
243+
MonikerDescriptor { name: s.name(db), desc: MonikerDescriptorKind::Meta }
244+
}
245+
};
246+
247+
description.push(name_desc);
248+
144249
Some(MonikerResult {
145250
identifier: MonikerIdentifier {
146251
crate_name: krate.display_name(db)?.crate_name().to_string(),
147-
path,
252+
description,
148253
},
149254
kind: if krate == from_crate { MonikerKind::Export } else { MonikerKind::Import },
150255
package_information: {

crates/rust-analyzer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ crossbeam-channel = "0.5.5"
2323
dissimilar = "1.0.4"
2424
itertools = "0.10.3"
2525
lsp-types = { version = "0.93.0", features = ["proposed"] }
26+
scip = "0.1.1"
2627
parking_lot = "0.12.1"
2728
xflags = "0.2.4"
2829
oorandom = "11.1.3"

crates/rust-analyzer/src/bin/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn try_main() -> Result<()> {
9393
flags::RustAnalyzerCmd::Ssr(cmd) => cmd.run()?,
9494
flags::RustAnalyzerCmd::Search(cmd) => cmd.run()?,
9595
flags::RustAnalyzerCmd::Lsif(cmd) => cmd.run()?,
96+
flags::RustAnalyzerCmd::Scip(cmd) => cmd.run()?,
9697
}
9798
Ok(())
9899
}

crates/rust-analyzer/src/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod analysis_stats;
99
mod diagnostics;
1010
mod ssr;
1111
mod lsif;
12+
mod scip;
1213

1314
mod progress_report;
1415

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ xflags::xflags! {
112112
cmd lsif
113113
required path: PathBuf
114114
{}
115+
116+
cmd scip
117+
required path: PathBuf
118+
{}
115119
}
116120
}
117121

@@ -140,6 +144,7 @@ pub enum RustAnalyzerCmd {
140144
Search(Search),
141145
ProcMacro(ProcMacro),
142146
Lsif(Lsif),
147+
Scip(Scip),
143148
}
144149

145150
#[derive(Debug)]
@@ -207,6 +212,11 @@ pub struct Lsif {
207212
pub path: PathBuf,
208213
}
209214

215+
#[derive(Debug)]
216+
pub struct Scip {
217+
pub path: PathBuf,
218+
}
219+
210220
impl RustAnalyzer {
211221
pub const HELP: &'static str = Self::HELP_;
212222

0 commit comments

Comments
 (0)