Repository: rust-analyzer/rust-analyzer
Pull request #9083 (2021-05-31 15:33:50)

internal: Simplify proc_macro_srv tests
Removes `serde_derive`, instead using `proc_macro_test` macros.

Should fix https://github.com/rust-analyzer/rust-analyzer/issues/9067

bors r+


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index ee04cdce8e..505263c645 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1143,13 +1143,13 @@ name = "proc_macro_srv"
 version = "0.0.0"
 dependencies = [
  "cargo_metadata",
+ "expect-test",
  "libloading",
  "mbe",
  "memmap2",
  "object",
  "proc_macro_api",
  "proc_macro_test",
- "serde_derive",
  "test_utils",
  "toolchain",
  "tt",
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 4ea41175e8..c15cb88214 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -20,10 +20,9 @@ proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
 
 [dev-dependencies]
 test_utils = { path = "../test_utils" }
+toolchain = { path = "../toolchain" }
 cargo_metadata = "0.13"
+expect-test = "1.1.0"
 
 # used as proc macro test targets
-serde_derive = "1.0.106"
 proc_macro_test = { path = "../proc_macro_test" }
-
-toolchain = { path = "../toolchain" }


Test patch:
diff --git a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
deleted file mode 100644
index eb67c71348..0000000000
--- a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-SUBTREE $
-  PUNCH   # [alone] 4294967295
-  SUBTREE [] 4294967295
-    IDENT   doc 4294967295
-    SUBTREE () 4294967295
-      IDENT   hidden 4294967295
-  PUNCH   # [alone] 4294967295
-  SUBTREE [] 4294967295
-    IDENT   allow 4294967295
-    SUBTREE () 4294967295
-      IDENT   non_upper_case_globals 4294967295
-      PUNCH   , [alone] 4294967295
-      IDENT   unused_attributes 4294967295
-      PUNCH   , [alone] 4294967295
-      IDENT   unused_qualifications 4294967295
-  IDENT   const 4294967295
-  IDENT   _ 4294967295
-  PUNCH   : [alone] 4294967295
-  SUBTREE () 4294967295
-  PUNCH   = [alone] 4294967295
-  SUBTREE {} 4294967295
-    PUNCH   # [alone] 4294967295
-    SUBTREE [] 4294967295
-      IDENT   allow 4294967295
-      SUBTREE () 4294967295
-        IDENT   unused_extern_crates 4294967295
-        PUNCH   , [alone] 4294967295
-        IDENT   clippy 4294967295
-        PUNCH   : [joint] 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   useless_attribute 4294967295
-    IDENT   extern 4294967295
-    IDENT   crate 4294967295
-    IDENT   serde 4294967295
-    IDENT   as 4294967295
-    IDENT   _serde 4294967295
-    PUNCH   ; [alone] 4294967295
-    PUNCH   # [alone] 4294967295
-    SUBTREE [] 4294967295
-      IDENT   allow 4294967295
-      SUBTREE () 4294967295
-        IDENT   unused_macros 4294967295
-    IDENT   macro_rules 4294967295
-    PUNCH   ! [alone] 4294967295
-    IDENT   try 4294967295
-    SUBTREE {} 4294967295
-      SUBTREE () 4294967295
-        PUNCH   $ [alone] 4294967295
-        IDENT   __expr 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   expr 4294967295
-      PUNCH   = [joint] 4294967295
-      PUNCH   > [alone] 4294967295
-      SUBTREE {} 4294967295
-        IDENT   match 4294967295
-        PUNCH   $ [alone] 4294967295
-        IDENT   __expr 4294967295
-        SUBTREE {} 4294967295
-          IDENT   _serde 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   __private 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   Ok 4294967295
-          SUBTREE () 4294967295
-            IDENT   __val 4294967295
-          PUNCH   = [joint] 4294967295
-          PUNCH   > [alone] 4294967295
-          IDENT   __val 4294967295
-          PUNCH   , [alone] 4294967295
-          IDENT   _serde 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   __private 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   Err 4294967295
-          SUBTREE () 4294967295
-            IDENT   __err 4294967295
-          PUNCH   = [joint] 4294967295
-          PUNCH   > [alone] 4294967295
-          SUBTREE {} 4294967295
-            IDENT   return 4294967295
-            IDENT   _serde 4294967295
-            PUNCH   : [joint] 4294967295
-            PUNCH   : [alone] 4294967295
-            IDENT   __private 4294967295
-            PUNCH   : [joint] 4294967295
-            PUNCH   : [alone] 4294967295
-            IDENT   Err 4294967295
-            SUBTREE () 4294967295
-              IDENT   __err 4294967295
-            PUNCH   ; [alone] 4294967295
-    PUNCH   # [alone] 4294967295
-    SUBTREE [] 4294967295
-      IDENT   automatically_derived 4294967295
-    IDENT   impl 4294967295
-    IDENT   _serde 4294967295
-    PUNCH   : [joint] 4294967295
-    PUNCH   : [alone] 4294967295
-    IDENT   Serialize 4294967295
-    IDENT   for 4294967295
-    IDENT   Foo 4294967295
-    SUBTREE {} 4294967295
-      IDENT   fn 4294967295
-      IDENT   serialize 4294967295
-      PUNCH   < [alone] 4294967295
-      IDENT   __S 4294967295
-      PUNCH   > [alone] 4294967295
-      SUBTREE () 4294967295
-        PUNCH   & [alone] 4294967295
-        IDENT   self 4294967295
-        PUNCH   , [alone] 4294967295
-        IDENT   __serializer 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   __S 4294967295
-      PUNCH   - [joint] 4294967295
-      PUNCH   > [alone] 4294967295
-      IDENT   _serde 4294967295
-      PUNCH   : [joint] 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   __private 4294967295
-      PUNCH   : [joint] 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   Result 4294967295
-      PUNCH   < [alone] 4294967295
-      IDENT   __S 4294967295
-      PUNCH   : [joint] 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   Ok 4294967295
-      PUNCH   , [alone] 4294967295
-      IDENT   __S 4294967295
-      PUNCH   : [joint] 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   Error 4294967295
-      PUNCH   > [alone] 4294967295
-      IDENT   where 4294967295
-      IDENT   __S 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   _serde 4294967295
-      PUNCH   : [joint] 4294967295
-      PUNCH   : [alone] 4294967295
-      IDENT   Serializer 4294967295
-      PUNCH   , [alone] 4294967295
-      SUBTREE {} 4294967295
-        IDENT   let 4294967295
-        IDENT   __serde_state 4294967295
-        PUNCH   = [alone] 4294967295
-        IDENT   try 4294967295
-        PUNCH   ! [alone] 4294967295
-        SUBTREE () 4294967295
-          IDENT   _serde 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   Serializer 4294967295
-          PUNCH   : [joint] 4294967295
-          PUNCH   : [alone] 4294967295
-          IDENT   serialize_struct 4294967295
-          SUBTREE () 4294967295
-            IDENT   __serializer 4294967295
-            PUNCH   , [alone] 4294967295
-            LITERAL "Foo" 4294967295
-            PUNCH   , [alone] 4294967295
-            IDENT   false 4294967295
-            IDENT   as 4294967295
-            IDENT   usize 4294967295
-        PUNCH   ; [alone] 4294967295
-        IDENT   _serde 4294967295
-        PUNCH   : [joint] 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   ser 4294967295
-        PUNCH   : [joint] 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   SerializeStruct 4294967295
-        PUNCH   : [joint] 4294967295
-        PUNCH   : [alone] 4294967295
-        IDENT   end 4294967295
-        SUBTREE () 4294967295
-          IDENT   __serde_state 4294967295
-  PUNCH   ; [alone] 4294967295
diff --git a/crates/proc_macro_srv/src/tests/mod.rs b/crates/proc_macro_srv/src/tests/mod.rs
index b4ab4c0776..5ca2b8a750 100644
--- a/crates/proc_macro_srv/src/tests/mod.rs
+++ b/crates/proc_macro_srv/src/tests/mod.rs
@@ -2,64 +2,86 @@
 
 #[macro_use]
 mod utils;
-use test_utils::assert_eq_text;
+use expect_test::expect;
 use utils::*;
 
 #[test]
-fn test_derive_serialize_proc_macro() {
+fn test_derive_empty() {
+    assert_expand("DeriveEmpty", r#"struct S;"#, expect![[r#"SUBTREE $"#]]);
+}
+
+#[test]
+fn test_derive_error() {
     assert_expand(
-        "serde_derive",
-        "Serialize",
-        "1.0",
-        r"struct Foo {}",
-        include_str!("fixtures/test_serialize_proc_macro.txt"),
+        "DeriveError",
+        r#"struct S;"#,
+        expect![[r##"
+            SUBTREE $
+              IDENT   compile_error 4294967295
+              PUNCH   ! [alone] 4294967295
+              SUBTREE () 4294967295
+                LITERAL "#[derive(DeriveError)] struct S ;" 4294967295
+              PUNCH   ; [alone] 4294967295"##]],
     );
 }
 
 #[test]
-fn test_derive_serialize_proc_macro_failed() {
+fn test_fn_like_macro() {
     assert_expand(
-        "serde_derive",
-        "Serialize",
-        "1.0",
-        r"struct {}",
-        r##"
-SUBTREE $
-  IDENT   compile_error 4294967295
-  PUNCH   ! [alone] 4294967295
-  SUBTREE {} 4294967295
-    LITERAL "expected identifier" 4294967295
-"##,
+        "fn_like_noop",
+        r#"ident, 0, 1, []"#,
+        expect![[r#"
+            SUBTREE $
+              IDENT   ident 4294967295
+              PUNCH   , [alone] 4294967295
+              LITERAL 0 4294967295
+              PUNCH   , [alone] 4294967295
+              LITERAL 1 4294967295
+              PUNCH   , [alone] 4294967295
+              SUBTREE [] 4294967295"#]],
     );
 }
 
 #[test]
-fn test_derive_proc_macro_list() {
-    let res = list("serde_derive", "1").join("\n");
-
-    assert_eq_text!(
-        r#"Serialize [CustomDerive]
-Deserialize [CustomDerive]"#,
-        &res
+fn test_attr_macro() {
+    // Corresponds to
+    //    #[proc_macro_test::attr_error(some arguments)]
+    //    mod m {}
+    assert_expand_attr(
+        "attr_error",
+        r#"mod m {}"#,
+        r#"some arguments"#,
+        expect![[r##"
+            SUBTREE $
+              IDENT   compile_error 4294967295
+              PUNCH   ! [alone] 4294967295
+              SUBTREE () 4294967295
+                LITERAL "#[attr_error(some arguments)] mod m {}" 4294967295
+              PUNCH   ; [alone] 4294967295"##]],
     );
 }
 
-/// Tests that we find and classify non-derive macros correctly.
+/// Tests that we find and classify all proc macros correctly.
 #[test]
 fn list_test_macros() {
-    let res = list("proc_macro_test", "0.0.0").join("\n");
+    let res = list().join("\n");
 
-    assert_eq_text!(
-        r#"function_like_macro [FuncLike]
-attribute_macro [Attr]
-DummyTrait [CustomDerive]"#,
-        &res
-    );
+    expect![[r#"
+        fn_like_noop [FuncLike]
+        fn_like_panic [FuncLike]
+        fn_like_error [FuncLike]
+        attr_noop [Attr]
+        attr_panic [Attr]
+        attr_error [Attr]
+        DeriveEmpty [CustomDerive]
+        DerivePanic [CustomDerive]
+        DeriveError [CustomDerive]"#]]
+    .assert_eq(&res);
 }
 
 #[test]
 fn test_version_check() {
-    let path = fixtures::dylib_path("proc_macro_test", "0.0.0");
+    let path = fixtures::proc_macro_test_dylib_path();
     let info = proc_macro_api::read_dylib_info(&path).unwrap();
     assert!(info.version.1 >= 50);
 }
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs
index f15381f0f4..f0a514b325 100644
--- a/crates/proc_macro_srv/src/tests/utils.rs
+++ b/crates/proc_macro_srv/src/tests/utils.rs
@@ -2,9 +2,9 @@
 
 use crate::dylib;
 use crate::ProcMacroSrv;
+use expect_test::Expect;
 use proc_macro_api::ListMacrosTask;
 use std::str::FromStr;
-use test_utils::assert_eq_text;
 
 pub mod fixtures {
     use cargo_metadata::Message;
@@ -12,9 +12,11 @@ pub mod fixtures {
     use std::process::Command;
 
     // Use current project metadata to get the proc-macro dylib path
-    pub fn dylib_path(crate_name: &str, version: &str) -> std::path::PathBuf {
+    pub fn proc_macro_test_dylib_path() -> std::path::PathBuf {
+        let name = "proc_macro_test";
+        let version = "0.0.0";
         let command = Command::new(toolchain::cargo())
-            .args(&["check", "--tests", "--message-format", "json"])
+            .args(&["build", "-p", name, "--message-format", "json"])
             .output()
             .unwrap()
             .stdout;
@@ -23,7 +25,7 @@ pub mod fixtures {
             match message.unwrap() {
                 Message::CompilerArtifact(artifact) => {
                     if artifact.target.kind.contains(&"proc-macro".to_string()) {
-                        let repr = format!("{} {}", crate_name, version);
+                        let repr = format!("{} {}", name, version);
                         if artifact.package_id.repr.starts_with(&repr) {
                             return PathBuf::from(&artifact.filenames[0]);
                         }
@@ -33,7 +35,7 @@ pub mod fixtures {
             }
         }
 
-        panic!("No proc-macro dylib for {} found!", crate_name);
+        panic!("No proc-macro dylib for {} found!", name);
     }
 }
 
@@ -41,23 +43,26 @@ fn parse_string(code: &str) -> Option<crate::rustc_server::TokenStream> {
     Some(crate::rustc_server::TokenStream::from_str(code).unwrap())
 }
 
-pub fn assert_expand(
-    crate_name: &str,
-    macro_name: &str,
-    version: &str,
-    ra_fixture: &str,
-    expect: &str,
-) {
-    let path = fixtures::dylib_path(crate_name, version);
+pub fn assert_expand(macro_name: &str, ra_fixture: &str, expect: Expect) {
+    assert_expand_impl(macro_name, ra_fixture, None, expect);
+}
+
+pub fn assert_expand_attr(macro_name: &str, ra_fixture: &str, attr_args: &str, expect: Expect) {
+    assert_expand_impl(macro_name, ra_fixture, Some(attr_args), expect);
+}
+
+fn assert_expand_impl(macro_name: &str, input: &str, attr: Option<&str>, expect: Expect) {
+    let path = fixtures::proc_macro_test_dylib_path();
     let expander = dylib::Expander::new(&path).unwrap();
-    let fixture = parse_string(ra_fixture).unwrap();
+    let fixture = parse_string(input).unwrap();
+    let attr = attr.map(|attr| parse_string(attr).unwrap().into_subtree());
 
-    let res = expander.expand(macro_name, &fixture.into_subtree(), None).unwrap();
-    assert_eq_text!(&expect.trim(), &format!("{:?}", res));
+    let res = expander.expand(macro_name, &fixture.into_subtree(), attr.as_ref()).unwrap();
+    expect.assert_eq(&format!("{:?}", res));
 }
 
-pub fn list(crate_name: &str, version: &str) -> Vec<String> {
-    let path = fixtures::dylib_path(crate_name, version);
+pub fn list() -> Vec<String> {
+    let path = fixtures::proc_macro_test_dylib_path();
     let task = ListMacrosTask { lib: path };
     let mut srv = ProcMacroSrv::default();
     let res = srv.list_macros(&task).unwrap();
diff --git a/crates/proc_macro_test/src/lib.rs b/crates/proc_macro_test/src/lib.rs
index ec2a114a35..4b26d24721 100644
--- a/crates/proc_macro_test/src/lib.rs
+++ b/crates/proc_macro_test/src/lib.rs
@@ -3,16 +3,46 @@
 use proc_macro::TokenStream;
 
 #[proc_macro]
-pub fn function_like_macro(args: TokenStream) -> TokenStream {
+pub fn fn_like_noop(args: TokenStream) -> TokenStream {
     args
 }
 
+#[proc_macro]
+pub fn fn_like_panic(args: TokenStream) -> TokenStream {
+    panic!("fn_like_panic!({})", args);
+}
+
+#[proc_macro]
+pub fn fn_like_error(args: TokenStream) -> TokenStream {
+    format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap()
+}
+
 #[proc_macro_attribute]
-pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
+pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream {
     item
 }
 
-#[proc_macro_derive(DummyTrait)]
-pub fn derive_macro(_item: TokenStream) -> TokenStream {
+#[proc_macro_attribute]
+pub fn attr_panic(args: TokenStream, item: TokenStream) -> TokenStream {
+    panic!("#[attr_panic {}] {}", args, item);
+}
+
+#[proc_macro_attribute]
+pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream {
+    format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap()
+}
+
+#[proc_macro_derive(DeriveEmpty)]
+pub fn derive_empty(_item: TokenStream) -> TokenStream {
     TokenStream::new()
 }
+
+#[proc_macro_derive(DerivePanic)]
+pub fn derive_panic(item: TokenStream) -> TokenStream {
+    panic!("#[derive(DerivePanic)] {}", item);
+}
+
+#[proc_macro_derive(DeriveError)]
+pub fn derive_error(item: TokenStream) -> TokenStream {
+    format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap()
+}