mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Fix cfg completions not working
This commit is contained in:
parent
ca6ddd8ea3
commit
853f8a21f7
4 changed files with 98 additions and 33 deletions
|
@ -179,8 +179,8 @@ impl ChangeFixture {
|
||||||
meta.edition,
|
meta.edition,
|
||||||
Some(crate_name.clone().into()),
|
Some(crate_name.clone().into()),
|
||||||
version,
|
version,
|
||||||
meta.cfg,
|
meta.cfg.clone(),
|
||||||
Default::default(),
|
Some(meta.cfg),
|
||||||
meta.env,
|
meta.env,
|
||||||
false,
|
false,
|
||||||
origin,
|
origin,
|
||||||
|
@ -200,7 +200,7 @@ impl ChangeFixture {
|
||||||
} else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
|
} else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
|
||||||
assert!(default_crate_root.is_none());
|
assert!(default_crate_root.is_none());
|
||||||
default_crate_root = Some(file_id);
|
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_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
|
||||||
default_target_data_layout = meta.target_data_layout;
|
default_target_data_layout = meta.target_data_layout;
|
||||||
}
|
}
|
||||||
|
@ -220,8 +220,8 @@ impl ChangeFixture {
|
||||||
Edition::CURRENT,
|
Edition::CURRENT,
|
||||||
Some(CrateName::new("test").unwrap().into()),
|
Some(CrateName::new("test").unwrap().into()),
|
||||||
None,
|
None,
|
||||||
default_cfg,
|
default_cfg.clone(),
|
||||||
Default::default(),
|
Some(default_cfg),
|
||||||
default_env,
|
default_env,
|
||||||
false,
|
false,
|
||||||
CrateOrigin::Local { repo: None, name: None },
|
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)]
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct CfgDiff {
|
pub struct CfgDiff {
|
||||||
// Invariants: No duplicates, no atom that's both in `enable` and `disable`.
|
// Invariants: No duplicates, no atom that's both in `enable` and `disable`.
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
//! Completion for cfg
|
//! Completion for cfg
|
||||||
|
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
use ide_db::SymbolKind;
|
use ide_db::SymbolKind;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::SyntaxKind;
|
use syntax::{algo, ast::Ident, AstToken, Direction, NodeOrToken, SyntaxKind};
|
||||||
|
|
||||||
use crate::{completions::Completions, context::CompletionContext, CompletionItem};
|
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));
|
acc.add(completion.build(ctx.db));
|
||||||
};
|
};
|
||||||
|
|
||||||
let previous = iter::successors(ctx.original_token.prev_token(), |t| {
|
// FIXME: Move this into context/analysis.rs
|
||||||
(matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia())
|
let previous = ctx
|
||||||
.then(|| t.prev_token())
|
.original_token
|
||||||
.flatten()
|
.prev_token()
|
||||||
})
|
.and_then(|it| {
|
||||||
.find(|t| matches!(t.kind(), SyntaxKind::IDENT));
|
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()) {
|
acc.add(item.build(ctx.db));
|
||||||
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));
|
|
||||||
}),
|
|
||||||
None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().unique().for_each(|s| {
|
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);
|
let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
|
||||||
acc.add(item.build(ctx.db));
|
acc.add(item.build(ctx.db));
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const KNOWN_ARCH: [&str; 20] = [
|
const KNOWN_ARCH: [&str; 20] = [
|
||||||
|
|
|
@ -66,11 +66,6 @@ struct Foo;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn inside_nested_attr() {
|
|
||||||
check(r#"#[cfg($0)]"#, expect![[]])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn with_existing_attr() {
|
fn with_existing_attr() {
|
||||||
check(
|
check(
|
||||||
|
@ -635,6 +630,32 @@ struct Foo;
|
||||||
mod cfg {
|
mod cfg {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn cfg_target_endian() {
|
fn cfg_target_endian() {
|
||||||
check(
|
check(
|
||||||
|
@ -644,6 +665,13 @@ mod cfg {
|
||||||
ba little
|
ba little
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
check(
|
||||||
|
r#"#[cfg(target_endian = b$0"#,
|
||||||
|
expect![[r#"
|
||||||
|
ba big
|
||||||
|
ba little
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue