about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-08 10:51:17 +0000
committerbors <bors@rust-lang.org>2023-09-08 10:51:17 +0000
commit347695abc82fc4dc432c8c93032afde465d0fe51 (patch)
treed0ebb9407191c5c35551aa513665538688865501
parentb67606c4e27e626f84ee86651616462b7dfaa4c8 (diff)
parentfddef42e92f69b04c2b39d2accbe74a86ae4cc22 (diff)
downloadrust-347695abc82fc4dc432c8c93032afde465d0fe51.tar.gz
rust-347695abc82fc4dc432c8c93032afde465d0fe51.zip
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).
-rw-r--r--crates/base-db/src/fixture.rs10
-rw-r--r--crates/cfg/src/lib.rs26
-rw-r--r--crates/ide-completion/src/completions/attribute/cfg.rs57
-rw-r--r--crates/ide-completion/src/tests/attribute.rs38
-rw-r--r--crates/ide-db/src/search.rs6
-rw-r--r--crates/project-model/src/workspace.rs36
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model.txt4
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt4
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt4
-rw-r--r--crates/project-model/test_data/output/rust_project_hello_world_project_model.txt44
10 files changed, 170 insertions, 59 deletions
diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs
index aaac0fc3790..3f5ccb621c7 100644
--- a/crates/base-db/src/fixture.rs
+++ b/crates/base-db/src/fixture.rs
@@ -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 },
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index 183b9b7d278..0aeb0b05052 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -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`.
diff --git a/crates/ide-completion/src/completions/attribute/cfg.rs b/crates/ide-completion/src/completions/attribute/cfg.rs
index 62bdb6ee688..87a286778e6 100644
--- a/crates/ide-completion/src/completions/attribute/cfg.rs
+++ b/crates/ide-completion/src/completions/attribute/cfg.rs
@@ -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));
-
-    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);
+    // 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);
 
-            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] = [
diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs
index 1aaf3958726..d8c134c533b 100644
--- a/crates/ide-completion/src/tests/attribute.rs
+++ b/crates/ide-completion/src/tests/attribute.rs
@@ -67,11 +67,6 @@ struct Foo;
 }
 
 #[test]
-fn inside_nested_attr() {
-    check(r#"#[cfg($0)]"#, expect![[]])
-}
-
-#[test]
 fn with_existing_attr() {
     check(
         r#"#[no_mangle] #[$0] mcall!();"#,
@@ -636,6 +631,32 @@ 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(
             r#"#[cfg(target_endian = $0"#,
@@ -644,6 +665,13 @@ mod cfg {
                 ba little
             "#]],
         );
+        check(
+            r#"#[cfg(target_endian = b$0"#,
+            expect![[r#"
+                ba big
+                ba little
+            "#]],
+        );
     }
 }
 
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 7e00d368652..2ffce3c7513 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -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)
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 8cb0e65be1d..0904ef080d4 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -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
+}
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 447c7e5c869..727d39a3077 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -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",
             ],
         ),
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 447c7e5c869..727d39a3077 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -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",
             ],
         ),
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 2e8ece82a10..89728babd82 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -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,
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index fb3f5933b17..b7bf6cb2774 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -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 {