aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock51
-rw-r--r--Cargo.toml2
-rw-r--r--crates/assists/src/handlers/invert_if.rs9
-rw-r--r--crates/assists/src/handlers/reorder_fields.rs129
-rw-r--r--crates/assists/src/utils.rs4
-rw-r--r--crates/completion/src/render/macro_.rs6
-rw-r--r--crates/hir/src/code_model.rs8
-rw-r--r--crates/hir/src/from_id.rs17
-rw-r--r--crates/hir/src/has_source.rs16
-rw-r--r--crates/hir/src/semantics.rs53
-rw-r--r--crates/hir/src/semantics/source_to_def.rs26
-rw-r--r--crates/hir_def/src/adt.rs13
-rw-r--r--crates/hir_def/src/body/lower.rs246
-rw-r--r--crates/hir_def/src/generics.rs55
-rw-r--r--crates/hir_def/src/item_tree.rs22
-rw-r--r--crates/hir_def/src/item_tree/lower.rs29
-rw-r--r--crates/hir_def/src/keys.rs5
-rw-r--r--crates/hir_def/src/nameres/collector.rs65
-rw-r--r--crates/hir_def/src/path/lower.rs8
-rw-r--r--crates/hir_def/src/src.rs5
-rw-r--r--crates/hir_expand/src/builtin_macro.rs41
-rw-r--r--crates/hir_expand/src/db.rs4
-rw-r--r--crates/hir_expand/src/lib.rs2
-rw-r--r--crates/hir_expand/src/name.rs3
-rw-r--r--crates/hir_ty/src/tests/macros.rs1
-rw-r--r--crates/hir_ty/src/tests/regression.rs24
-rw-r--r--crates/ide/src/file_structure.rs14
-rw-r--r--crates/ide/src/references.rs117
-rw-r--r--crates/ide/src/syntax_highlighting.rs52
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html6
-rw-r--r--crates/ide_db/src/defs.rs2
-rw-r--r--crates/ide_db/src/search.rs15
-rw-r--r--crates/ide_db/src/symbol_index.rs8
-rw-r--r--crates/mbe/src/mbe_expander.rs2
-rw-r--r--crates/mbe/src/tests.rs4
-rw-r--r--crates/parser/src/grammar/items.rs44
-rw-r--r--crates/parser/src/syntax_kind/generated.rs7
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/dylib.rs65
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs43
-rw-r--r--crates/syntax/src/ast/make.rs3
-rw-r--r--crates/syntax/src/ast/node_ext.rs17
-rw-r--r--crates/syntax/src/display.rs2
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs4
-rw-r--r--crates/syntax/src/validation.rs14
-rw-r--r--crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast14
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast48
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast7
-rw-r--r--crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast7
-rw-r--r--docs/dev/style.md8
-rw-r--r--docs/user/manual.adoc2
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--xtask/src/ast_src.rs4
56 files changed, 879 insertions, 492 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8cb5fd7ad..ff2c33f45 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -89,7 +89,7 @@ dependencies = [
89 "cfg-if 1.0.0", 89 "cfg-if 1.0.0",
90 "libc", 90 "libc",
91 "miniz_oxide", 91 "miniz_oxide",
92 "object", 92 "object 0.22.0",
93 "rustc-demangle", 93 "rustc-demangle",
94] 94]
95 95
@@ -500,17 +500,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
500checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" 500checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
501 501
502[[package]] 502[[package]]
503name = "goblin"
504version = "0.2.3"
505source = "registry+https://github.com/rust-lang/crates.io-index"
506checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
507dependencies = [
508 "log",
509 "plain",
510 "scroll",
511]
512
513[[package]]
514name = "hashbrown" 503name = "hashbrown"
515version = "0.9.1" 504version = "0.9.1"
516source = "registry+https://github.com/rust-lang/crates.io-index" 505source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1055,6 +1044,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1055checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" 1044checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
1056 1045
1057[[package]] 1046[[package]]
1047name = "object"
1048version = "0.23.0"
1049source = "registry+https://github.com/rust-lang/crates.io-index"
1050checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
1051
1052[[package]]
1058name = "once_cell" 1053name = "once_cell"
1059version = "1.5.2" 1054version = "1.5.2"
1060source = "registry+https://github.com/rust-lang/crates.io-index" 1055source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1159,12 +1154,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1159checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" 1154checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
1160 1155
1161[[package]] 1156[[package]]
1162name = "plain"
1163version = "0.2.3"
1164source = "registry+https://github.com/rust-lang/crates.io-index"
1165checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
1166
1167[[package]]
1168name = "proc-macro2" 1157name = "proc-macro2"
1169version = "1.0.24" 1158version = "1.0.24"
1170source = "registry+https://github.com/rust-lang/crates.io-index" 1159source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1192,10 +1181,10 @@ version = "0.0.0"
1192dependencies = [ 1181dependencies = [
1193 "cargo_metadata", 1182 "cargo_metadata",
1194 "difference", 1183 "difference",
1195 "goblin",
1196 "libloading", 1184 "libloading",
1197 "mbe", 1185 "mbe",
1198 "memmap", 1186 "memmap",
1187 "object 0.23.0",
1199 "proc_macro_api", 1188 "proc_macro_api",
1200 "proc_macro_test", 1189 "proc_macro_test",
1201 "serde_derive", 1190 "serde_derive",
@@ -1472,26 +1461,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1472checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1461checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1473 1462
1474[[package]] 1463[[package]]
1475name = "scroll"
1476version = "0.10.2"
1477source = "registry+https://github.com/rust-lang/crates.io-index"
1478checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec"
1479dependencies = [
1480 "scroll_derive",
1481]
1482
1483[[package]]
1484name = "scroll_derive"
1485version = "0.10.4"
1486source = "registry+https://github.com/rust-lang/crates.io-index"
1487checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d"
1488dependencies = [
1489 "proc-macro2",
1490 "quote",
1491 "syn",
1492]
1493
1494[[package]]
1495name = "semver" 1464name = "semver"
1496version = "0.9.0" 1465version = "0.9.0"
1497source = "registry+https://github.com/rust-lang/crates.io-index" 1466source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1858,9 +1827,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1858 1827
1859[[package]] 1828[[package]]
1860name = "ungrammar" 1829name = "ungrammar"
1861version = "1.1.4" 1830version = "1.2.2"
1862source = "registry+https://github.com/rust-lang/crates.io-index" 1831source = "registry+https://github.com/rust-lang/crates.io-index"
1863checksum = "df0cd89993af555540e2436fc6adb8479b0dbe386339a136397952e9c89e17a9" 1832checksum = "873186a460627379e7e28880a0d33b729c205634f6f021321f50b323235e62d7"
1864 1833
1865[[package]] 1834[[package]]
1866name = "unicase" 1835name = "unicase"
diff --git a/Cargo.toml b/Cargo.toml
index e30ef0e2f..59d36fbc1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,3 +25,5 @@ debug = 0 # Set this to 1 or 2 to get more useful backtraces in debugger.
25# chalk-solve = { path = "../chalk/chalk-solve" } 25# chalk-solve = { path = "../chalk/chalk-solve" }
26# chalk-ir = { path = "../chalk/chalk-ir" } 26# chalk-ir = { path = "../chalk/chalk-ir" }
27# chalk-recursive = { path = "../chalk/chalk-recursive" } 27# chalk-recursive = { path = "../chalk/chalk-recursive" }
28
29# ungrammar = { path = "../ungrammar" }
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs
index ea722b91b..91e2f5c8c 100644
--- a/crates/assists/src/handlers/invert_if.rs
+++ b/crates/assists/src/handlers/invert_if.rs
@@ -69,6 +69,15 @@ mod tests {
69 use crate::tests::{check_assist, check_assist_not_applicable}; 69 use crate::tests::{check_assist, check_assist_not_applicable};
70 70
71 #[test] 71 #[test]
72 fn invert_if_composite_condition() {
73 check_assist(
74 invert_if,
75 "fn f() { i<|>f x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }",
76 "fn f() { if !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }",
77 )
78 }
79
80 #[test]
72 fn invert_if_remove_inequality() { 81 fn invert_if_remove_inequality() {
73 check_assist( 82 check_assist(
74 invert_if, 83 invert_if,
diff --git a/crates/assists/src/handlers/reorder_fields.rs b/crates/assists/src/handlers/reorder_fields.rs
index 7c0f0f44e..fe5574242 100644
--- a/crates/assists/src/handlers/reorder_fields.rs
+++ b/crates/assists/src/handlers/reorder_fields.rs
@@ -4,6 +4,7 @@ use rustc_hash::FxHashMap;
4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
5use ide_db::RootDatabase; 5use ide_db::RootDatabase;
6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; 6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7use test_utils::mark;
7 8
8use crate::{AssistContext, AssistId, AssistKind, Assists}; 9use crate::{AssistContext, AssistId, AssistKind, Assists};
9 10
@@ -38,6 +39,7 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
38 }); 39 });
39 40
40 if sorted_fields == fields { 41 if sorted_fields == fields {
42 mark::hit!(reorder_sorted_fields);
41 return None; 43 return None;
42 } 44 }
43 45
@@ -107,22 +109,25 @@ fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM
107 109
108#[cfg(test)] 110#[cfg(test)]
109mod tests { 111mod tests {
112 use test_utils::mark;
113
110 use crate::tests::{check_assist, check_assist_not_applicable}; 114 use crate::tests::{check_assist, check_assist_not_applicable};
111 115
112 use super::*; 116 use super::*;
113 117
114 #[test] 118 #[test]
115 fn not_applicable_if_sorted() { 119 fn reorder_sorted_fields() {
120 mark::check!(reorder_sorted_fields);
116 check_assist_not_applicable( 121 check_assist_not_applicable(
117 reorder_fields, 122 reorder_fields,
118 r#" 123 r#"
119 struct Foo { 124struct Foo {
120 foo: i32, 125 foo: i32,
121 bar: i32, 126 bar: i32,
122 } 127}
123 128
124 const test: Foo = <|>Foo { foo: 0, bar: 0 }; 129const test: Foo = <|>Foo { foo: 0, bar: 0 };
125 "#, 130"#,
126 ) 131 )
127 } 132 }
128 133
@@ -131,9 +136,9 @@ mod tests {
131 check_assist_not_applicable( 136 check_assist_not_applicable(
132 reorder_fields, 137 reorder_fields,
133 r#" 138 r#"
134 struct Foo {}; 139struct Foo {};
135 const test: Foo = <|>Foo {} 140const test: Foo = <|>Foo {}
136 "#, 141"#,
137 ) 142 )
138 } 143 }
139 144
@@ -142,13 +147,13 @@ mod tests {
142 check_assist( 147 check_assist(
143 reorder_fields, 148 reorder_fields,
144 r#" 149 r#"
145 struct Foo {foo: i32, bar: i32}; 150struct Foo {foo: i32, bar: i32};
146 const test: Foo = <|>Foo {bar: 0, foo: 1} 151const test: Foo = <|>Foo {bar: 0, foo: 1}
147 "#, 152"#,
148 r#" 153 r#"
149 struct Foo {foo: i32, bar: i32}; 154struct Foo {foo: i32, bar: i32};
150 const test: Foo = Foo {foo: 1, bar: 0} 155const test: Foo = Foo {foo: 1, bar: 0}
151 "#, 156"#,
152 ) 157 )
153 } 158 }
154 159
@@ -157,25 +162,25 @@ mod tests {
157 check_assist( 162 check_assist(
158 reorder_fields, 163 reorder_fields,
159 r#" 164 r#"
160 struct Foo { foo: i64, bar: i64, baz: i64 } 165struct Foo { foo: i64, bar: i64, baz: i64 }
161 166
162 fn f(f: Foo) -> { 167fn f(f: Foo) -> {
163 match f { 168 match f {
164 <|>Foo { baz: 0, ref mut bar, .. } => (), 169 <|>Foo { baz: 0, ref mut bar, .. } => (),
165 _ => () 170 _ => ()
166 } 171 }
167 } 172}
168 "#, 173"#,
169 r#" 174 r#"
170 struct Foo { foo: i64, bar: i64, baz: i64 } 175struct Foo { foo: i64, bar: i64, baz: i64 }
171 176
172 fn f(f: Foo) -> { 177fn f(f: Foo) -> {
173 match f { 178 match f {
174 Foo { ref mut bar, baz: 0, .. } => (), 179 Foo { ref mut bar, baz: 0, .. } => (),
175 _ => () 180 _ => ()
176 } 181 }
177 } 182}
178 "#, 183"#,
179 ) 184 )
180 } 185 }
181 186
@@ -184,39 +189,39 @@ mod tests {
184 check_assist( 189 check_assist(
185 reorder_fields, 190 reorder_fields,
186 r#" 191 r#"
187 struct Foo { 192struct Foo {
188 foo: String, 193 foo: String,
189 bar: String, 194 bar: String,
190 } 195}
191 196
192 impl Foo { 197impl Foo {
193 fn new() -> Foo { 198 fn new() -> Foo {
194 let foo = String::new(); 199 let foo = String::new();
195 <|>Foo { 200 <|>Foo {
196 bar: foo.clone(), 201 bar: foo.clone(),
197 extra: "Extra field", 202 extra: "Extra field",
198 foo, 203 foo,
199 } 204 }
200 } 205 }
201 } 206}
202 "#, 207"#,
203 r#" 208 r#"
204 struct Foo { 209struct Foo {
205 foo: String, 210 foo: String,
206 bar: String, 211 bar: String,
207 } 212}
208 213
209 impl Foo { 214impl Foo {
210 fn new() -> Foo { 215 fn new() -> Foo {
211 let foo = String::new(); 216 let foo = String::new();
212 Foo { 217 Foo {
213 foo, 218 foo,
214 bar: foo.clone(), 219 bar: foo.clone(),
215 extra: "Extra field", 220 extra: "Extra field",
216 } 221 }
217 } 222 }
218 } 223}
219 "#, 224"#,
220 ) 225 )
221 } 226 }
222} 227}
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index 01f5c291f..f2cacf7c8 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -212,6 +212,10 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
212 ast::Expr::BinExpr(bin) => match bin.op_kind()? { 212 ast::Expr::BinExpr(bin) => match bin.op_kind()? {
213 ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()), 213 ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
214 ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), 214 ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
215 // Parenthesize composite boolean expressions before prefixing `!`
216 ast::BinOp::BooleanAnd | ast::BinOp::BooleanOr => {
217 Some(make::expr_prefix(T![!], make::expr_paren(expr.clone())))
218 }
215 _ => None, 219 _ => None,
216 }, 220 },
217 ast::Expr::MethodCallExpr(mce) => { 221 ast::Expr::MethodCallExpr(mce) => {
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index eb3209bee..6cfbd6c9b 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -144,7 +144,7 @@ mod tests {
144use foo::<|>; 144use foo::<|>;
145//- /foo/lib.rs crate:foo 145//- /foo/lib.rs crate:foo
146#[macro_export] 146#[macro_export]
147macro_rules frobnicate { () => () } 147macro_rules! frobnicate { () => () }
148"#, 148"#,
149 r#" 149 r#"
150use foo::frobnicate; 150use foo::frobnicate;
@@ -154,11 +154,11 @@ use foo::frobnicate;
154 check_edit( 154 check_edit(
155 "frobnicate!", 155 "frobnicate!",
156 r#" 156 r#"
157macro_rules frobnicate { () => () } 157macro_rules! frobnicate { () => () }
158fn main() { frob<|>!(); } 158fn main() { frob<|>!(); }
159"#, 159"#,
160 r#" 160 r#"
161macro_rules frobnicate { () => () } 161macro_rules! frobnicate { () => () }
162fn main() { frobnicate!(); } 162fn main() { frobnicate!(); }
163"#, 163"#,
164 ); 164 );
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index fcc42c6bb..42dc35b76 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1250,6 +1250,14 @@ impl LifetimeParam {
1250 let params = db.generic_params(self.id.parent); 1250 let params = db.generic_params(self.id.parent);
1251 params.lifetimes[self.id.local_id].name.clone() 1251 params.lifetimes[self.id.local_id].name.clone()
1252 } 1252 }
1253
1254 pub fn module(self, db: &dyn HirDatabase) -> Module {
1255 self.id.parent.module(db.upcast()).into()
1256 }
1257
1258 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
1259 self.id.parent.into()
1260 }
1253} 1261}
1254 1262
1255// FIXME: rename from `ImplDef` to `Impl` 1263// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 265ef6d1f..dd3fcfe4a 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -41,6 +41,7 @@ from_id![
41 (hir_def::FunctionId, crate::Function), 41 (hir_def::FunctionId, crate::Function),
42 (hir_def::ImplId, crate::ImplDef), 42 (hir_def::ImplId, crate::ImplDef),
43 (hir_def::TypeParamId, crate::TypeParam), 43 (hir_def::TypeParamId, crate::TypeParam),
44 (hir_def::LifetimeParamId, crate::LifetimeParam),
44 (hir_expand::MacroDefId, crate::MacroDef) 45 (hir_expand::MacroDefId, crate::MacroDef)
45]; 46];
46 47
@@ -154,6 +155,22 @@ impl From<GenericDef> for GenericDefId {
154 } 155 }
155} 156}
156 157
158impl From<GenericDefId> for GenericDef {
159 fn from(def: GenericDefId) -> Self {
160 match def {
161 GenericDefId::FunctionId(it) => GenericDef::Function(it.into()),
162 GenericDefId::AdtId(it) => GenericDef::Adt(it.into()),
163 GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
164 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
165 GenericDefId::ImplId(it) => GenericDef::ImplDef(it.into()),
166 GenericDefId::EnumVariantId(it) => {
167 GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id })
168 }
169 GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
170 }
171 }
172}
173
157impl From<Adt> for GenericDefId { 174impl From<Adt> for GenericDefId {
158 fn from(id: Adt) -> Self { 175 fn from(id: Adt) -> Self {
159 match id { 176 match id {
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index c77494152..04845037f 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -10,8 +10,8 @@ use hir_expand::InFile;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, MacroDef, 13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef,
14 Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, 14 LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
15}; 15};
16 16
17pub trait HasSource { 17pub trait HasSource {
@@ -110,8 +110,8 @@ impl HasSource for TypeAlias {
110 } 110 }
111} 111}
112impl HasSource for MacroDef { 112impl HasSource for MacroDef {
113 type Ast = ast::MacroCall; 113 type Ast = ast::MacroRules;
114 fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroCall> { 114 fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> {
115 InFile { 115 InFile {
116 file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, 116 file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
117 value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), 117 value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()),
@@ -132,3 +132,11 @@ impl HasSource for TypeParam {
132 child_source.map(|it| it[self.id.local_id].clone()) 132 child_source.map(|it| it[self.id.local_id].clone())
133 } 133 }
134} 134}
135
136impl HasSource for LifetimeParam {
137 type Ast = ast::LifetimeParam;
138 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
139 let child_source = self.id.parent.child_source(db.upcast());
140 child_source.map(|it| it[self.id.local_id].clone())
141 }
142}
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 4bd22ed27..5959ac4ca 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,7 +13,11 @@ use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
13use hir_ty::associated_type_shorthand_candidates; 13use hir_ty::associated_type_shorthand_candidates;
14use itertools::Itertools; 14use itertools::Itertools;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
16use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize}; 16use syntax::{
17 algo::find_node_at_offset,
18 ast::{self, GenericParamsOwner},
19 match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
20};
17 21
18use crate::{ 22use crate::{
19 code_model::Access, 23 code_model::Access,
@@ -21,8 +25,9 @@ use crate::{
21 diagnostics::Diagnostic, 25 diagnostics::Diagnostic,
22 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 26 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
23 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 27 source_analyzer::{resolve_hir_path, SourceAnalyzer},
24 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, 28 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local,
25 Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 29 MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
30 VariantDef,
26}; 31};
27 32
28#[derive(Debug, Clone, PartialEq, Eq)] 33#[derive(Debug, Clone, PartialEq, Eq)]
@@ -173,6 +178,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
173 self.imp.descend_node_at_offset(node, offset).find_map(N::cast) 178 self.imp.descend_node_at_offset(node, offset).find_map(N::cast)
174 } 179 }
175 180
181 // FIXME: Replace the SyntaxToken with a typed ast Node/Token
182 pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
183 self.imp.resolve_lifetime_param(lifetime_token)
184 }
185
176 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 186 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
177 self.imp.type_of_expr(expr) 187 self.imp.type_of_expr(expr)
178 } 188 }
@@ -392,16 +402,44 @@ impl<'db> SemanticsImpl<'db> {
392 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 402 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
393 } 403 }
394 404
405 // FIXME: Replace the SyntaxToken with a typed ast Node/Token
406 fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
407 if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME {
408 return None;
409 }
410 let lifetime_text = lifetime_token.text();
411 let lifetime_param = lifetime_token.parent().ancestors().find_map(|syn| {
412 let gpl = match_ast! {
413 match syn {
414 ast::Fn(it) => it.generic_param_list()?,
415 ast::TypeAlias(it) => it.generic_param_list()?,
416 ast::Struct(it) => it.generic_param_list()?,
417 ast::Enum(it) => it.generic_param_list()?,
418 ast::Union(it) => it.generic_param_list()?,
419 ast::Trait(it) => it.generic_param_list()?,
420 ast::Impl(it) => it.generic_param_list()?,
421 ast::WherePred(it) => it.generic_param_list()?,
422 ast::ForType(it) => it.generic_param_list()?,
423 _ => return None,
424 }
425 };
426 gpl.lifetime_params()
427 .find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text))
428 })?;
429 let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param);
430 ToDef::to_def(self, src)
431 }
432
395 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 433 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
396 self.analyze(expr.syntax()).type_of_expr(self.db, &expr) 434 self.analyze(expr.syntax()).type_of_expr(self.db, expr)
397 } 435 }
398 436
399 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { 437 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
400 self.analyze(pat.syntax()).type_of_pat(self.db, &pat) 438 self.analyze(pat.syntax()).type_of_pat(self.db, pat)
401 } 439 }
402 440
403 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { 441 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
404 self.analyze(param.syntax()).type_of_self(self.db, &param) 442 self.analyze(param.syntax()).type_of_self(self.db, param)
405 } 443 }
406 444
407 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 445 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
@@ -684,7 +722,8 @@ to_def_impls![
684 (crate::Field, ast::TupleField, tuple_field_to_def), 722 (crate::Field, ast::TupleField, tuple_field_to_def),
685 (crate::EnumVariant, ast::Variant, enum_variant_to_def), 723 (crate::EnumVariant, ast::Variant, enum_variant_to_def),
686 (crate::TypeParam, ast::TypeParam, type_param_to_def), 724 (crate::TypeParam, ast::TypeParam, type_param_to_def),
687 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros 725 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
726 (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
688 (crate::Local, ast::IdentPat, bind_pat_to_def), 727 (crate::Local, ast::IdentPat, bind_pat_to_def),
689]; 728];
690 729
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 66fc11611..a333d7aea 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -7,7 +7,8 @@ use hir_def::{
7 expr::PatId, 7 expr::PatId,
8 keys::{self, Key}, 8 keys::{self, Key},
9 ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, 9 ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
10 ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, 10 LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
11 VariantId,
11}; 12};
12use hir_expand::{name::AsName, AstId, MacroDefKind}; 13use hir_expand::{name::AsName, AstId, MacroDefKind};
13use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
@@ -128,15 +129,30 @@ impl SourceToDefCtx<'_, '_> {
128 129
129 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { 130 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
130 let container: ChildContainer = 131 let container: ChildContainer =
131 self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into(); 132 self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
132 let db = self.db; 133 let db = self.db;
133 let dyn_map = 134 let dyn_map =
134 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); 135 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
135 dyn_map[keys::TYPE_PARAM].get(&src).copied() 136 dyn_map[keys::TYPE_PARAM].get(&src).copied()
136 } 137 }
137 138
139 pub(super) fn lifetime_param_to_def(
140 &mut self,
141 src: InFile<ast::LifetimeParam>,
142 ) -> Option<LifetimeParamId> {
143 let container: ChildContainer =
144 self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
145 let db = self.db;
146 let dyn_map =
147 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
148 dyn_map[keys::LIFETIME_PARAM].get(&src).copied()
149 }
150
138 // FIXME: use DynMap as well? 151 // FIXME: use DynMap as well?
139 pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { 152 pub(super) fn macro_rules_to_def(
153 &mut self,
154 src: InFile<ast::MacroRules>,
155 ) -> Option<MacroDefId> {
140 let kind = MacroDefKind::Declarative; 156 let kind = MacroDefKind::Declarative;
141 let file_id = src.file_id.original_file(self.db.upcast()); 157 let file_id = src.file_id.original_file(self.db.upcast());
142 let krate = self.file_to_def(file_id)?.krate; 158 let krate = self.file_to_def(file_id)?.krate;
@@ -203,7 +219,7 @@ impl SourceToDefCtx<'_, '_> {
203 Some(def.into()) 219 Some(def.into())
204 } 220 }
205 221
206 fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { 222 fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
207 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { 223 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
208 let res: GenericDefId = match_ast! { 224 let res: GenericDefId = match_ast! {
209 match (container.value) { 225 match (container.value) {
@@ -247,7 +263,7 @@ pub(crate) enum ChildContainer {
247 VariantId(VariantId), 263 VariantId(VariantId),
248 TypeAliasId(TypeAliasId), 264 TypeAliasId(TypeAliasId),
249 /// XXX: this might be the same def as, for example an `EnumId`. However, 265 /// XXX: this might be the same def as, for example an `EnumId`. However,
250 /// here the children generic parameters, and not, eg enum variants. 266 /// here the children are generic parameters, and not, eg enum variants.
251 GenericDefId(GenericDefId), 267 GenericDefId(GenericDefId),
252} 268}
253impl_from! { 269impl_from! {
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 6539959c3..eafa3abb6 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -145,10 +145,12 @@ impl EnumData {
145 } 145 }
146} 146}
147 147
148impl HasChildSource for EnumId { 148impl HasChildSource<LocalEnumVariantId> for EnumId {
149 type ChildId = LocalEnumVariantId;
150 type Value = ast::Variant; 149 type Value = ast::Variant;
151 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 150 fn child_source(
151 &self,
152 db: &dyn DefDatabase,
153 ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
152 let src = self.lookup(db).source(db); 154 let src = self.lookup(db).source(db);
153 let mut trace = Trace::new_for_map(); 155 let mut trace = Trace::new_for_map();
154 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); 156 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db));
@@ -212,11 +214,10 @@ impl VariantData {
212 } 214 }
213} 215}
214 216
215impl HasChildSource for VariantId { 217impl HasChildSource<LocalFieldId> for VariantId {
216 type ChildId = LocalFieldId;
217 type Value = Either<ast::TupleField, ast::RecordField>; 218 type Value = Either<ast::TupleField, ast::RecordField>;
218 219
219 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 220 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
220 let (src, module_id) = match self { 221 let (src, module_id) = match self {
221 VariantId::EnumVariantId(it) => { 222 VariantId::EnumVariantId(it) => {
222 // I don't really like the fact that we call into parent source 223 // I don't really like the fact that we call into parent source
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 689a3274c..bdba4c33e 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -548,63 +548,70 @@ impl ExprCollector<'_> {
548 } 548 }
549 } 549 }
550 ast::Expr::MacroCall(e) => { 550 ast::Expr::MacroCall(e) => {
551 if let Some(name) = e.is_macro_rules().map(|it| it.as_name()) { 551 let mut ids = vec![];
552 let mac = MacroDefId { 552 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| {
553 krate: Some(self.expander.module.krate), 553 ids.push(match expansion {
554 ast_id: Some(self.expander.ast_id(&e)), 554 Some(it) => this.collect_expr(it),
555 kind: MacroDefKind::Declarative, 555 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
556 local_inner: false, 556 })
557 }; 557 });
558 self.body.item_scope.define_legacy_macro(name, mac); 558 ids[0]
559 }
560 }
561 }
559 562
560 // FIXME: do we still need to allocate this as missing ? 563 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
561 self.alloc_expr(Expr::Missing, syntax_ptr) 564 &mut self,
565 e: ast::MacroCall,
566 syntax_ptr: AstPtr<ast::Expr>,
567 mut collector: F,
568 ) {
569 // File containing the macro call. Expansion errors will be attached here.
570 let outer_file = self.expander.current_file_id;
571
572 let macro_call = self.expander.to_source(AstPtr::new(&e));
573 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
574
575 match &res.err {
576 Some(ExpandError::UnresolvedProcMacro) => {
577 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
578 UnresolvedProcMacro {
579 file: outer_file,
580 node: syntax_ptr.into(),
581 precise_location: None,
582 macro_name: None,
583 },
584 ));
585 }
586 Some(err) => {
587 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(MacroError {
588 file: outer_file,
589 node: syntax_ptr.into(),
590 message: err.to_string(),
591 }));
592 }
593 None => {}
594 }
595
596 match res.value {
597 Some((mark, expansion)) => {
598 // FIXME: Statements are too complicated to recover from error for now.
599 // It is because we don't have any hygenine for local variable expansion right now.
600 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() {
601 self.expander.exit(self.db, mark);
602 collector(self, None);
562 } else { 603 } else {
563 // File containing the macro call. Expansion errors will be attached here. 604 self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
564 let outer_file = self.expander.current_file_id;
565
566 let macro_call = self.expander.to_source(AstPtr::new(&e));
567 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
568
569 match res.err {
570 Some(ExpandError::UnresolvedProcMacro) => {
571 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
572 UnresolvedProcMacro {
573 file: outer_file,
574 node: syntax_ptr.clone().into(),
575 precise_location: None,
576 macro_name: None,
577 },
578 ));
579 }
580 Some(err) => {
581 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(
582 MacroError {
583 file: outer_file,
584 node: syntax_ptr.clone().into(),
585 message: err.to_string(),
586 },
587 ));
588 }
589 None => {}
590 }
591 605
592 match res.value { 606 let item_tree = self.db.item_tree(self.expander.current_file_id);
593 Some((mark, expansion)) => { 607 self.item_trees.insert(self.expander.current_file_id, item_tree);
594 self.source_map 608
595 .expansions 609 let id = collector(self, Some(expansion));
596 .insert(macro_call, self.expander.current_file_id); 610 self.expander.exit(self.db, mark);
597 611 id
598 let item_tree = self.db.item_tree(self.expander.current_file_id);
599 self.item_trees.insert(self.expander.current_file_id, item_tree);
600 let id = self.collect_expr(expansion);
601 self.expander.exit(self.db, mark);
602 id
603 }
604 None => self.alloc_expr(Expr::Missing, syntax_ptr),
605 }
606 } 612 }
607 } 613 }
614 None => collector(self, None),
608 } 615 }
609 } 616 }
610 617
@@ -642,44 +649,75 @@ impl ExprCollector<'_> {
642 } 649 }
643 } 650 }
644 651
645 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 652 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
646 let syntax_node_ptr = AstPtr::new(&block.clone().into()); 653 let stmt =
647 self.collect_block_items(&block); 654 match s {
648 let statements = block 655 ast::Stmt::LetStmt(stmt) => {
649 .statements() 656 self.check_cfg(&stmt)?;
650 .filter_map(|s| {
651 let stmt = match s {
652 ast::Stmt::LetStmt(stmt) => {
653 self.check_cfg(&stmt)?;
654
655 let pat = self.collect_pat_opt(stmt.pat());
656 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
657 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
658 Statement::Let { pat, type_ref, initializer }
659 }
660 ast::Stmt::ExprStmt(stmt) => {
661 self.check_cfg(&stmt)?;
662 657
663 Statement::Expr(self.collect_expr_opt(stmt.expr())) 658 let pat = self.collect_pat_opt(stmt.pat());
664 } 659 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
665 ast::Stmt::Item(item) => { 660 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
666 self.check_cfg(&item)?; 661 vec![Statement::Let { pat, type_ref, initializer }]
662 }
663 ast::Stmt::ExprStmt(stmt) => {
664 self.check_cfg(&stmt)?;
665
666 // Note that macro could be expended to multiple statements
667 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
668 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
669 let mut stmts = vec![];
670
671 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| {
672 match expansion {
673 Some(expansion) => {
674 let statements: ast::MacroStmts = expansion;
675 this.collect_stmts_items(statements.statements());
667 676
668 return None; 677 statements.statements().for_each(|stmt| {
678 if let Some(mut r) = this.collect_stmt(stmt) {
679 stmts.append(&mut r);
680 }
681 });
682 if let Some(expr) = statements.expr() {
683 stmts.push(Statement::Expr(this.collect_expr(expr)));
684 }
685 }
686 None => {
687 stmts.push(Statement::Expr(
688 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
689 ));
690 }
691 }
692 });
693 stmts
694 } else {
695 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
669 } 696 }
670 }; 697 }
671 Some(stmt) 698 ast::Stmt::Item(item) => {
672 }) 699 self.check_cfg(&item)?;
673 .collect(); 700
701 return None;
702 }
703 };
704
705 Some(stmt)
706 }
707
708 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
709 let syntax_node_ptr = AstPtr::new(&block.clone().into());
710 self.collect_stmts_items(block.statements());
711 let statements =
712 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
674 let tail = block.expr().map(|e| self.collect_expr(e)); 713 let tail = block.expr().map(|e| self.collect_expr(e));
675 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) 714 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr)
676 } 715 }
677 716
678 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 717 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
679 let container = ContainerId::DefWithBodyId(self.def); 718 let container = ContainerId::DefWithBodyId(self.def);
680 719
681 let items = block 720 let items = stmts
682 .statements()
683 .filter_map(|stmt| match stmt { 721 .filter_map(|stmt| match stmt {
684 ast::Stmt::Item(it) => Some(it), 722 ast::Stmt::Item(it) => Some(it),
685 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None, 723 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
@@ -733,26 +771,44 @@ impl ExprCollector<'_> {
733 | ast::Item::ExternCrate(_) 771 | ast::Item::ExternCrate(_)
734 | ast::Item::Module(_) 772 | ast::Item::Module(_)
735 | ast::Item::MacroCall(_) => return None, 773 | ast::Item::MacroCall(_) => return None,
774 ast::Item::MacroRules(def) => {
775 return Some(Either::Right(def));
776 }
736 }; 777 };
737 778
738 Some((def, name)) 779 Some(Either::Left((def, name)))
739 }) 780 })
740 .collect::<Vec<_>>(); 781 .collect::<Vec<_>>();
741 782
742 for (def, name) in items { 783 for either in items {
743 self.body.item_scope.define_def(def); 784 match either {
744 if let Some(name) = name { 785 Either::Left((def, name)) => {
745 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 786 self.body.item_scope.define_def(def);
746 let has_constructor = match def { 787 if let Some(name) = name {
747 ModuleDefId::AdtId(AdtId::StructId(s)) => { 788 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
748 self.db.struct_data(s).variant_data.kind() != StructKind::Record 789 let has_constructor = match def {
790 ModuleDefId::AdtId(AdtId::StructId(s)) => {
791 self.db.struct_data(s).variant_data.kind() != StructKind::Record
792 }
793 _ => true,
794 };
795 self.body.item_scope.push_res(
796 name.as_name(),
797 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
798 );
749 } 799 }
750 _ => true, 800 }
751 }; 801 Either::Right(e) => {
752 self.body.item_scope.push_res( 802 let mac = MacroDefId {
753 name.as_name(), 803 krate: Some(self.expander.module.krate),
754 crate::per_ns::PerNs::from_def(def, vis, has_constructor), 804 ast_id: Some(self.expander.ast_id(&e)),
755 ); 805 kind: MacroDefKind::Declarative,
806 local_inner: false,
807 };
808 if let Some(name) = e.name() {
809 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
810 }
811 }
756 } 812 }
757 } 813 }
758 } 814 }
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 5189c7e9f..924046435 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -19,10 +19,10 @@ use crate::{
19 db::DefDatabase, 19 db::DefDatabase,
20 dyn_map::DynMap, 20 dyn_map::DynMap,
21 keys, 21 keys,
22 src::HasChildSource, 22 src::{HasChildSource, HasSource},
23 src::HasSource,
24 type_ref::{LifetimeRef, TypeBound, TypeRef}, 23 type_ref::{LifetimeRef, TypeBound, TypeRef},
25 AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, 24 AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup,
25 TypeParamId,
26}; 26};
27 27
28/// Data about a generic parameter (to a function, struct, impl, ...). 28/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -72,7 +72,11 @@ pub enum WherePredicateTypeTarget {
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef) 72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; 75#[derive(Default)]
76pub(crate) struct SourceMap {
77 pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
78 lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
79}
76 80
77impl GenericParams { 81impl GenericParams {
78 pub(crate) fn generic_params_query( 82 pub(crate) fn generic_params_query(
@@ -131,7 +135,7 @@ impl GenericParams {
131 135
132 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 136 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
133 let mut generics = GenericParams::default(); 137 let mut generics = GenericParams::default();
134 let mut sm = ArenaMap::default(); 138 let mut sm = SourceMap::default();
135 139
136 // FIXME: add `: Sized` bound for everything except for `Self` in traits 140 // FIXME: add `: Sized` bound for everything except for `Self` in traits
137 let file_id = match def { 141 let file_id = match def {
@@ -174,7 +178,7 @@ impl GenericParams {
174 default: None, 178 default: None,
175 provenance: TypeParamProvenance::TraitSelf, 179 provenance: TypeParamProvenance::TraitSelf,
176 }); 180 });
177 sm.insert(self_param_id, Either::Left(src.value.clone())); 181 sm.type_params.insert(self_param_id, Either::Left(src.value.clone()));
178 // add super traits as bounds on Self 182 // add super traits as bounds on Self
179 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 183 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
180 let self_param = TypeRef::Path(name![Self].into()); 184 let self_param = TypeRef::Path(name![Self].into());
@@ -250,7 +254,7 @@ impl GenericParams {
250 provenance: TypeParamProvenance::TypeParamList, 254 provenance: TypeParamProvenance::TypeParamList,
251 }; 255 };
252 let param_id = self.types.alloc(param); 256 let param_id = self.types.alloc(param);
253 sm.insert(param_id, Either::Right(type_param.clone())); 257 sm.type_params.insert(param_id, Either::Right(type_param.clone()));
254 258
255 let type_ref = TypeRef::Path(name.into()); 259 let type_ref = TypeRef::Path(name.into());
256 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); 260 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
@@ -260,7 +264,8 @@ impl GenericParams {
260 .lifetime_token() 264 .lifetime_token()
261 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); 265 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
262 let param = LifetimeParamData { name: name.clone() }; 266 let param = LifetimeParamData { name: name.clone() };
263 let _param_id = self.lifetimes.alloc(param); 267 let param_id = self.lifetimes.alloc(param);
268 sm.lifetime_params.insert(param_id, lifetime_param.clone());
264 let lifetime_ref = LifetimeRef::new_name(name); 269 let lifetime_ref = LifetimeRef::new_name(name);
265 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); 270 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
266 } 271 }
@@ -341,26 +346,42 @@ impl GenericParams {
341 } 346 }
342} 347}
343 348
344impl HasChildSource for GenericDefId { 349impl HasChildSource<LocalTypeParamId> for GenericDefId {
345 type ChildId = LocalTypeParamId;
346 type Value = Either<ast::Trait, ast::TypeParam>; 350 type Value = Either<ast::Trait, ast::TypeParam>;
347 fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> { 351 fn child_source(
348 let (_, sm) = GenericParams::new(db, *self); 352 &self,
349 sm 353 db: &dyn DefDatabase,
354 ) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
355 GenericParams::new(db, *self).1.map(|source_maps| source_maps.type_params)
356 }
357}
358
359impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
360 type Value = ast::LifetimeParam;
361 fn child_source(
362 &self,
363 db: &dyn DefDatabase,
364 ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
365 GenericParams::new(db, *self).1.map(|source_maps| source_maps.lifetime_params)
350 } 366 }
351} 367}
352 368
353impl ChildBySource for GenericDefId { 369impl ChildBySource for GenericDefId {
354 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 370 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
355 let mut res = DynMap::default(); 371 let mut res = DynMap::default();
356 let arena_map = self.child_source(db); 372 let (_, sm) = GenericParams::new(db, *self);
357 let arena_map = arena_map.as_ref(); 373
358 for (local_id, src) in arena_map.value.iter() { 374 let sm = sm.as_ref();
375 for (local_id, src) in sm.value.type_params.iter() {
359 let id = TypeParamId { parent: *self, local_id }; 376 let id = TypeParamId { parent: *self, local_id };
360 if let Either::Right(type_param) = src { 377 if let Either::Right(type_param) = src {
361 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) 378 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
362 } 379 }
363 } 380 }
381 for (local_id, src) in sm.value.lifetime_params.iter() {
382 let id = LifetimeParamId { parent: *self, local_id };
383 res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
384 }
364 res 385 res
365 } 386 }
366} 387}
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b08167281..1c9babf37 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -94,6 +94,9 @@ impl ItemTree {
94 ast::MacroItems(items) => { 94 ast::MacroItems(items) => {
95 ctx.lower_module_items(&items) 95 ctx.lower_module_items(&items)
96 }, 96 },
97 ast::MacroStmts(stmts) => {
98 ctx.lower_inner_items(stmts.syntax())
99 },
97 // Macros can expand to expressions. We return an empty item tree in this case, but 100 // Macros can expand to expressions. We return an empty item tree in this case, but
98 // still need to collect inner items. 101 // still need to collect inner items.
99 ast::Expr(e) => { 102 ast::Expr(e) => {
@@ -139,6 +142,7 @@ impl ItemTree {
139 type_aliases, 142 type_aliases,
140 mods, 143 mods,
141 macro_calls, 144 macro_calls,
145 macro_rules,
142 exprs, 146 exprs,
143 vis, 147 vis,
144 generics, 148 generics,
@@ -159,6 +163,7 @@ impl ItemTree {
159 type_aliases.shrink_to_fit(); 163 type_aliases.shrink_to_fit();
160 mods.shrink_to_fit(); 164 mods.shrink_to_fit();
161 macro_calls.shrink_to_fit(); 165 macro_calls.shrink_to_fit();
166 macro_rules.shrink_to_fit();
162 exprs.shrink_to_fit(); 167 exprs.shrink_to_fit();
163 168
164 vis.arena.shrink_to_fit(); 169 vis.arena.shrink_to_fit();
@@ -277,6 +282,7 @@ struct ItemTreeData {
277 type_aliases: Arena<TypeAlias>, 282 type_aliases: Arena<TypeAlias>,
278 mods: Arena<Mod>, 283 mods: Arena<Mod>,
279 macro_calls: Arena<MacroCall>, 284 macro_calls: Arena<MacroCall>,
285 macro_rules: Arena<MacroRules>,
280 exprs: Arena<Expr>, 286 exprs: Arena<Expr>,
281 287
282 vis: ItemVisibilities, 288 vis: ItemVisibilities,
@@ -424,6 +430,7 @@ mod_items! {
424 TypeAlias in type_aliases -> ast::TypeAlias, 430 TypeAlias in type_aliases -> ast::TypeAlias,
425 Mod in mods -> ast::Module, 431 Mod in mods -> ast::Module,
426 MacroCall in macro_calls -> ast::MacroCall, 432 MacroCall in macro_calls -> ast::MacroCall,
433 MacroRules in macro_rules -> ast::MacroRules,
427} 434}
428 435
429macro_rules! impl_index { 436macro_rules! impl_index {
@@ -626,17 +633,22 @@ pub enum ModKind {
626 633
627#[derive(Debug, Clone, Eq, PartialEq)] 634#[derive(Debug, Clone, Eq, PartialEq)]
628pub struct MacroCall { 635pub struct MacroCall {
629 /// For `macro_rules!` declarations, this is the name of the declared macro.
630 pub name: Option<Name>,
631 /// Path to the called macro. 636 /// Path to the called macro.
632 pub path: ModPath, 637 pub path: ModPath,
638 pub ast_id: FileAstId<ast::MacroCall>,
639}
640
641#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules {
643 /// For `macro_rules!` declarations, this is the name of the declared macro.
644 pub name: Name,
633 /// Has `#[macro_export]`. 645 /// Has `#[macro_export]`.
634 pub is_export: bool, 646 pub is_export: bool,
635 /// Has `#[macro_export(local_inner_macros)]`. 647 /// Has `#[macro_export(local_inner_macros)]`.
636 pub is_local_inner: bool, 648 pub is_local_inner: bool,
637 /// Has `#[rustc_builtin_macro]`. 649 /// Has `#[rustc_builtin_macro]`.
638 pub is_builtin: bool, 650 pub is_builtin: bool,
639 pub ast_id: FileAstId<ast::MacroCall>, 651 pub ast_id: FileAstId<ast::MacroRules>,
640} 652}
641 653
642// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array 654// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
@@ -667,7 +679,8 @@ impl ModItem {
667 | ModItem::Static(_) 679 | ModItem::Static(_)
668 | ModItem::Trait(_) 680 | ModItem::Trait(_)
669 | ModItem::Impl(_) 681 | ModItem::Impl(_)
670 | ModItem::Mod(_) => None, 682 | ModItem::Mod(_)
683 | ModItem::MacroRules(_) => None,
671 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), 684 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
672 ModItem::Const(konst) => Some(AssocItem::Const(*konst)), 685 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
673 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), 686 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -694,6 +707,7 @@ impl ModItem {
694 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(), 707 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
695 ModItem::Mod(it) => tree[it.index].ast_id().upcast(), 708 ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
696 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), 709 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
697 } 711 }
698 } 712 }
699} 713}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index f7ce2e26d..b39d7fb7a 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -2,7 +2,6 @@
2 2
3use std::{collections::hash_map::Entry, mem, sync::Arc}; 3use std::{collections::hash_map::Entry, mem, sync::Arc};
4 4
5use arena::map::ArenaMap;
6use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; 5use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
7use smallvec::SmallVec; 6use smallvec::SmallVec;
8use syntax::{ 7use syntax::{
@@ -85,8 +84,7 @@ impl Ctx {
85 | ast::Item::Fn(_) 84 | ast::Item::Fn(_)
86 | ast::Item::TypeAlias(_) 85 | ast::Item::TypeAlias(_)
87 | ast::Item::Const(_) 86 | ast::Item::Const(_)
88 | ast::Item::Static(_) 87 | ast::Item::Static(_) => {
89 | ast::Item::MacroCall(_) => {
90 // Skip this if we're already collecting inner items. We'll descend into all nodes 88 // Skip this if we're already collecting inner items. We'll descend into all nodes
91 // already. 89 // already.
92 if !inner { 90 if !inner {
@@ -99,7 +97,11 @@ impl Ctx {
99 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} 97 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {}
100 98
101 // These don't have inner items. 99 // These don't have inner items.
102 ast::Item::Module(_) | ast::Item::ExternCrate(_) | ast::Item::Use(_) => {} 100 ast::Item::Module(_)
101 | ast::Item::ExternCrate(_)
102 | ast::Item::Use(_)
103 | ast::Item::MacroCall(_)
104 | ast::Item::MacroRules(_) => {}
103 }; 105 };
104 106
105 let attrs = Attrs::new(item, &self.hygiene); 107 let attrs = Attrs::new(item, &self.hygiene);
@@ -119,6 +121,7 @@ impl Ctx {
119 )), 121 )),
120 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), 122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
121 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
122 ast::Item::ExternBlock(ast) => { 125 ast::Item::ExternBlock(ast) => {
123 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) 126 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
124 } 127 }
@@ -526,9 +529,15 @@ impl Ctx {
526 } 529 }
527 530
528 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 531 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
529 let name = m.name().map(|it| it.as_name());
530 let attrs = Attrs::new(m, &self.hygiene);
531 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 532 let path = ModPath::from_src(m.path()?, &self.hygiene)?;
533 let ast_id = self.source_ast_id_map.ast_id(m);
534 let res = MacroCall { path, ast_id };
535 Some(id(self.data().macro_calls.alloc(res)))
536 }
537
538 fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
539 let name = m.name().map(|it| it.as_name())?;
540 let attrs = Attrs::new(m, &self.hygiene);
532 541
533 let ast_id = self.source_ast_id_map.ast_id(m); 542 let ast_id = self.source_ast_id_map.ast_id(m);
534 543
@@ -548,8 +557,8 @@ impl Ctx {
548 }; 557 };
549 558
550 let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); 559 let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
551 let res = MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }; 560 let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id };
552 Some(id(self.data().macro_calls.alloc(res))) 561 Some(id(self.data().macro_rules.alloc(res)))
553 } 562 }
554 563
555 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 564 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
@@ -607,7 +616,7 @@ impl Ctx {
607 owner: GenericsOwner<'_>, 616 owner: GenericsOwner<'_>,
608 node: &impl ast::GenericParamsOwner, 617 node: &impl ast::GenericParamsOwner,
609 ) -> GenericParamsId { 618 ) -> GenericParamsId {
610 let mut sm = &mut ArenaMap::default(); 619 let mut sm = &mut Default::default();
611 let mut generics = GenericParams::default(); 620 let mut generics = GenericParams::default();
612 match owner { 621 match owner {
613 GenericsOwner::Function(func) => { 622 GenericsOwner::Function(func) => {
@@ -630,7 +639,7 @@ impl Ctx {
630 default: None, 639 default: None,
631 provenance: TypeParamProvenance::TraitSelf, 640 provenance: TypeParamProvenance::TraitSelf,
632 }); 641 });
633 sm.insert(self_param_id, Either::Left(trait_def.clone())); 642 sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
634 // add super traits as bounds on Self 643 // add super traits as bounds on Self
635 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 644 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
636 let self_param = TypeRef::Path(name![Self].into()); 645 let self_param = TypeRef::Path(name![Self].into());
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs
index 40a5d92b5..9c585de2c 100644
--- a/crates/hir_def/src/keys.rs
+++ b/crates/hir_def/src/keys.rs
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
8 8
9use crate::{ 9use crate::{
10 dyn_map::{DynMap, Policy}, 10 dyn_map::{DynMap, Policy},
11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, StaticId, StructId, TraitId, 11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
12 TypeAliasId, TypeParamId, UnionId, 12 StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
13}; 13};
14 14
15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; 15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -28,6 +28,7 @@ pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); 28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); 29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); 30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
31 32
32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); 33pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
33 34
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 19cd713ba..85cc342c4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -11,7 +11,7 @@ use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_derive::find_builtin_derive, 12 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
17}; 17};
@@ -25,7 +25,9 @@ use crate::{
25 attr::Attrs, 25 attr::Attrs,
26 db::DefDatabase, 26 db::DefDatabase,
27 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind}, 28 item_tree::{
29 self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind,
30 },
29 nameres::{ 31 nameres::{
30 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 32 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
31 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 33 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -972,7 +974,8 @@ impl ModCollector<'_, '_> {
972 status: PartialResolvedImport::Unresolved, 974 status: PartialResolvedImport::Unresolved,
973 }) 975 })
974 } 976 }
975 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]), 977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]),
976 ModItem::Impl(imp) => { 979 ModItem::Impl(imp) => {
977 let module = ModuleId { 980 let module = ModuleId {
978 krate: self.def_collector.def_map.krate, 981 krate: self.def_collector.def_map.krate,
@@ -1276,45 +1279,37 @@ impl ModCollector<'_, '_> {
1276 self.def_collector.resolve_proc_macro(&macro_name); 1279 self.def_collector.resolve_proc_macro(&macro_name);
1277 } 1280 }
1278 1281
1279 fn collect_macro(&mut self, mac: &MacroCall) { 1282 fn collect_macro_rules(&mut self, mac: &MacroRules) {
1280 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1283 let ast_id = InFile::new(self.file_id, mac.ast_id);
1281 1284
1282 // Case 0: builtin macros 1285 // Case 1: builtin macros
1283 if mac.is_builtin { 1286 if mac.is_builtin {
1284 if let Some(name) = &mac.name { 1287 let krate = self.def_collector.def_map.krate;
1285 let krate = self.def_collector.def_map.krate; 1288 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
1286 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) {
1287 self.def_collector.define_macro(
1288 self.module_id,
1289 name.clone(),
1290 macro_id,
1291 mac.is_export,
1292 );
1293 return;
1294 }
1295 }
1296 }
1297
1298 // Case 1: macro rules, define a macro in crate-global mutable scope
1299 if is_macro_rules(&mac.path) {
1300 if let Some(name) = &mac.name {
1301 let macro_id = MacroDefId {
1302 ast_id: Some(ast_id.ast_id),
1303 krate: Some(self.def_collector.def_map.krate),
1304 kind: MacroDefKind::Declarative,
1305 local_inner: mac.is_local_inner,
1306 };
1307 self.def_collector.define_macro( 1289 self.def_collector.define_macro(
1308 self.module_id, 1290 self.module_id,
1309 name.clone(), 1291 mac.name.clone(),
1310 macro_id, 1292 macro_id,
1311 mac.is_export, 1293 mac.is_export,
1312 ); 1294 );
1295 return;
1313 } 1296 }
1314 return;
1315 } 1297 }
1316 1298
1317 // Case 2: try to resolve in legacy scope and expand macro_rules 1299 // Case 2: normal `macro_rules!` macro
1300 let macro_id = MacroDefId {
1301 ast_id: Some(ast_id),
1302 krate: Some(self.def_collector.def_map.krate),
1303 kind: MacroDefKind::Declarative,
1304 local_inner: mac.is_local_inner,
1305 };
1306 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export);
1307 }
1308
1309 fn collect_macro_call(&mut self, mac: &MacroCall) {
1310 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1311
1312 // Case 1: try to resolve in legacy scope and expand macro_rules
1318 if let Some(macro_call_id) = 1313 if let Some(macro_call_id) =
1319 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1314 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
1320 path.as_ident().and_then(|name| { 1315 path.as_ident().and_then(|name| {
@@ -1332,7 +1327,7 @@ impl ModCollector<'_, '_> {
1332 return; 1327 return;
1333 } 1328 }
1334 1329
1335 // Case 3: resolve in module scope, expand during name resolution. 1330 // Case 2: resolve in module scope, expand during name resolution.
1336 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. 1331 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
1337 if ast_id.path.is_ident() { 1332 if ast_id.path.is_ident() {
1338 ast_id.path.kind = PathKind::Super(0); 1333 ast_id.path.kind = PathKind::Super(0);
@@ -1370,10 +1365,6 @@ impl ModCollector<'_, '_> {
1370 } 1365 }
1371} 1366}
1372 1367
1373fn is_macro_rules(path: &ModPath) -> bool {
1374 path.as_ident() == Some(&name![macro_rules])
1375}
1376
1377#[cfg(test)] 1368#[cfg(test)]
1378mod tests { 1369mod tests {
1379 use crate::{db::DefDatabase, test_db::TestDB}; 1370 use crate::{db::DefDatabase, test_db::TestDB};
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 60fa7646b..609925012 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -122,11 +122,9 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :) 123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain { 124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { 125 if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() { 126 if let Some(crate_id) = hygiene.local_inner_macros() {
127 if let Some(crate_id) = hygiene.local_inner_macros() { 127 kind = PathKind::DollarCrate(crate_id);
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 } 128 }
131 } 129 }
132 } 130 }
diff --git a/crates/hir_def/src/src.rs b/crates/hir_def/src/src.rs
index 7a79b0314..f67244b46 100644
--- a/crates/hir_def/src/src.rs
+++ b/crates/hir_def/src/src.rs
@@ -36,8 +36,7 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
36 } 36 }
37} 37}
38 38
39pub trait HasChildSource { 39pub trait HasChildSource<ChildId> {
40 type ChildId;
41 type Value; 40 type Value;
42 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>>; 41 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
43} 42}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 477192a09..bd9223825 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -63,7 +63,7 @@ macro_rules! register_builtin {
63pub fn find_builtin_macro( 63pub fn find_builtin_macro(
64 ident: &name::Name, 64 ident: &name::Name,
65 krate: CrateId, 65 krate: CrateId,
66 ast_id: AstId<ast::MacroCall>, 66 ast_id: AstId<ast::MacroRules>,
67) -> Option<MacroDefId> { 67) -> Option<MacroDefId> {
68 let kind = find_by_name(ident)?; 68 let kind = find_by_name(ident)?;
69 69
@@ -88,12 +88,15 @@ register_builtin! {
88 (column, Column) => column_expand, 88 (column, Column) => column_expand,
89 (file, File) => file_expand, 89 (file, File) => file_expand,
90 (line, Line) => line_expand, 90 (line, Line) => line_expand,
91 (module_path, ModulePath) => module_path_expand,
91 (assert, Assert) => assert_expand, 92 (assert, Assert) => assert_expand,
92 (stringify, Stringify) => stringify_expand, 93 (stringify, Stringify) => stringify_expand,
93 (format_args, FormatArgs) => format_args_expand, 94 (format_args, FormatArgs) => format_args_expand,
94 // format_args_nl only differs in that it adds a newline in the end, 95 // format_args_nl only differs in that it adds a newline in the end,
95 // so we use the same stub expansion for now 96 // so we use the same stub expansion for now
96 (format_args_nl, FormatArgsNl) => format_args_expand, 97 (format_args_nl, FormatArgsNl) => format_args_expand,
98 (llvm_asm, LlvmAsm) => asm_expand,
99 (asm, Asm) => asm_expand,
97 100
98 EAGER: 101 EAGER:
99 (compile_error, CompileError) => compile_error_expand, 102 (compile_error, CompileError) => compile_error_expand,
@@ -105,6 +108,15 @@ register_builtin! {
105 (option_env, OptionEnv) => option_env_expand 108 (option_env, OptionEnv) => option_env_expand
106} 109}
107 110
111fn module_path_expand(
112 _db: &dyn AstDatabase,
113 _id: LazyMacroId,
114 _tt: &tt::Subtree,
115) -> ExpandResult<tt::Subtree> {
116 // Just return a dummy result.
117 ExpandResult::ok(quote! { "module::path" })
118}
119
108fn line_expand( 120fn line_expand(
109 _db: &dyn AstDatabase, 121 _db: &dyn AstDatabase,
110 _id: LazyMacroId, 122 _id: LazyMacroId,
@@ -261,6 +273,19 @@ fn format_args_expand(
261 ExpandResult::ok(expanded) 273 ExpandResult::ok(expanded)
262} 274}
263 275
276fn asm_expand(
277 _db: &dyn AstDatabase,
278 _id: LazyMacroId,
279 _tt: &tt::Subtree,
280) -> ExpandResult<tt::Subtree> {
281 // both asm and llvm_asm don't return anything, so we can expand them to nothing,
282 // for now
283 let expanded = quote! {
284 ()
285 };
286 ExpandResult::ok(expanded)
287}
288
264fn unquote_str(lit: &tt::Literal) -> Option<String> { 289fn unquote_str(lit: &tt::Literal) -> Option<String> {
265 let lit = ast::make::tokens::literal(&lit.to_string()); 290 let lit = ast::make::tokens::literal(&lit.to_string());
266 let token = ast::String::cast(lit)?; 291 let token = ast::String::cast(lit)?;
@@ -490,12 +515,16 @@ mod tests {
490 fn expand_builtin_macro(ra_fixture: &str) -> String { 515 fn expand_builtin_macro(ra_fixture: &str) -> String {
491 let (db, file_id) = TestDB::with_single_file(&ra_fixture); 516 let (db, file_id) = TestDB::with_single_file(&ra_fixture);
492 let parsed = db.parse(file_id); 517 let parsed = db.parse(file_id);
518 let macro_rules: Vec<_> =
519 parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect();
493 let macro_calls: Vec<_> = 520 let macro_calls: Vec<_> =
494 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); 521 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect();
495 522
496 let ast_id_map = db.ast_id_map(file_id.into()); 523 let ast_id_map = db.ast_id_map(file_id.into());
497 524
498 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap(); 525 assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`");
526 assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call");
527 let expander = find_by_name(&macro_rules[0].name().unwrap().as_name()).unwrap();
499 528
500 let krate = CrateId(0); 529 let krate = CrateId(0);
501 let file_id = match expander { 530 let file_id = match expander {
@@ -503,7 +532,7 @@ mod tests {
503 // the first one should be a macro_rules 532 // the first one should be a macro_rules
504 let def = MacroDefId { 533 let def = MacroDefId {
505 krate: Some(CrateId(0)), 534 krate: Some(CrateId(0)),
506 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 535 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))),
507 kind: MacroDefKind::BuiltIn(expander), 536 kind: MacroDefKind::BuiltIn(expander),
508 local_inner: false, 537 local_inner: false,
509 }; 538 };
@@ -513,7 +542,7 @@ mod tests {
513 krate, 542 krate,
514 kind: MacroCallKind::FnLike(AstId::new( 543 kind: MacroCallKind::FnLike(AstId::new(
515 file_id.into(), 544 file_id.into(),
516 ast_id_map.ast_id(&macro_calls[1]), 545 ast_id_map.ast_id(&macro_calls[0]),
517 )), 546 )),
518 }; 547 };
519 548
@@ -524,12 +553,12 @@ mod tests {
524 // the first one should be a macro_rules 553 // the first one should be a macro_rules
525 let def = MacroDefId { 554 let def = MacroDefId {
526 krate: Some(krate), 555 krate: Some(krate),
527 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 556 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))),
528 kind: MacroDefKind::BuiltInEager(expander), 557 kind: MacroDefKind::BuiltInEager(expander),
529 local_inner: false, 558 local_inner: false,
530 }; 559 };
531 560
532 let args = macro_calls[1].token_tree().unwrap(); 561 let args = macro_calls[0].token_tree().unwrap();
533 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; 562 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
534 563
535 let arg_id = db.intern_eager_expansion({ 564 let arg_id = db.intern_eager_expansion({
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index ffb70f723..11b5b98c8 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -394,8 +394,8 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
394 // FIXME: Handle Pattern 394 // FIXME: Handle Pattern
395 FragmentKind::Expr 395 FragmentKind::Expr
396 } 396 }
397 // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that 397 EXPR_STMT => FragmentKind::Statements,
398 EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr, 398 BLOCK_EXPR => FragmentKind::Expr,
399 ARG_LIST => FragmentKind::Expr, 399 ARG_LIST => FragmentKind::Expr,
400 TRY_EXPR => FragmentKind::Expr, 400 TRY_EXPR => FragmentKind::Expr,
401 TUPLE_EXPR => FragmentKind::Expr, 401 TUPLE_EXPR => FragmentKind::Expr,
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 1a9428514..ae3086a95 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -228,7 +228,7 @@ pub struct MacroDefId {
228 // (which will probably require touching this code), we can instead use 228 // (which will probably require touching this code), we can instead use
229 // that (and also remove the hacks for resolving built-in derives). 229 // that (and also remove the hacks for resolving built-in derives).
230 pub krate: Option<CrateId>, 230 pub krate: Option<CrateId>,
231 pub ast_id: Option<AstId<ast::MacroCall>>, 231 pub ast_id: Option<AstId<ast::MacroRules>>,
232 pub kind: MacroDefKind, 232 pub kind: MacroDefKind,
233 233
234 pub local_inner: bool, 234 pub local_inner: bool,
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 583ed6142..69d8e6803 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -188,6 +188,7 @@ pub mod known {
188 column, 188 column,
189 compile_error, 189 compile_error,
190 line, 190 line,
191 module_path,
191 assert, 192 assert,
192 stringify, 193 stringify,
193 concat, 194 concat,
@@ -198,6 +199,8 @@ pub mod known {
198 format_args_nl, 199 format_args_nl,
199 env, 200 env,
200 option_env, 201 option_env,
202 llvm_asm,
203 asm,
201 // Builtin derives 204 // Builtin derives
202 Copy, 205 Copy,
203 Clone, 206 Clone,
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 597a195d0..de97ec3c2 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -413,7 +413,6 @@ fn infer_local_macro() {
413 expect![[r#" 413 expect![[r#"
414 !0..6 '1usize': usize 414 !0..6 '1usize': usize
415 10..89 '{ ...!(); }': () 415 10..89 '{ ...!(); }': ()
416 16..65 'macro_... }': {unknown}
417 74..76 '_a': usize 416 74..76 '_a': usize
418 "#]], 417 "#]],
419 ); 418 );
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index da8170417..307a257b1 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -593,6 +593,30 @@ fn issue_4465_dollar_crate_at_type() {
593} 593}
594 594
595#[test] 595#[test]
596fn issue_6811() {
597 check_infer(
598 r#"
599 macro_rules! profile_function {
600 () => {
601 let _a = 1;
602 let _b = 1;
603 };
604 }
605 fn main() {
606 profile_function!();
607 }
608 "#,
609 expect![[r#"
610 !3..5 '_a': i32
611 !6..7 '1': i32
612 !11..13 '_b': i32
613 !14..15 '1': i32
614 103..131 '{ ...!(); }': ()
615 "#]],
616 );
617}
618
619#[test]
596fn issue_4053_diesel_where_clauses() { 620fn issue_4053_diesel_where_clauses() {
597 check_infer( 621 check_infer(
598 r#" 622 r#"
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 415795e8c..c51531391 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -150,13 +150,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
150 }; 150 };
151 Some(node) 151 Some(node)
152 }, 152 },
153 ast::MacroCall(it) => { 153 ast::MacroRules(it) => decl(it),
154 match it.path().and_then(|it| it.segment()).and_then(|it| it.name_ref()) {
155 Some(path_segment) if path_segment.text() == "macro_rules"
156 => decl(it),
157 _ => None,
158 }
159 },
160 _ => None, 154 _ => None,
161 } 155 }
162 } 156 }
@@ -380,7 +374,7 @@ fn very_obsolete() {}
380 label: "mc", 374 label: "mc",
381 navigation_range: 284..286, 375 navigation_range: 284..286,
382 node_range: 271..303, 376 node_range: 271..303,
383 kind: MACRO_CALL, 377 kind: MACRO_RULES,
384 detail: None, 378 detail: None,
385 deprecated: false, 379 deprecated: false,
386 }, 380 },
@@ -389,7 +383,7 @@ fn very_obsolete() {}
389 label: "mcexp", 383 label: "mcexp",
390 navigation_range: 334..339, 384 navigation_range: 334..339,
391 node_range: 305..356, 385 node_range: 305..356,
392 kind: MACRO_CALL, 386 kind: MACRO_RULES,
393 detail: None, 387 detail: None,
394 deprecated: false, 388 deprecated: false,
395 }, 389 },
@@ -398,7 +392,7 @@ fn very_obsolete() {}
398 label: "mcexp", 392 label: "mcexp",
399 navigation_range: 387..392, 393 navigation_range: 387..392,
400 node_range: 358..409, 394 node_range: 358..409,
401 kind: MACRO_CALL, 395 kind: MACRO_RULES,
402 detail: None, 396 detail: None,
403 deprecated: false, 397 deprecated: false,
404 }, 398 },
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 7395b81bd..675957fff 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -97,6 +97,9 @@ pub(crate) fn find_all_refs(
97 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) 97 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
98 { 98 {
99 (Some(name), ReferenceKind::StructLiteral) 99 (Some(name), ReferenceKind::StructLiteral)
100 } else if let Some(name) = get_enum_def_name_for_struct_literal_search(&sema, &syntax, position)
101 {
102 (Some(name), ReferenceKind::EnumLiteral)
100 } else { 103 } else {
101 ( 104 (
102 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), 105 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset),
@@ -198,6 +201,33 @@ fn get_struct_def_name_for_struct_literal_search(
198 None 201 None
199} 202}
200 203
204fn get_enum_def_name_for_struct_literal_search(
205 sema: &Semantics<RootDatabase>,
206 syntax: &SyntaxNode,
207 position: FilePosition,
208) -> Option<ast::Name> {
209 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) {
210 if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN {
211 return None;
212 }
213 if let Some(name) =
214 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start())
215 {
216 return name.syntax().ancestors().find_map(ast::Enum::cast).and_then(|l| l.name());
217 }
218 if sema
219 .find_node_at_offset_with_descend::<ast::GenericParamList>(
220 &syntax,
221 left.text_range().start(),
222 )
223 .is_some()
224 {
225 return left.ancestors().find_map(ast::Enum::cast).and_then(|l| l.name());
226 }
227 }
228 None
229}
230
201fn try_find_self_references( 231fn try_find_self_references(
202 syntax: &SyntaxNode, 232 syntax: &SyntaxNode,
203 position: FilePosition, 233 position: FilePosition,
@@ -357,6 +387,91 @@ fn main() {
357 } 387 }
358 388
359 #[test] 389 #[test]
390 fn test_enum_after_space() {
391 check(
392 r#"
393enum Foo <|>{
394 A,
395 B,
396}
397fn main() {
398 let f: Foo;
399 f = Foo::A;
400}
401"#,
402 expect![[r#"
403 Foo ENUM FileId(0) 0..26 5..8 Other
404
405 FileId(0) 63..66 EnumLiteral
406 "#]],
407 );
408 }
409
410 #[test]
411 fn test_enum_before_space() {
412 check(
413 r#"
414enum Foo<|> {
415 A,
416 B,
417}
418fn main() {
419 let f: Foo;
420 f = Foo::A;
421}
422"#,
423 expect![[r#"
424 Foo ENUM FileId(0) 0..26 5..8 Other
425
426 FileId(0) 50..53 Other
427 FileId(0) 63..66 EnumLiteral
428 "#]],
429 );
430 }
431
432 #[test]
433 fn test_enum_with_generic_type() {
434 check(
435 r#"
436enum Foo<T> <|>{
437 A(T),
438 B,
439}
440fn main() {
441 let f: Foo<i8>;
442 f = Foo::A(1);
443}
444"#,
445 expect![[r#"
446 Foo ENUM FileId(0) 0..32 5..8 Other
447
448 FileId(0) 73..76 EnumLiteral
449 "#]],
450 );
451 }
452
453 #[test]
454 fn test_enum_for_tuple() {
455 check(
456 r#"
457enum Foo<|>{
458 A(i8),
459 B(i8),
460}
461fn main() {
462 let f: Foo;
463 f = Foo::A(1);
464}
465"#,
466 expect![[r#"
467 Foo ENUM FileId(0) 0..33 5..8 Other
468
469 FileId(0) 70..73 EnumLiteral
470 "#]],
471 );
472 }
473
474 #[test]
360 fn test_find_all_refs_for_local() { 475 fn test_find_all_refs_for_local() {
361 check( 476 check(
362 r#" 477 r#"
@@ -655,7 +770,7 @@ fn foo() {
655} 770}
656"#, 771"#,
657 expect![[r#" 772 expect![[r#"
658 m1 MACRO_CALL FileId(0) 0..46 29..31 Other 773 m1 MACRO_RULES FileId(0) 0..46 29..31 Other
659 774
660 FileId(0) 63..65 StructLiteral 775 FileId(0) 63..65 StructLiteral
661 FileId(0) 73..75 StructLiteral 776 FileId(0) 73..75 StructLiteral
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index f5c6eabef..990b0f7d9 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -74,6 +74,7 @@ pub(crate) fn highlight(
74 let mut stack = HighlightedRangeStack::new(); 74 let mut stack = HighlightedRangeStack::new();
75 75
76 let mut current_macro_call: Option<ast::MacroCall> = None; 76 let mut current_macro_call: Option<ast::MacroCall> = None;
77 let mut current_macro_rules: Option<ast::MacroRules> = None;
77 let mut format_string_highlighter = FormatStringHighlighter::default(); 78 let mut format_string_highlighter = FormatStringHighlighter::default();
78 let mut macro_rules_highlighter = MacroRulesHighlighter::default(); 79 let mut macro_rules_highlighter = MacroRulesHighlighter::default();
79 let mut inside_attribute = false; 80 let mut inside_attribute = false;
@@ -106,28 +107,26 @@ pub(crate) fn highlight(
106 binding_hash: None, 107 binding_hash: None,
107 }); 108 });
108 } 109 }
109 if let Some(name) = mc.is_macro_rules() {
110 macro_rules_highlighter.init();
111 if let Some((highlight, binding_hash)) = highlight_element(
112 &sema,
113 &mut bindings_shadow_count,
114 syntactic_name_ref_highlighting,
115 name.syntax().clone().into(),
116 ) {
117 stack.add(HighlightedRange {
118 range: name.syntax().text_range(),
119 highlight,
120 binding_hash,
121 });
122 }
123 }
124 current_macro_call = Some(mc.clone()); 110 current_macro_call = Some(mc.clone());
125 continue; 111 continue;
126 } 112 }
127 WalkEvent::Leave(Some(mc)) => { 113 WalkEvent::Leave(Some(mc)) => {
128 assert!(current_macro_call == Some(mc)); 114 assert_eq!(current_macro_call, Some(mc));
129 current_macro_call = None; 115 current_macro_call = None;
130 format_string_highlighter = FormatStringHighlighter::default(); 116 format_string_highlighter = FormatStringHighlighter::default();
117 }
118 _ => (),
119 }
120
121 match event.clone().map(|it| it.into_node().and_then(ast::MacroRules::cast)) {
122 WalkEvent::Enter(Some(mac)) => {
123 macro_rules_highlighter.init();
124 current_macro_rules = Some(mac);
125 continue;
126 }
127 WalkEvent::Leave(Some(mac)) => {
128 assert_eq!(current_macro_rules, Some(mac));
129 current_macro_rules = None;
131 macro_rules_highlighter = MacroRulesHighlighter::default(); 130 macro_rules_highlighter = MacroRulesHighlighter::default();
132 } 131 }
133 _ => (), 132 _ => (),
@@ -163,6 +162,12 @@ pub(crate) fn highlight(
163 162
164 let range = element.text_range(); 163 let range = element.text_range();
165 164
165 if current_macro_rules.is_some() {
166 if let Some(tok) = element.as_token() {
167 macro_rules_highlighter.advance(tok);
168 }
169 }
170
166 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT { 171 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT {
167 // Inside a macro -- expand it first 172 // Inside a macro -- expand it first
168 let token = match element.clone().into_token() { 173 let token = match element.clone().into_token() {
@@ -173,9 +178,6 @@ pub(crate) fn highlight(
173 let parent = token.parent(); 178 let parent = token.parent();
174 179
175 format_string_highlighter.check_for_format_string(&parent); 180 format_string_highlighter.check_for_format_string(&parent);
176 if let Some(tok) = element.as_token() {
177 macro_rules_highlighter.advance(tok);
178 }
179 181
180 // We only care Name and Name_ref 182 // We only care Name and Name_ref
181 match (token.kind(), parent.kind()) { 183 match (token.kind(), parent.kind()) {
@@ -386,10 +388,14 @@ impl HighlightedRangeStack {
386 let mut res = self.stack.pop().unwrap(); 388 let mut res = self.stack.pop().unwrap();
387 res.sort_by_key(|range| range.range.start()); 389 res.sort_by_key(|range| range.range.start());
388 // Check that ranges are sorted and disjoint 390 // Check that ranges are sorted and disjoint
389 assert!(res 391 for (left, right) in res.iter().zip(res.iter().skip(1)) {
390 .iter() 392 assert!(
391 .zip(res.iter().skip(1)) 393 left.range.end() <= right.range.start(),
392 .all(|(left, right)| left.range.end() <= right.range.start())); 394 "left: {:#?}, right: {:#?}",
395 left,
396 right
397 );
398 }
393 res 399 res
394 } 400 }
395} 401}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 396fd46fb..920956b51 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -95,7 +95,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
95<span class="comment documentation">/// ```</span> 95<span class="comment documentation">/// ```</span>
96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> 96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
97</span><span class="comment documentation">/// ```</span> 97</span><span class="comment documentation">/// ```</span>
98<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> 98<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
99 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 99 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
100 <span class="punctuation">$</span>expr 100 <span class="punctuation">$</span>expr
101 <span class="punctuation">}</span> 101 <span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index d398e1ec8..c843b5085 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -35,13 +35,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span> 38<pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span>
39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span> 39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span>
40 <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> 40 <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span>
41 <span class="punctuation">}</span><span class="punctuation">)</span> 41 <span class="punctuation">}</span><span class="punctuation">)</span>
42<span class="punctuation">}</span> 42<span class="punctuation">}</span>
43#[rustc_builtin_macro] 43<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
44<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span> 44<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span>
45 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> 45 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
46 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> 46 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
47<span class="punctuation">}</span> 47<span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index a3b4f20e8..0569cf1e5 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -125,7 +125,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
125 <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 125 <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
126<span class="punctuation">}</span> 126<span class="punctuation">}</span>
127 127
128<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span> 128<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span>
129 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span> 129 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span>
130<span class="punctuation">}</span> 130<span class="punctuation">}</span>
131 131
@@ -135,13 +135,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
135 <span class="punctuation">}</span> 135 <span class="punctuation">}</span>
136<span class="punctuation">}</span> 136<span class="punctuation">}</span>
137 137
138<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> 138<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
139 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 139 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
140 <span class="punctuation">$</span>expr 140 <span class="punctuation">$</span>expr
141 <span class="punctuation">}</span> 141 <span class="punctuation">}</span>
142<span class="punctuation">}</span> 142<span class="punctuation">}</span>
143 143
144<span class="macro">macro_rules!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span> 144<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span>
145 <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span> 145 <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span>
146<span class="punctuation">}</span> 146<span class="punctuation">}</span>
147 147
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 5d2cd30d1..d4a774261 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -217,7 +217,7 @@ impl NameClass {
217 let def: hir::TypeAlias = sema.to_def(&it)?; 217 let def: hir::TypeAlias = sema.to_def(&it)?;
218 Some(NameClass::Definition(Definition::ModuleDef(def.into()))) 218 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
219 }, 219 },
220 ast::MacroCall(it) => { 220 ast::MacroRules(it) => {
221 let def = sema.to_def(&it)?; 221 let def = sema.to_def(&it)?;
222 Some(NameClass::Definition(Definition::Macro(def))) 222 Some(NameClass::Definition(Definition::Macro(def)))
223 }, 223 },
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 607185ca9..3936c7390 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -32,6 +32,7 @@ pub enum ReferenceKind {
32 StructLiteral, 32 StructLiteral,
33 RecordFieldExprOrPat, 33 RecordFieldExprOrPat,
34 SelfKw, 34 SelfKw,
35 EnumLiteral,
35 Other, 36 Other,
36} 37}
37 38
@@ -284,6 +285,8 @@ impl<'a> FindUsages<'a> {
284 ReferenceKind::RecordFieldExprOrPat 285 ReferenceKind::RecordFieldExprOrPat
285 } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { 286 } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) {
286 ReferenceKind::StructLiteral 287 ReferenceKind::StructLiteral
288 } else if is_enum_lit_name_ref(&name_ref) {
289 ReferenceKind::EnumLiteral
287 } else { 290 } else {
288 ReferenceKind::Other 291 ReferenceKind::Other
289 }; 292 };
@@ -402,3 +405,15 @@ fn is_record_field_expr_or_pat(name_ref: &ast::NameRef) -> bool {
402 false 405 false
403 } 406 }
404} 407}
408
409fn is_enum_lit_name_ref(name_ref: &ast::NameRef) -> bool {
410 name_ref
411 .syntax()
412 .ancestors()
413 .find_map(ast::PathExpr::cast)
414 .and_then(|p| p.path())
415 .and_then(|p| p.qualifier())
416 .and_then(|p| p.segment())
417 .map(|p| p.name_ref().as_ref() == Some(name_ref))
418 .unwrap_or(false)
419}
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 654df898e..121063aea 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -404,13 +404,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
404 ast::TypeAlias(it) => decl(it), 404 ast::TypeAlias(it) => decl(it),
405 ast::Const(it) => decl(it), 405 ast::Const(it) => decl(it),
406 ast::Static(it) => decl(it), 406 ast::Static(it) => decl(it),
407 ast::MacroCall(it) => { 407 ast::MacroRules(it) => decl(it),
408 if it.is_macro_rules().is_some() {
409 decl(it)
410 } else {
411 None
412 }
413 },
414 _ => None, 408 _ => None,
415 } 409 }
416 } 410 }
diff --git a/crates/mbe/src/mbe_expander.rs b/crates/mbe/src/mbe_expander.rs
index 97bce0536..a80b73db4 100644
--- a/crates/mbe/src/mbe_expander.rs
+++ b/crates/mbe/src/mbe_expander.rs
@@ -163,7 +163,7 @@ mod tests {
163 fn create_rules(macro_definition: &str) -> crate::MacroRules { 163 fn create_rules(macro_definition: &str) -> crate::MacroRules {
164 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); 164 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap();
165 let macro_definition = 165 let macro_definition =
166 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 166 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
167 167
168 let (definition_tt, _) = 168 let (definition_tt, _) =
169 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 169 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 843054fe8..dff6e98c2 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -48,7 +48,7 @@ mod rule_parsing {
48 let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition); 48 let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition);
49 let source_file = ast::SourceFile::parse(&macro_definition).ok().unwrap(); 49 let source_file = ast::SourceFile::parse(&macro_definition).ok().unwrap();
50 let macro_definition = 50 let macro_definition =
51 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 51 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
52 52
53 let (definition_tt, _) = 53 let (definition_tt, _) =
54 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 54 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
@@ -1668,7 +1668,7 @@ impl MacroFixture {
1668fn parse_macro_to_tt(ra_fixture: &str) -> tt::Subtree { 1668fn parse_macro_to_tt(ra_fixture: &str) -> tt::Subtree {
1669 let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); 1669 let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
1670 let macro_definition = 1670 let macro_definition =
1671 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 1671 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
1672 1672
1673 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 1673 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
1674 1674
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index ad29b82f7..8999829b4 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -232,6 +232,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
232 T![macro] => { 232 T![macro] => {
233 macro_def(p, m); 233 macro_def(p, m);
234 } 234 }
235 IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
236 macro_rules(p, m);
237 }
235 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 238 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
236 // test union_items 239 // test union_items
237 // union Foo {} 240 // union Foo {}
@@ -363,6 +366,34 @@ pub(crate) fn item_list(p: &mut Parser) {
363 m.complete(p, ITEM_LIST); 366 m.complete(p, ITEM_LIST);
364} 367}
365 368
369fn macro_rules(p: &mut Parser, m: Marker) {
370 assert!(p.at_contextual_kw("macro_rules"));
371 p.bump_remap(T![macro_rules]);
372 p.expect(T![!]);
373
374 if p.at(IDENT) {
375 name(p);
376 }
377 // Special-case `macro_rules! try`.
378 // This is a hack until we do proper edition support
379
380 // test try_macro_rules
381 // macro_rules! try { () => {} }
382 if p.at(T![try]) {
383 let m = p.start();
384 p.bump_remap(IDENT);
385 m.complete(p, NAME);
386 }
387
388 match p.current() {
389 T!['{'] => {
390 token_tree(p);
391 }
392 _ => p.error("expected `{`"),
393 }
394 m.complete(p, MACRO_RULES);
395}
396
366// test macro_def 397// test macro_def
367// macro m { ($i:ident) => {} } 398// macro m { ($i:ident) => {} }
368// macro m($i:ident) {} 399// macro m($i:ident) {}
@@ -394,19 +425,6 @@ fn macro_call(p: &mut Parser) -> BlockLike {
394 425
395pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { 426pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
396 p.expect(T![!]); 427 p.expect(T![!]);
397 if p.at(IDENT) {
398 name(p);
399 }
400 // Special-case `macro_rules! try`.
401 // This is a hack until we do proper edition support
402
403 // test try_macro_rules
404 // macro_rules! try { () => {} }
405 if p.at(T![try]) {
406 let m = p.start();
407 p.bump_remap(IDENT);
408 m.complete(p, NAME);
409 }
410 428
411 match p.current() { 429 match p.current() {
412 T!['{'] => { 430 T!['{'] => {
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 8bc6688f3..5d6ec17a4 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -106,6 +106,7 @@ pub enum SyntaxKind {
106 EXISTENTIAL_KW, 106 EXISTENTIAL_KW,
107 UNION_KW, 107 UNION_KW,
108 RAW_KW, 108 RAW_KW,
109 MACRO_RULES_KW,
109 INT_NUMBER, 110 INT_NUMBER,
110 FLOAT_NUMBER, 111 FLOAT_NUMBER,
111 CHAR, 112 CHAR,
@@ -135,6 +136,8 @@ pub enum SyntaxKind {
135 IMPL, 136 IMPL,
136 TYPE_ALIAS, 137 TYPE_ALIAS,
137 MACRO_CALL, 138 MACRO_CALL,
139 MACRO_RULES,
140 MACRO_ARM,
138 TOKEN_TREE, 141 TOKEN_TREE,
139 MACRO_DEF, 142 MACRO_DEF,
140 PAREN_TYPE, 143 PAREN_TYPE,
@@ -258,7 +261,7 @@ impl SyntaxKind {
258 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW 261 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
259 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW 262 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
260 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW 263 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
261 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true, 264 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW | MACRO_RULES_KW => true,
262 _ => false, 265 _ => false,
263 } 266 }
264 } 267 }
@@ -361,4 +364,4 @@ impl SyntaxKind {
361 } 364 }
362} 365}
363#[macro_export] 366#[macro_export]
364macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [lifetime] => { $ crate :: SyntaxKind :: LIFETIME } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } 367macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [lifetime] => { $ crate :: SyntaxKind :: LIFETIME } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 729372968..1bfa6c3fc 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
10doctest = false 10doctest = false
11 11
12[dependencies] 12[dependencies]
13goblin = "0.2.1" 13object = { version = "0.23", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] }
14libloading = "0.6.0" 14libloading = "0.6.0"
15memmap = "0.7" 15memmap = "0.7"
16 16
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs
index f8f705da8..2afb973cc 100644
--- a/crates/proc_macro_srv/src/dylib.rs
+++ b/crates/proc_macro_srv/src/dylib.rs
@@ -1,14 +1,17 @@
1//! Handles dynamic library loading for proc macro 1//! Handles dynamic library loading for proc macro
2 2
3use crate::{proc_macro::bridge, rustc_server::TokenStream}; 3use std::{
4use std::fs::File; 4 fs::File,
5use std::path::{Path, PathBuf}; 5 io,
6 path::{Path, PathBuf},
7};
6 8
7use goblin::{mach::Mach, Object};
8use libloading::Library; 9use libloading::Library;
9use memmap::Mmap; 10use memmap::Mmap;
11use object::Object;
10use proc_macro_api::ProcMacroKind; 12use proc_macro_api::ProcMacroKind;
11use std::io; 13
14use crate::{proc_macro::bridge, rustc_server::TokenStream};
12 15
13const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 16const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
14 17
@@ -23,40 +26,26 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
23fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> { 26fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
24 let file = File::open(file)?; 27 let file = File::open(file)?;
25 let buffer = unsafe { Mmap::map(&file)? }; 28 let buffer = unsafe { Mmap::map(&file)? };
26 let object = Object::parse(&buffer).map_err(invalid_data_err)?;
27 29
28 let name = match object { 30 Ok(object::File::parse(&buffer)
29 Object::Elf(elf) => { 31 .map_err(invalid_data_err)?
30 let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; 32 .exports()
31 symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned) 33 .map_err(invalid_data_err)?
32 } 34 .into_iter()
33 Object::PE(pe) => pe 35 .map(|export| export.name())
34 .exports 36 .filter_map(|sym| String::from_utf8(sym.into()).ok())
35 .iter() 37 .find(|sym| is_derive_registrar_symbol(sym))
36 .flat_map(|s| s.name) 38 .map(|sym| {
37 .find(|s| is_derive_registrar_symbol(s)) 39 // From MacOS docs:
38 .map(&str::to_owned), 40 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
39 Object::Mach(Mach::Binary(binary)) => { 41 // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
40 let exports = binary.exports().map_err(invalid_data_err)?; 42 // prepended with an underscore.
41 exports 43 if cfg!(target_os = "macos") && sym.starts_with('_') {
42 .iter() 44 sym[1..].to_owned()
43 .map(|s| { 45 } else {
44 // In macos doc: 46 sym
45 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html 47 }
46 // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be 48 }))
47 // prepended with an underscore.
48 if s.name.starts_with('_') {
49 &s.name[1..]
50 } else {
51 &s.name
52 }
53 })
54 .find(|s| is_derive_registrar_symbol(s))
55 .map(&str::to_owned)
56 }
57 _ => return Ok(None),
58 };
59 return Ok(name);
60} 49}
61 50
62/// Loads dynamic library in platform dependent manner. 51/// Loads dynamic library in platform dependent manner.
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 30d11b146..0ad75214f 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -128,7 +128,6 @@ pub struct MacroCall {
128 pub(crate) syntax: SyntaxNode, 128 pub(crate) syntax: SyntaxNode,
129} 129}
130impl ast::AttrsOwner for MacroCall {} 130impl ast::AttrsOwner for MacroCall {}
131impl ast::NameOwner for MacroCall {}
132impl MacroCall { 131impl MacroCall {
133 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 132 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
134 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } 133 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
@@ -273,6 +272,20 @@ impl Impl {
273 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) } 272 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
274} 273}
275#[derive(Debug, Clone, PartialEq, Eq, Hash)] 274#[derive(Debug, Clone, PartialEq, Eq, Hash)]
275pub struct MacroRules {
276 pub(crate) syntax: SyntaxNode,
277}
278impl ast::AttrsOwner for MacroRules {}
279impl ast::NameOwner for MacroRules {}
280impl ast::VisibilityOwner for MacroRules {}
281impl MacroRules {
282 pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
283 support::token(&self.syntax, T![macro_rules])
284 }
285 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
286 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
287}
288#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276pub struct Module { 289pub struct Module {
277 pub(crate) syntax: SyntaxNode, 290 pub(crate) syntax: SyntaxNode,
278} 291}
@@ -1318,6 +1331,7 @@ pub enum Item {
1318 Fn(Fn), 1331 Fn(Fn),
1319 Impl(Impl), 1332 Impl(Impl),
1320 MacroCall(MacroCall), 1333 MacroCall(MacroCall),
1334 MacroRules(MacroRules),
1321 Module(Module), 1335 Module(Module),
1322 Static(Static), 1336 Static(Static),
1323 Struct(Struct), 1337 Struct(Struct),
@@ -1374,7 +1388,6 @@ pub enum AssocItem {
1374 TypeAlias(TypeAlias), 1388 TypeAlias(TypeAlias),
1375} 1389}
1376impl ast::AttrsOwner for AssocItem {} 1390impl ast::AttrsOwner for AssocItem {}
1377impl ast::NameOwner for AssocItem {}
1378#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1379pub enum ExternItem { 1392pub enum ExternItem {
1380 Fn(Fn), 1393 Fn(Fn),
@@ -1383,7 +1396,6 @@ pub enum ExternItem {
1383 TypeAlias(TypeAlias), 1396 TypeAlias(TypeAlias),
1384} 1397}
1385impl ast::AttrsOwner for ExternItem {} 1398impl ast::AttrsOwner for ExternItem {}
1386impl ast::NameOwner for ExternItem {}
1387#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1399#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1388pub enum GenericParam { 1400pub enum GenericParam {
1389 ConstParam(ConstParam), 1401 ConstParam(ConstParam),
@@ -1666,6 +1678,17 @@ impl AstNode for Impl {
1666 } 1678 }
1667 fn syntax(&self) -> &SyntaxNode { &self.syntax } 1679 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1668} 1680}
1681impl AstNode for MacroRules {
1682 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
1683 fn cast(syntax: SyntaxNode) -> Option<Self> {
1684 if Self::can_cast(syntax.kind()) {
1685 Some(Self { syntax })
1686 } else {
1687 None
1688 }
1689 }
1690 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1691}
1669impl AstNode for Module { 1692impl AstNode for Module {
1670 fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } 1693 fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
1671 fn cast(syntax: SyntaxNode) -> Option<Self> { 1694 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3060,6 +3083,9 @@ impl From<Impl> for Item {
3060impl From<MacroCall> for Item { 3083impl From<MacroCall> for Item {
3061 fn from(node: MacroCall) -> Item { Item::MacroCall(node) } 3084 fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
3062} 3085}
3086impl From<MacroRules> for Item {
3087 fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
3088}
3063impl From<Module> for Item { 3089impl From<Module> for Item {
3064 fn from(node: Module) -> Item { Item::Module(node) } 3090 fn from(node: Module) -> Item { Item::Module(node) }
3065} 3091}
@@ -3084,8 +3110,8 @@ impl From<Use> for Item {
3084impl AstNode for Item { 3110impl AstNode for Item {
3085 fn can_cast(kind: SyntaxKind) -> bool { 3111 fn can_cast(kind: SyntaxKind) -> bool {
3086 match kind { 3112 match kind {
3087 CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MODULE 3113 CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES
3088 | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, 3114 | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true,
3089 _ => false, 3115 _ => false,
3090 } 3116 }
3091 } 3117 }
@@ -3098,6 +3124,7 @@ impl AstNode for Item {
3098 FN => Item::Fn(Fn { syntax }), 3124 FN => Item::Fn(Fn { syntax }),
3099 IMPL => Item::Impl(Impl { syntax }), 3125 IMPL => Item::Impl(Impl { syntax }),
3100 MACRO_CALL => Item::MacroCall(MacroCall { syntax }), 3126 MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
3127 MACRO_RULES => Item::MacroRules(MacroRules { syntax }),
3101 MODULE => Item::Module(Module { syntax }), 3128 MODULE => Item::Module(Module { syntax }),
3102 STATIC => Item::Static(Static { syntax }), 3129 STATIC => Item::Static(Static { syntax }),
3103 STRUCT => Item::Struct(Struct { syntax }), 3130 STRUCT => Item::Struct(Struct { syntax }),
@@ -3118,6 +3145,7 @@ impl AstNode for Item {
3118 Item::Fn(it) => &it.syntax, 3145 Item::Fn(it) => &it.syntax,
3119 Item::Impl(it) => &it.syntax, 3146 Item::Impl(it) => &it.syntax,
3120 Item::MacroCall(it) => &it.syntax, 3147 Item::MacroCall(it) => &it.syntax,
3148 Item::MacroRules(it) => &it.syntax,
3121 Item::Module(it) => &it.syntax, 3149 Item::Module(it) => &it.syntax,
3122 Item::Static(it) => &it.syntax, 3150 Item::Static(it) => &it.syntax,
3123 Item::Struct(it) => &it.syntax, 3151 Item::Struct(it) => &it.syntax,
@@ -3582,6 +3610,11 @@ impl std::fmt::Display for Impl {
3582 std::fmt::Display::fmt(self.syntax(), f) 3610 std::fmt::Display::fmt(self.syntax(), f)
3583 } 3611 }
3584} 3612}
3613impl std::fmt::Display for MacroRules {
3614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3615 std::fmt::Display::fmt(self.syntax(), f)
3616 }
3617}
3585impl std::fmt::Display for Module { 3618impl std::fmt::Display for Module {
3586 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 3619 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3587 std::fmt::Display::fmt(self.syntax(), f) 3620 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index cc09b77a5..16b079c42 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -196,6 +196,9 @@ pub fn expr_method_call(receiver: ast::Expr, method: &str, arg_list: ast::ArgLis
196pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr { 196pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr {
197 expr_from_text(&if exclusive { format!("&mut {}", expr) } else { format!("&{}", expr) }) 197 expr_from_text(&if exclusive { format!("&mut {}", expr) } else { format!("&{}", expr) })
198} 198}
199pub fn expr_paren(expr: ast::Expr) -> ast::Expr {
200 expr_from_text(&format!("({})", expr))
201}
199fn expr_from_text(text: &str) -> ast::Expr { 202fn expr_from_text(text: &str) -> ast::Expr {
200 ast_from_text(&format!("const C: () = {};", text)) 203 ast_from_text(&format!("const C: () = {};", text))
201} 204}
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 820af2d20..c59a29eab 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -382,21 +382,6 @@ impl ast::Visibility {
382 } 382 }
383} 383}
384 384
385impl ast::MacroCall {
386 pub fn is_macro_rules(&self) -> Option<ast::Name> {
387 let name_ref = self.path()?.segment()?.name_ref()?;
388 if name_ref.text() == "macro_rules" {
389 self.name()
390 } else {
391 None
392 }
393 }
394
395 pub fn is_bang(&self) -> bool {
396 self.is_macro_rules().is_none()
397 }
398}
399
400impl ast::LifetimeParam { 385impl ast::LifetimeParam {
401 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> { 386 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
402 self.syntax() 387 self.syntax()
@@ -476,5 +461,5 @@ impl ast::DocCommentsOwner for ast::Static {}
476impl ast::DocCommentsOwner for ast::Const {} 461impl ast::DocCommentsOwner for ast::Const {}
477impl ast::DocCommentsOwner for ast::TypeAlias {} 462impl ast::DocCommentsOwner for ast::TypeAlias {}
478impl ast::DocCommentsOwner for ast::Impl {} 463impl ast::DocCommentsOwner for ast::Impl {}
479impl ast::DocCommentsOwner for ast::MacroCall {} 464impl ast::DocCommentsOwner for ast::MacroRules {}
480impl ast::DocCommentsOwner for ast::Use {} 465impl ast::DocCommentsOwner for ast::Use {}
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs
index 8d2c7eae4..d33bde30c 100644
--- a/crates/syntax/src/display.rs
+++ b/crates/syntax/src/display.rs
@@ -76,7 +76,7 @@ pub fn type_label(node: &ast::TypeAlias) -> String {
76 label.trim().to_owned() 76 label.trim().to_owned()
77} 77}
78 78
79pub fn macro_label(node: &ast::MacroCall) -> String { 79pub fn macro_label(node: &ast::MacroRules) -> String {
80 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); 80 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
81 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; 81 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
82 format!("{}macro_rules! {}", vis, name) 82 format!("{}macro_rules! {}", vis, name)
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
index 49842177a..ce27c3dd9 100644
--- a/crates/syntax/src/parsing/text_tree_sink.rs
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -147,8 +147,8 @@ fn n_attached_trivias<'a>(
147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, 147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
148) -> usize { 148) -> usize {
149 match kind { 149 match kind {
150 MACRO_CALL | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT | MODULE 150 MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT
151 | RECORD_FIELD | STATIC | USE => { 151 | MODULE | RECORD_FIELD | STATIC | USE => {
152 let mut res = 0; 152 let mut res = 0;
153 let mut trivias = trivias.enumerate().peekable(); 153 let mut trivias = trivias.enumerate().peekable();
154 154
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 6f45149bf..2ddaeb176 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -3,7 +3,9 @@
3mod block; 3mod block;
4 4
5use crate::{ 5use crate::{
6 algo, ast, match_ast, AstNode, SyntaxError, 6 algo,
7 ast::{self, VisibilityOwner},
8 match_ast, AstNode, SyntaxError,
7 SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS}, 9 SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS},
8 SyntaxNode, SyntaxToken, TextSize, T, 10 SyntaxNode, SyntaxToken, TextSize, T,
9}; 11};
@@ -99,6 +101,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
99 ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors), 101 ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors),
100 ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors), 102 ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
101 ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors), 103 ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
104 ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
102 _ => (), 105 _ => (),
103 } 106 }
104 } 107 }
@@ -350,3 +353,12 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
350 } 353 }
351 None 354 None
352} 355}
356
357fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec<SyntaxError>) {
358 if let Some(vis) = mac.visibility() {
359 errors.push(SyntaxError::new(
360 "visibilities are not allowed on `macro_rules!` items",
361 vis.syntax().text_range(),
362 ));
363 }
364}
diff --git a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
index 4cfd1bce4..9ad5b12b8 100644
--- a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
+++ b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
@@ -17,14 +17,17 @@ [email protected]
17 [email protected] "bin" 17 [email protected] "bin"
18 [email protected] 18 [email protected]
19 [email protected] "/" 19 [email protected] "/"
20 MACRO_CALL@32..41 20 MACRO_CALL@32..35
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] "env" 24 [email protected] "env"
25 [email protected] " " 25 [email protected] " "
26 [email protected] 26 [email protected]
27 [email protected] "rusti" 27 [email protected]
28 [email protected]
29 [email protected]
30 [email protected] "rusti"
28 [email protected] "\n" 31 [email protected] "\n"
29error 23..23: expected `[` 32error 23..23: expected `[`
30error 23..23: expected an item 33error 23..23: expected an item
@@ -35,5 +38,8 @@ error 31..31: expected `{`, `[`, `(`
35error 31..31: expected SEMICOLON 38error 31..31: expected SEMICOLON
36error 31..31: expected an item 39error 31..31: expected an item
37error 35..35: expected BANG 40error 35..35: expected BANG
41error 35..35: expected `{`, `[`, `(`
42error 35..35: expected SEMICOLON
43error 41..41: expected BANG
38error 41..41: expected `{`, `[`, `(` 44error 41..41: expected `{`, `[`, `(`
39error 41..41: expected SEMICOLON 45error 41..41: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
index de8217064..e4fb32de1 100644
--- a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
@@ -12,11 +12,8 @@ [email protected]
12 [email protected] "{" 12 [email protected] "{"
13 [email protected] "}" 13 [email protected] "}"
14 [email protected] "\n" 14 [email protected] "\n"
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "macro_rules"
17 [email protected]
18 [email protected]
19 [email protected] "macro_rules"
20 [email protected] "!" 17 [email protected] "!"
21 [email protected] " " 18 [email protected] " "
22 [email protected] 19 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
index e757249f0..e84b9164f 100644
--- a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
@@ -82,32 +82,28 @@ [email protected]
82 [email protected] "{" 82 [email protected] "{"
83 [email protected] "}" 83 [email protected] "}"
84 [email protected] "\n " 84 [email protected] "\n "
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected] "macro_rules"
87 [email protected] 87 [email protected] "!"
88 [email protected] 88 [email protected] " "
89 [email protected] 89 [email protected]
90 [email protected] "macro_rules" 90 [email protected] "test"
91 [email protected] "!" 91 [email protected] " "
92 [email protected] " " 92 [email protected]
93 [email protected] 93 [email protected] "{"
94 [email protected] "test" 94 [email protected] "\n "
95 [email protected] " " 95 [email protected]
96 [email protected] 96 [email protected] "("
97 [email protected] "{" 97 [email protected] ")"
98 [email protected] "\n " 98 [email protected] " "
99 [email protected] 99 [email protected] "="
100 [email protected] "(" 100 [email protected] ">"
101 [email protected] ")" 101 [email protected] " "
102 [email protected] " " 102 [email protected]
103 [email protected] "=" 103 [email protected] "{"
104 [email protected] ">" 104 [email protected] "}"
105 [email protected] " " 105 [email protected] "\n "
106 [email protected] 106 [email protected] "}"
107 [email protected] "{"
108 [email protected] "}"
109 [email protected] "\n "
110 [email protected] "}"
111 [email protected] "\n " 107 [email protected] "\n "
112 [email protected] 108 [email protected]
113 [email protected] 109 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
index 05b89d1c3..d1c22947b 100644
--- a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
@@ -1,9 +1,6 @@
1[email protected] 1[email protected]
2 [email protected] 2 [email protected]
3 [email protected] 3 [email protected] "macro_rules"
4 [email protected]
5 [email protected]
6 [email protected] "macro_rules"
7 [email protected] "!" 4 [email protected] "!"
8 [email protected] " " 5 [email protected] " "
9 [email protected] 6 [email protected]
diff --git a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
index be60f7a8e..87d8ebcba 100644
--- a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
+++ b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
@@ -1,5 +1,5 @@
1[email protected] 1[email protected]
2 MACRO_CALL@0..64 2 MACRO_RULES@0..64
3 [email protected] "/// Some docs" 3 [email protected] "/// Some docs"
4 [email protected] "\n" 4 [email protected] "\n"
5 [email protected] 5 [email protected]
@@ -11,10 +11,7 @@ [email protected]
11 [email protected] "macro_export" 11 [email protected] "macro_export"
12 [email protected] "]" 12 [email protected] "]"
13 [email protected] "\n" 13 [email protected] "\n"
14 [email protected] 14 [email protected] "macro_rules"
15 [email protected]
16 [email protected]
17 [email protected] "macro_rules"
18 [email protected] "!" 15 [email protected] "!"
19 [email protected] " " 16 [email protected] " "
20 [email protected] 17 [email protected]
diff --git a/docs/dev/style.md b/docs/dev/style.md
index c8d943142..13c6a2a16 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -96,19 +96,19 @@ When using multiline fixtures, use unindented raw string literals:
96 fn inline_field_shorthand() { 96 fn inline_field_shorthand() {
97 check_assist( 97 check_assist(
98 inline_local_variable, 98 inline_local_variable,
99 r" 99 r#"
100struct S { foo: i32} 100struct S { foo: i32}
101fn main() { 101fn main() {
102 let <|>foo = 92; 102 let <|>foo = 92;
103 S { foo } 103 S { foo }
104} 104}
105", 105"#,
106 r" 106 r#"
107struct S { foo: i32} 107struct S { foo: i32}
108fn main() { 108fn main() {
109 S { foo: 92 } 109 S { foo: 92 }
110} 110}
111", 111"#,
112 ); 112 );
113 } 113 }
114``` 114```
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 42317b231..1ec6e81bb 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -289,6 +289,8 @@ GNOME Builder 3.37.1 and newer has native `rust-analyzer` support. If the LSP bi
289 289
290== Configuration 290== Configuration
291 291
292**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/rust-analyzer/src/config.rs[config.rs]
293
292rust-analyzer is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files. 294rust-analyzer is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files.
293Please consult your editor's documentation to learn how to configure LSP servers. 295Please consult your editor's documentation to learn how to configure LSP servers.
294 296
diff --git a/editors/code/.vscodeignore b/editors/code/.vscodeignore
index 7149ab799..5096ce4da 100644
--- a/editors/code/.vscodeignore
+++ b/editors/code/.vscodeignore
@@ -1,4 +1,5 @@
1** 1**
2!language-configuration.json
2!out/src/main.js 3!out/src/main.js
3!package.json 4!package.json
4!package-lock.json 5!package-lock.json
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 8ceaaf60e..72a4c10f5 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", 70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
71 "trait", "true", "try", "type", "unsafe", "use", "where", "while", 71 "trait", "true", "try", "type", "unsafe", "use", "where", "while",
72 ], 72 ],
73 contextual_keywords: &["auto", "default", "existential", "union", "raw"], 73 contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules"],
74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"], 74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"],
75 tokens: &[ 75 tokens: &[
76 "ERROR", 76 "ERROR",
@@ -98,6 +98,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
98 "IMPL", 98 "IMPL",
99 "TYPE_ALIAS", 99 "TYPE_ALIAS",
100 "MACRO_CALL", 100 "MACRO_CALL",
101 "MACRO_RULES",
102 "MACRO_ARM",
101 "TOKEN_TREE", 103 "TOKEN_TREE",
102 "MACRO_DEF", 104 "MACRO_DEF",
103 "PAREN_TYPE", 105 "PAREN_TYPE",