aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock47
-rw-r--r--crates/assists/src/handlers/reorder_fields.rs129
-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.rs14
-rw-r--r--crates/hir/src/semantics.rs51
-rw-r--r--crates/hir/src/semantics/source_to_def.rs21
-rw-r--r--crates/hir_def/src/generics.rs49
-rw-r--r--crates/hir_def/src/item_tree/lower.rs5
-rw-r--r--crates/hir_def/src/keys.rs5
-rw-r--r--crates/hir_expand/src/builtin_macro.rs25
-rw-r--r--crates/hir_expand/src/name.rs3
-rw-r--r--crates/ide/src/references.rs115
-rw-r--r--crates/ide_db/src/search.rs15
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/dylib.rs65
-rw-r--r--docs/dev/style.md8
-rw-r--r--docs/user/manual.adoc2
-rw-r--r--editors/code/.vscodeignore1
19 files changed, 399 insertions, 183 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8cb5fd7ad..ec8ad11cb 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"
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/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..1e64a1614 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 {
@@ -129,6 +129,14 @@ impl HasSource for TypeParam {
129 type Ast = Either<ast::Trait, ast::TypeParam>; 129 type Ast = Either<ast::Trait, ast::TypeParam>;
130 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { 130 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
131 let child_source = self.id.parent.child_source(db.upcast()); 131 let child_source = self.id.parent.child_source(db.upcast());
132 child_source.map(|it| it[self.id.local_id].clone()) 132 child_source.map(|it| it.type_params[self.id.local_id].clone())
133 }
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.lifetime_params[self.id.local_id].clone())
133 } 141 }
134} 142}
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 4bd22ed27..e4fc21ced 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,6 +722,7 @@ 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),
725 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
687 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros 726 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros
688 (crate::Local, ast::IdentPat, bind_pat_to_def), 727 (crate::Local, ast::IdentPat, bind_pat_to_def),
689]; 728];
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 66fc11611..badcf0ae8 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,13 +129,25 @@ 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_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> {
140 let kind = MacroDefKind::Declarative; 153 let kind = MacroDefKind::Declarative;
@@ -203,7 +216,7 @@ impl SourceToDefCtx<'_, '_> {
203 Some(def.into()) 216 Some(def.into())
204 } 217 }
205 218
206 fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { 219 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) { 220 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
208 let res: GenericDefId = match_ast! { 221 let res: GenericDefId = match_ast! {
209 match (container.value) { 222 match (container.value) {
@@ -247,7 +260,7 @@ pub(crate) enum ChildContainer {
247 VariantId(VariantId), 260 VariantId(VariantId),
248 TypeAliasId(TypeAliasId), 261 TypeAliasId(TypeAliasId),
249 /// XXX: this might be the same def as, for example an `EnumId`. However, 262 /// XXX: this might be the same def as, for example an `EnumId`. However,
250 /// here the children generic parameters, and not, eg enum variants. 263 /// here the children are generic parameters, and not, eg enum variants.
251 GenericDefId(GenericDefId), 264 GenericDefId(GenericDefId),
252} 265}
253impl_from! { 266impl_from! {
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 5189c7e9f..81912a454 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,
23 src::HasSource, 22 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 struct SourceMaps {
77 pub type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
78 pub 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(
@@ -129,9 +133,9 @@ impl GenericParams {
129 Arc::new(generics) 133 Arc::new(generics)
130 } 134 }
131 135
132 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 136 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMaps>) {
133 let mut generics = GenericParams::default(); 137 let mut generics = GenericParams::default();
134 let mut sm = ArenaMap::default(); 138 let mut sm = SourceMaps::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());
@@ -210,7 +214,7 @@ impl GenericParams {
210 pub(crate) fn fill( 214 pub(crate) fn fill(
211 &mut self, 215 &mut self,
212 lower_ctx: &LowerCtx, 216 lower_ctx: &LowerCtx,
213 sm: &mut SourceMap, 217 sm: &mut SourceMaps,
214 node: &dyn GenericParamsOwner, 218 node: &dyn GenericParamsOwner,
215 ) { 219 ) {
216 if let Some(params) = node.generic_param_list() { 220 if let Some(params) = node.generic_param_list() {
@@ -237,7 +241,7 @@ impl GenericParams {
237 fn fill_params( 241 fn fill_params(
238 &mut self, 242 &mut self,
239 lower_ctx: &LowerCtx, 243 lower_ctx: &LowerCtx,
240 sm: &mut SourceMap, 244 sm: &mut SourceMaps,
241 params: ast::GenericParamList, 245 params: ast::GenericParamList,
242 ) { 246 ) {
243 for type_param in params.type_params() { 247 for type_param in params.type_params() {
@@ -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 }
@@ -340,27 +345,29 @@ impl GenericParams {
340 }) 345 })
341 } 346 }
342} 347}
343 348impl GenericDefId {
344impl HasChildSource for GenericDefId { 349 // FIXME: Change HasChildSource's ChildId AssocItem to be a generic parameter instead
345 type ChildId = LocalTypeParamId; 350 pub fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMaps> {
346 type Value = Either<ast::Trait, ast::TypeParam>; 351 GenericParams::new(db, *self).1
347 fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> {
348 let (_, sm) = GenericParams::new(db, *self);
349 sm
350 } 352 }
351} 353}
352 354
353impl ChildBySource for GenericDefId { 355impl ChildBySource for GenericDefId {
354 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 356 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
355 let mut res = DynMap::default(); 357 let mut res = DynMap::default();
356 let arena_map = self.child_source(db); 358 let (_, sm) = GenericParams::new(db, *self);
357 let arena_map = arena_map.as_ref(); 359
358 for (local_id, src) in arena_map.value.iter() { 360 let sm = sm.as_ref();
361 for (local_id, src) in sm.value.type_params.iter() {
359 let id = TypeParamId { parent: *self, local_id }; 362 let id = TypeParamId { parent: *self, local_id };
360 if let Either::Right(type_param) = src { 363 if let Either::Right(type_param) = src {
361 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) 364 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
362 } 365 }
363 } 366 }
367 for (local_id, src) in sm.value.lifetime_params.iter() {
368 let id = LifetimeParamId { parent: *self, local_id };
369 res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
370 }
364 res 371 res
365 } 372 }
366} 373}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index f7ce2e26d..2939c6b1e 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::{
@@ -607,7 +606,7 @@ impl Ctx {
607 owner: GenericsOwner<'_>, 606 owner: GenericsOwner<'_>,
608 node: &impl ast::GenericParamsOwner, 607 node: &impl ast::GenericParamsOwner,
609 ) -> GenericParamsId { 608 ) -> GenericParamsId {
610 let mut sm = &mut ArenaMap::default(); 609 let mut sm = &mut Default::default();
611 let mut generics = GenericParams::default(); 610 let mut generics = GenericParams::default();
612 match owner { 611 match owner {
613 GenericsOwner::Function(func) => { 612 GenericsOwner::Function(func) => {
@@ -630,7 +629,7 @@ impl Ctx {
630 default: None, 629 default: None,
631 provenance: TypeParamProvenance::TraitSelf, 630 provenance: TypeParamProvenance::TraitSelf,
632 }); 631 });
633 sm.insert(self_param_id, Either::Left(trait_def.clone())); 632 sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
634 // add super traits as bounds on Self 633 // add super traits as bounds on Self
635 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 634 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
636 let self_param = TypeRef::Path(name![Self].into()); 635 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_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 477192a09..b1b432ded 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -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)?;
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/ide/src/references.rs b/crates/ide/src/references.rs
index 7395b81bd..66f0f7950 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#"
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/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/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