Auto merge of #15528 - Veykril:r-a-cfg, r=Veykril
Enable `rust_analyzer` for cfgs when code is being analyzed by rust-analyzer This allows one to have r-a skip analysis/replace macros that work not well with r-a at all by gating them behind this cfg (an example being the `quote` macro which r-a struggles with in terms of performance).
This commit is contained in:
commit
347695abc8
10 changed files with 170 additions and 59 deletions
|
|
@ -179,8 +179,8 @@ impl ChangeFixture {
|
|||
meta.edition,
|
||||
Some(crate_name.clone().into()),
|
||||
version,
|
||||
meta.cfg,
|
||||
Default::default(),
|
||||
meta.cfg.clone(),
|
||||
Some(meta.cfg),
|
||||
meta.env,
|
||||
false,
|
||||
origin,
|
||||
|
|
@ -200,7 +200,7 @@ impl ChangeFixture {
|
|||
} else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
|
||||
assert!(default_crate_root.is_none());
|
||||
default_crate_root = Some(file_id);
|
||||
default_cfg = meta.cfg;
|
||||
default_cfg.extend(meta.cfg.into_iter());
|
||||
default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
|
||||
default_target_data_layout = meta.target_data_layout;
|
||||
}
|
||||
|
|
@ -220,8 +220,8 @@ impl ChangeFixture {
|
|||
Edition::CURRENT,
|
||||
Some(CrateName::new("test").unwrap().into()),
|
||||
None,
|
||||
default_cfg,
|
||||
Default::default(),
|
||||
default_cfg.clone(),
|
||||
Some(default_cfg),
|
||||
default_env,
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
|
|
|
|||
|
|
@ -86,6 +86,32 @@ impl CfgOptions {
|
|||
}
|
||||
}
|
||||
|
||||
impl Extend<CfgAtom> for CfgOptions {
|
||||
fn extend<T: IntoIterator<Item = CfgAtom>>(&mut self, iter: T) {
|
||||
iter.into_iter().for_each(|cfg_flag| _ = self.enabled.insert(cfg_flag));
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for CfgOptions {
|
||||
type Item = <FxHashSet<CfgAtom> as IntoIterator>::Item;
|
||||
|
||||
type IntoIter = <FxHashSet<CfgAtom> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
<FxHashSet<CfgAtom> as IntoIterator>::into_iter(self.enabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a CfgOptions {
|
||||
type Item = <&'a FxHashSet<CfgAtom> as IntoIterator>::Item;
|
||||
|
||||
type IntoIter = <&'a FxHashSet<CfgAtom> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
<&FxHashSet<CfgAtom> as IntoIterator>::into_iter(&self.enabled)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CfgDiff {
|
||||
// Invariants: No duplicates, no atom that's both in `enable` and `disable`.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
//! Completion for cfg
|
||||
|
||||
use std::iter;
|
||||
|
||||
use ide_db::SymbolKind;
|
||||
use itertools::Itertools;
|
||||
use syntax::SyntaxKind;
|
||||
use syntax::{algo, ast::Ident, AstToken, Direction, NodeOrToken, SyntaxKind};
|
||||
|
||||
use crate::{completions::Completions, context::CompletionContext, CompletionItem};
|
||||
|
||||
|
|
@ -15,31 +13,44 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
|
|||
acc.add(completion.build(ctx.db));
|
||||
};
|
||||
|
||||
let previous = iter::successors(ctx.original_token.prev_token(), |t| {
|
||||
(matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia())
|
||||
.then(|| t.prev_token())
|
||||
.flatten()
|
||||
})
|
||||
.find(|t| matches!(t.kind(), SyntaxKind::IDENT));
|
||||
// FIXME: Move this into context/analysis.rs
|
||||
let previous = ctx
|
||||
.original_token
|
||||
.prev_token()
|
||||
.and_then(|it| {
|
||||
if matches!(it.kind(), SyntaxKind::EQ) {
|
||||
Some(it.into())
|
||||
} else {
|
||||
algo::non_trivia_sibling(it.into(), Direction::Prev)
|
||||
}
|
||||
})
|
||||
.filter(|t| matches!(t.kind(), SyntaxKind::EQ))
|
||||
.and_then(|it| algo::non_trivia_sibling(it.prev_sibling_or_token()?, Direction::Prev))
|
||||
.map(|it| match it {
|
||||
NodeOrToken::Node(_) => None,
|
||||
NodeOrToken::Token(t) => Ident::cast(t),
|
||||
});
|
||||
match previous {
|
||||
Some(None) => (),
|
||||
Some(Some(p)) => match p.text() {
|
||||
"target_arch" => KNOWN_ARCH.iter().copied().for_each(add_completion),
|
||||
"target_env" => KNOWN_ENV.iter().copied().for_each(add_completion),
|
||||
"target_os" => KNOWN_OS.iter().copied().for_each(add_completion),
|
||||
"target_vendor" => KNOWN_VENDOR.iter().copied().for_each(add_completion),
|
||||
"target_endian" => ["little", "big"].into_iter().for_each(add_completion),
|
||||
name => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
|
||||
let insert_text = format!(r#""{s}""#);
|
||||
let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
|
||||
item.insert_text(insert_text);
|
||||
|
||||
match previous.as_ref().map(|p| p.text()) {
|
||||
Some("target_arch") => KNOWN_ARCH.iter().copied().for_each(add_completion),
|
||||
Some("target_env") => KNOWN_ENV.iter().copied().for_each(add_completion),
|
||||
Some("target_os") => KNOWN_OS.iter().copied().for_each(add_completion),
|
||||
Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion),
|
||||
Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
|
||||
Some(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
|
||||
let insert_text = format!(r#""{s}""#);
|
||||
let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
|
||||
item.insert_text(insert_text);
|
||||
|
||||
acc.add(item.build(ctx.db));
|
||||
}),
|
||||
acc.add(item.build(ctx.db));
|
||||
}),
|
||||
},
|
||||
None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().unique().for_each(|s| {
|
||||
let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
|
||||
acc.add(item.build(ctx.db));
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const KNOWN_ARCH: [&str; 20] = [
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ struct Foo;
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inside_nested_attr() {
|
||||
check(r#"#[cfg($0)]"#, expect![[]])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn with_existing_attr() {
|
||||
check(
|
||||
|
|
@ -635,6 +630,32 @@ struct Foo;
|
|||
mod cfg {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn inside_cfg() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs cfg:test,dbg=false,opt_level=2
|
||||
#[cfg($0)]
|
||||
"#,
|
||||
expect![[r#"
|
||||
ba dbg
|
||||
ba opt_level
|
||||
ba test
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs cfg:test,dbg=false,opt_level=2
|
||||
#[cfg(b$0)]
|
||||
"#,
|
||||
expect![[r#"
|
||||
ba dbg
|
||||
ba opt_level
|
||||
ba test
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cfg_target_endian() {
|
||||
check(
|
||||
|
|
@ -644,6 +665,13 @@ mod cfg {
|
|||
ba little
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"#[cfg(target_endian = b$0"#,
|
||||
expect![[r#"
|
||||
ba big
|
||||
ba little
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,6 @@ impl Definition {
|
|||
}
|
||||
|
||||
// def is crate root
|
||||
// FIXME: We don't do searches for crates currently, as a crate does not actually have a single name
|
||||
if let &Definition::Module(module) = self {
|
||||
if module.is_crate_root() {
|
||||
return SearchScope::reverse_dependencies(db, module.krate());
|
||||
|
|
@ -393,7 +392,10 @@ impl<'a> FindUsages<'a> {
|
|||
let name = match self.def {
|
||||
// special case crate modules as these do not have a proper name
|
||||
Definition::Module(module) if module.is_crate_root() => {
|
||||
// FIXME: This assumes the crate name is always equal to its display name when it really isn't
|
||||
// FIXME: This assumes the crate name is always equal to its display name when it
|
||||
// really isn't
|
||||
// we should instead look at the dependency edge name and recursively search our way
|
||||
// up the ancestors
|
||||
module
|
||||
.krate()
|
||||
.display_name(self.sema.db)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//! metadata` or `rust-project.json`) into representation stored in the salsa
|
||||
//! database -- `CrateGraph`.
|
||||
|
||||
use std::{collections::VecDeque, fmt, fs, process::Command, str::FromStr, sync};
|
||||
use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, sync};
|
||||
|
||||
use anyhow::{format_err, Context};
|
||||
use base_db::{
|
||||
|
|
@ -730,6 +730,7 @@ fn project_json_to_crate_graph(
|
|||
)
|
||||
});
|
||||
|
||||
let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
|
||||
let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
|
||||
let crates: FxHashMap<CrateId, CrateId> = project
|
||||
.crates()
|
||||
|
|
@ -765,7 +766,12 @@ fn project_json_to_crate_graph(
|
|||
*edition,
|
||||
display_name.clone(),
|
||||
version.clone(),
|
||||
target_cfgs.iter().chain(cfg.iter()).cloned().collect(),
|
||||
target_cfgs
|
||||
.iter()
|
||||
.chain(cfg.iter())
|
||||
.chain(iter::once(&r_a_cfg_flag))
|
||||
.cloned()
|
||||
.collect(),
|
||||
None,
|
||||
env,
|
||||
*is_proc_macro,
|
||||
|
|
@ -820,7 +826,7 @@ fn cargo_to_crate_graph(
|
|||
sysroot: Option<&Sysroot>,
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
override_cfg: &CfgOverrides,
|
||||
// Don't compute cfg and use this if present
|
||||
// Don't compute cfg and use this if present, only used for the sysroot experiment hack
|
||||
forced_cfg: Option<CfgOptions>,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
|
|
@ -842,12 +848,7 @@ fn cargo_to_crate_graph(
|
|||
None => (SysrootPublicDeps::default(), None),
|
||||
};
|
||||
|
||||
let cfg_options = {
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg);
|
||||
cfg_options.insert_atom("debug_assertions".into());
|
||||
cfg_options
|
||||
};
|
||||
let cfg_options = create_cfg_options(rustc_cfg);
|
||||
|
||||
// Mapping of a package to its library target
|
||||
let mut pkg_to_lib_crate = FxHashMap::default();
|
||||
|
|
@ -866,6 +867,9 @@ fn cargo_to_crate_graph(
|
|||
if cargo[pkg].is_local {
|
||||
cfg_options.insert_atom("test".into());
|
||||
}
|
||||
if cargo[pkg].is_member {
|
||||
cfg_options.insert_atom("rust_analyzer".into());
|
||||
}
|
||||
|
||||
if !override_cfg.global.is_empty() {
|
||||
cfg_options.apply_diff(override_cfg.global.clone());
|
||||
|
|
@ -1029,8 +1033,8 @@ fn detached_files_to_crate_graph(
|
|||
None => (SysrootPublicDeps::default(), None),
|
||||
};
|
||||
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg);
|
||||
let mut cfg_options = create_cfg_options(rustc_cfg);
|
||||
cfg_options.insert_atom("rust_analyzer".into());
|
||||
|
||||
for detached_file in detached_files {
|
||||
let file_id = match load(detached_file) {
|
||||
|
|
@ -1295,8 +1299,7 @@ fn sysroot_to_crate_graph(
|
|||
channel: Option<ReleaseChannel>,
|
||||
) -> (SysrootPublicDeps, Option<CrateId>) {
|
||||
let _p = profile::span("sysroot_to_crate_graph");
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg.clone());
|
||||
let cfg_options = create_cfg_options(rustc_cfg.clone());
|
||||
let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = match &sysroot.hack_cargo_workspace {
|
||||
Some(cargo) => handle_hack_cargo_workspace(
|
||||
load,
|
||||
|
|
@ -1475,3 +1478,10 @@ fn inject_cargo_env(package: &PackageData, env: &mut Env) {
|
|||
|
||||
env.set("CARGO_PKG_LICENSE_FILE", String::new());
|
||||
}
|
||||
|
||||
fn create_cfg_options(rustc_cfg: Vec<CfgFlag>) -> CfgOptions {
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg);
|
||||
cfg_options.insert_atom("debug_assertions".into());
|
||||
cfg_options
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -81,6 +82,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -151,6 +153,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -221,6 +224,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -81,6 +82,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -151,6 +153,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
@ -221,6 +224,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
"test",
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
|
|
@ -80,6 +81,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
|
|
@ -149,6 +151,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
|
|
@ -218,6 +221,7 @@
|
|||
cfg_options: CfgOptions(
|
||||
[
|
||||
"debug_assertions",
|
||||
"rust_analyzer",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -53,7 +55,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -84,7 +88,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -115,7 +121,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -146,7 +154,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -192,7 +202,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -223,7 +235,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -311,7 +325,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -342,7 +358,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -373,7 +391,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"debug_assertions",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
@ -404,7 +424,9 @@
|
|||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
[
|
||||
"rust_analyzer",
|
||||
],
|
||||
),
|
||||
potential_cfg_options: None,
|
||||
env: Env {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue