Merge #9080
9080: Improve completion of cfg attributes r=JamieCunliffe a=JamieCunliffe This will close #5398 and it also adds some completion for cfg options. Co-authored-by: Jamie Cunliffe <Jamie.Cunliffe@outlook.com>
This commit is contained in:
commit
f06ddbea6a
@ -128,6 +128,7 @@ impl ChangeFixture {
|
||||
file_id,
|
||||
meta.edition,
|
||||
Some(crate_name.clone().into()),
|
||||
meta.cfg.clone(),
|
||||
meta.cfg,
|
||||
meta.env,
|
||||
Default::default(),
|
||||
@ -157,6 +158,7 @@ impl ChangeFixture {
|
||||
crate_root,
|
||||
Edition::Edition2018,
|
||||
Some(CrateName::new("test").unwrap().into()),
|
||||
default_cfg.clone(),
|
||||
default_cfg,
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
@ -186,6 +188,7 @@ impl ChangeFixture {
|
||||
Edition::Edition2021,
|
||||
Some(CrateDisplayName::from_canonical_name("core".to_string())),
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Vec::new(),
|
||||
);
|
||||
|
@ -189,6 +189,7 @@ pub struct CrateData {
|
||||
/// `Dependency` matters), this name should only be used for UI.
|
||||
pub display_name: Option<CrateDisplayName>,
|
||||
pub cfg_options: CfgOptions,
|
||||
pub potential_cfg_options: CfgOptions,
|
||||
pub env: Env,
|
||||
pub dependencies: Vec<Dependency>,
|
||||
pub proc_macro: Vec<ProcMacro>,
|
||||
@ -219,6 +220,7 @@ impl CrateGraph {
|
||||
edition: Edition,
|
||||
display_name: Option<CrateDisplayName>,
|
||||
cfg_options: CfgOptions,
|
||||
potential_cfg_options: CfgOptions,
|
||||
env: Env,
|
||||
proc_macro: Vec<ProcMacro>,
|
||||
) -> CrateId {
|
||||
@ -227,6 +229,7 @@ impl CrateGraph {
|
||||
edition,
|
||||
display_name,
|
||||
cfg_options,
|
||||
potential_cfg_options,
|
||||
env,
|
||||
proc_macro,
|
||||
dependencies: Vec::new(),
|
||||
@ -504,6 +507,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -512,6 +516,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -520,6 +525,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -536,6 +542,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -544,6 +551,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -559,6 +567,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -567,6 +576,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -575,6 +585,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -590,6 +601,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
@ -598,6 +610,7 @@ mod tests {
|
||||
Edition2018,
|
||||
None,
|
||||
CfgOptions::default(),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
);
|
||||
|
@ -50,6 +50,26 @@ impl CfgOptions {
|
||||
self.enabled.remove(&atom);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cfg_keys(&self) -> Vec<&SmolStr> {
|
||||
self.enabled
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
CfgAtom::Flag(key) => key,
|
||||
CfgAtom::KeyValue { key, .. } => key,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_cfg_values(&self, cfg_key: &str) -> Vec<&SmolStr> {
|
||||
self.enabled
|
||||
.iter()
|
||||
.filter_map(|x| match x {
|
||||
CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -233,6 +233,10 @@ impl Crate {
|
||||
pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
|
||||
db.crate_graph()[self.id].cfg_options.clone()
|
||||
}
|
||||
|
||||
pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
|
||||
db.crate_graph()[self.id].potential_cfg_options.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -217,6 +217,7 @@ impl Analysis {
|
||||
file_id,
|
||||
Edition::Edition2018,
|
||||
None,
|
||||
cfg_options.clone(),
|
||||
cfg_options,
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
Completions,
|
||||
};
|
||||
|
||||
mod cfg;
|
||||
mod derive;
|
||||
mod lint;
|
||||
mod repr;
|
||||
@ -30,6 +31,9 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
|
||||
lint::complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINTS);
|
||||
lint::complete_lint(acc, ctx, token_tree, CLIPPY_LINTS);
|
||||
}
|
||||
"cfg" => {
|
||||
cfg::complete_cfg(acc, ctx);
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
(None, Some(_)) => (),
|
||||
@ -852,4 +856,15 @@ mod tests {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cfg() {
|
||||
check(
|
||||
r#"#[cfg(target_endian = $0"#,
|
||||
expect![[r#"
|
||||
at little
|
||||
at big
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
112
crates/ide_completion/src/completions/attribute/cfg.rs
Normal file
112
crates/ide_completion/src/completions/attribute/cfg.rs
Normal file
@ -0,0 +1,112 @@
|
||||
//! Completion for cfg
|
||||
|
||||
use std::iter;
|
||||
|
||||
use syntax::SyntaxKind;
|
||||
|
||||
use crate::{
|
||||
completions::Completions, context::CompletionContext, item::CompletionKind, CompletionItem,
|
||||
CompletionItemKind,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let add_completion = |item: &&str| {
|
||||
let mut completion =
|
||||
CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), *item);
|
||||
completion.insert_text(format!(r#""{}""#, item));
|
||||
completion.kind(CompletionItemKind::Attribute);
|
||||
acc.add(completion.build());
|
||||
};
|
||||
|
||||
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));
|
||||
|
||||
match previous.as_ref().map(|p| p.text()) {
|
||||
Some("target_arch") => KNOWN_ARCH.iter().for_each(add_completion),
|
||||
Some("target_env") => KNOWN_ENV.iter().for_each(add_completion),
|
||||
Some("target_os") => KNOWN_OS.iter().for_each(add_completion),
|
||||
Some("target_vendor") => KNOWN_VENDOR.iter().for_each(add_completion),
|
||||
Some("target_endian") => ["little", "big"].iter().for_each(add_completion),
|
||||
Some(name) => {
|
||||
ctx.krate.map(|krate| {
|
||||
krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| {
|
||||
let mut item = CompletionItem::new(
|
||||
CompletionKind::Attribute,
|
||||
ctx.source_range(),
|
||||
s.as_str(),
|
||||
);
|
||||
item.insert_text(format!(r#""{}""#, s));
|
||||
|
||||
acc.add(item.build());
|
||||
})
|
||||
});
|
||||
}
|
||||
None => {
|
||||
ctx.krate.map(|krate| {
|
||||
krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| {
|
||||
let item = CompletionItem::new(
|
||||
CompletionKind::Attribute,
|
||||
ctx.source_range(),
|
||||
s.as_str(),
|
||||
);
|
||||
acc.add(item.build());
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const KNOWN_ARCH: [&'static str; 19] = [
|
||||
"aarch64",
|
||||
"arm",
|
||||
"avr",
|
||||
"hexagon",
|
||||
"mips",
|
||||
"mips64",
|
||||
"msp430",
|
||||
"nvptx64",
|
||||
"powerpc",
|
||||
"powerpc64",
|
||||
"riscv32",
|
||||
"riscv64",
|
||||
"s390x",
|
||||
"sparc",
|
||||
"sparc64",
|
||||
"wasm32",
|
||||
"wasm64",
|
||||
"x86",
|
||||
"x86_64",
|
||||
];
|
||||
|
||||
const KNOWN_ENV: [&'static str; 7] =
|
||||
["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"];
|
||||
|
||||
const KNOWN_OS: [&'static str; 20] = [
|
||||
"cuda",
|
||||
"dragonfly",
|
||||
"emscripten",
|
||||
"freebsd",
|
||||
"fuchsia",
|
||||
"haiku",
|
||||
"hermit",
|
||||
"illumos",
|
||||
"l4re",
|
||||
"linux",
|
||||
"netbsd",
|
||||
"none",
|
||||
"openbsd",
|
||||
"psp",
|
||||
"redox",
|
||||
"solaris",
|
||||
"uefi",
|
||||
"unknown",
|
||||
"vxworks",
|
||||
"windows",
|
||||
];
|
||||
|
||||
const KNOWN_VENDOR: [&'static str; 8] =
|
||||
["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"];
|
@ -384,6 +384,7 @@ fn project_json_to_crate_graph(
|
||||
file_id,
|
||||
krate.edition,
|
||||
krate.display_name.clone(),
|
||||
cfg_options.clone(),
|
||||
cfg_options,
|
||||
env,
|
||||
proc_macro.unwrap_or_default(),
|
||||
@ -580,6 +581,7 @@ fn detached_files_to_crate_graph(
|
||||
Edition::Edition2018,
|
||||
display_name,
|
||||
cfg_options.clone(),
|
||||
cfg_options.clone(),
|
||||
Env::default(),
|
||||
Vec::new(),
|
||||
);
|
||||
@ -719,11 +721,19 @@ fn add_target_crate_root(
|
||||
.unwrap_or_default();
|
||||
|
||||
let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string());
|
||||
let mut potential_cfg_options = cfg_options.clone();
|
||||
potential_cfg_options.extend(
|
||||
pkg.features
|
||||
.iter()
|
||||
.map(|feat| CfgFlag::KeyValue { key: "feature".into(), value: feat.0.into() }),
|
||||
);
|
||||
|
||||
let crate_id = crate_graph.add_crate_root(
|
||||
file_id,
|
||||
edition,
|
||||
Some(display_name),
|
||||
cfg_options,
|
||||
potential_cfg_options,
|
||||
env,
|
||||
proc_macro,
|
||||
);
|
||||
@ -753,6 +763,7 @@ fn sysroot_to_crate_graph(
|
||||
Edition::Edition2018,
|
||||
Some(display_name),
|
||||
cfg_options.clone(),
|
||||
cfg_options.clone(),
|
||||
env,
|
||||
proc_macro,
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user