diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/handlers/reorder_fields.rs | 129 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/from_id.rs | 17 | ||||
-rw-r--r-- | crates/hir/src/has_source.rs | 14 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 51 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 21 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 49 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/keys.rs | 5 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 25 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 3 | ||||
-rw-r--r-- | crates/ide/src/references.rs | 115 | ||||
-rw-r--r-- | crates/ide_db/src/search.rs | 15 | ||||
-rw-r--r-- | crates/proc_macro_srv/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/proc_macro_srv/src/dylib.rs | 65 |
15 files changed, 384 insertions, 140 deletions
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; | |||
4 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; | 4 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; |
5 | use ide_db::RootDatabase; | 5 | use ide_db::RootDatabase; |
6 | use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; | 6 | use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; |
7 | use test_utils::mark; | ||
7 | 8 | ||
8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 9 | use 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)] |
109 | mod tests { | 111 | mod 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 { | 124 | struct 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 }; | 129 | const 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 {}; | 139 | struct Foo {}; |
135 | const test: Foo = <|>Foo {} | 140 | const 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}; | 150 | struct Foo {foo: i32, bar: i32}; |
146 | const test: Foo = <|>Foo {bar: 0, foo: 1} | 151 | const test: Foo = <|>Foo {bar: 0, foo: 1} |
147 | "#, | 152 | "#, |
148 | r#" | 153 | r#" |
149 | struct Foo {foo: i32, bar: i32}; | 154 | struct Foo {foo: i32, bar: i32}; |
150 | const test: Foo = Foo {foo: 1, bar: 0} | 155 | const 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 } | 165 | struct Foo { foo: i64, bar: i64, baz: i64 } |
161 | 166 | ||
162 | fn f(f: Foo) -> { | 167 | fn 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 } | 175 | struct Foo { foo: i64, bar: i64, baz: i64 } |
171 | 176 | ||
172 | fn f(f: Foo) -> { | 177 | fn 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 { | 192 | struct Foo { |
188 | foo: String, | 193 | foo: String, |
189 | bar: String, | 194 | bar: String, |
190 | } | 195 | } |
191 | 196 | ||
192 | impl Foo { | 197 | impl 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 { | 209 | struct Foo { |
205 | foo: String, | 210 | foo: String, |
206 | bar: String, | 211 | bar: String, |
207 | } | 212 | } |
208 | 213 | ||
209 | impl Foo { | 214 | impl 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 | ||
158 | impl 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 | |||
157 | impl From<Adt> for GenericDefId { | 174 | impl 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; | |||
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | ||
17 | pub trait HasSource { | 17 | pub 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 | |||
136 | impl 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}; | |||
13 | use hir_ty::associated_type_shorthand_candidates; | 13 | use hir_ty::associated_type_shorthand_candidates; |
14 | use itertools::Itertools; | 14 | use itertools::Itertools; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize}; | 16 | use syntax::{ |
17 | algo::find_node_at_offset, | ||
18 | ast::{self, GenericParamsOwner}, | ||
19 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize, | ||
20 | }; | ||
17 | 21 | ||
18 | use crate::{ | 22 | use 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, ¶m) | 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 | }; |
12 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
13 | use rustc_hash::FxHashMap; | 14 | use 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 | } |
253 | impl_from! { | 266 | impl_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 | ||
75 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; | 75 | #[derive(Default)] |
76 | pub struct SourceMaps { | ||
77 | pub type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, | ||
78 | pub lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, | ||
79 | } | ||
76 | 80 | ||
77 | impl GenericParams { | 81 | impl 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 | 348 | impl GenericDefId { | |
344 | impl 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 | ||
353 | impl ChildBySource for GenericDefId { | 355 | impl 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 | ||
3 | use std::{collections::hash_map::Entry, mem, sync::Arc}; | 3 | use std::{collections::hash_map::Entry, mem, sync::Arc}; |
4 | 4 | ||
5 | use arena::map::ArenaMap; | ||
6 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; | 5 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; |
7 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
8 | use syntax::{ | 7 | use 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 | ||
9 | use crate::{ | 9 | use 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 | ||
15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | 15 | pub 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(); | |||
28 | pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); | 28 | pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); |
29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); | 29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); |
30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | 30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); |
31 | pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); | ||
31 | 32 | ||
32 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | 33 | pub 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 | ||
111 | fn 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 | |||
108 | fn line_expand( | 120 | fn 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 | ||
276 | fn 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 | |||
264 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 289 | fn 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 | ||
204 | fn 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 | |||
201 | fn try_find_self_references( | 231 | fn 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#" | ||
393 | enum Foo <|>{ | ||
394 | A, | ||
395 | B, | ||
396 | } | ||
397 | fn 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#" | ||
414 | enum Foo<|> { | ||
415 | A, | ||
416 | B, | ||
417 | } | ||
418 | fn 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#" | ||
436 | enum Foo<T> <|>{ | ||
437 | A(T), | ||
438 | B, | ||
439 | } | ||
440 | fn 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#" | ||
457 | enum Foo<|>{ | ||
458 | A(i8), | ||
459 | B(i8), | ||
460 | } | ||
461 | fn 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 | |||
409 | fn 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" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | goblin = "0.2.1" | 13 | object = { version = "0.23", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] } |
14 | libloading = "0.6.0" | 14 | libloading = "0.6.0" |
15 | memmap = "0.7" | 15 | memmap = "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 | ||
3 | use crate::{proc_macro::bridge, rustc_server::TokenStream}; | 3 | use std::{ |
4 | use std::fs::File; | 4 | fs::File, |
5 | use std::path::{Path, PathBuf}; | 5 | io, |
6 | path::{Path, PathBuf}, | ||
7 | }; | ||
6 | 8 | ||
7 | use goblin::{mach::Mach, Object}; | ||
8 | use libloading::Library; | 9 | use libloading::Library; |
9 | use memmap::Mmap; | 10 | use memmap::Mmap; |
11 | use object::Object; | ||
10 | use proc_macro_api::ProcMacroKind; | 12 | use proc_macro_api::ProcMacroKind; |
11 | use std::io; | 13 | |
14 | use crate::{proc_macro::bridge, rustc_server::TokenStream}; | ||
12 | 15 | ||
13 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; | 16 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; |
14 | 17 | ||
@@ -23,40 +26,26 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool { | |||
23 | fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> { | 26 | fn 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. |