diff options
Diffstat (limited to 'crates')
107 files changed, 1579 insertions, 831 deletions
diff --git a/crates/assists/src/handlers/generate_impl.rs b/crates/assists/src/handlers/generate_impl.rs index 114974465..960af5ab3 100644 --- a/crates/assists/src/handlers/generate_impl.rs +++ b/crates/assists/src/handlers/generate_impl.rs | |||
@@ -53,7 +53,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
53 | if let Some(type_params) = type_params { | 53 | if let Some(type_params) = type_params { |
54 | let lifetime_params = type_params | 54 | let lifetime_params = type_params |
55 | .lifetime_params() | 55 | .lifetime_params() |
56 | .filter_map(|it| it.lifetime_token()) | 56 | .filter_map(|it| it.lifetime()) |
57 | .map(|it| it.text().clone()); | 57 | .map(|it| it.text().clone()); |
58 | let type_params = type_params | 58 | let type_params = type_params |
59 | .type_params() | 59 | .type_params() |
diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs index 7db10f276..c5fec4e0a 100644 --- a/crates/assists/src/handlers/generate_new.rs +++ b/crates/assists/src/handlers/generate_new.rs | |||
@@ -99,7 +99,7 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String { | |||
99 | if let Some(type_params) = type_params { | 99 | if let Some(type_params) = type_params { |
100 | let lifetime_params = type_params | 100 | let lifetime_params = type_params |
101 | .lifetime_params() | 101 | .lifetime_params() |
102 | .filter_map(|it| it.lifetime_token()) | 102 | .filter_map(|it| it.lifetime()) |
103 | .map(|it| it.text().clone()); | 103 | .map(|it| it.text().clone()); |
104 | let type_params = | 104 | let type_params = |
105 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | 105 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); |
diff --git a/crates/assists/src/handlers/introduce_named_lifetime.rs b/crates/assists/src/handlers/introduce_named_lifetime.rs index 4cc8dae65..ab8fe3ea9 100644 --- a/crates/assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use rustc_hash::FxHashSet; |
2 | use syntax::{ | 2 | use syntax::{ |
3 | ast::{self, GenericParamsOwner, NameOwner}, | 3 | ast::{self, GenericParamsOwner, NameOwner}, |
4 | AstNode, SyntaxKind, TextRange, TextSize, | 4 | AstNode, TextRange, TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; | 7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists}; |
@@ -35,13 +35,12 @@ static ASSIST_LABEL: &str = "Introduce named lifetime"; | |||
35 | // FIXME: How can we handle renaming any one of multiple anonymous lifetimes? | 35 | // FIXME: How can we handle renaming any one of multiple anonymous lifetimes? |
36 | // FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo | 36 | // FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo |
37 | pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 37 | pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
38 | let lifetime_token = ctx | 38 | let lifetime = |
39 | .find_token_syntax_at_offset(SyntaxKind::LIFETIME) | 39 | ctx.find_node_at_offset::<ast::Lifetime>().filter(|lifetime| lifetime.text() == "'_")?; |
40 | .filter(|lifetime| lifetime.text() == "'_")?; | 40 | if let Some(fn_def) = lifetime.syntax().ancestors().find_map(ast::Fn::cast) { |
41 | if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::Fn::cast) { | 41 | generate_fn_def_assist(acc, &fn_def, lifetime.lifetime_ident_token()?.text_range()) |
42 | generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range()) | 42 | } else if let Some(impl_def) = lifetime.syntax().ancestors().find_map(ast::Impl::cast) { |
43 | } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::Impl::cast) { | 43 | generate_impl_def_assist(acc, &impl_def, lifetime.lifetime_ident_token()?.text_range()) |
44 | generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range()) | ||
45 | } else { | 44 | } else { |
46 | None | 45 | None |
47 | } | 46 | } |
@@ -58,7 +57,7 @@ fn generate_fn_def_assist( | |||
58 | let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end(); | 57 | let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end(); |
59 | let self_param = | 58 | let self_param = |
60 | // use the self if it's a reference and has no explicit lifetime | 59 | // use the self if it's a reference and has no explicit lifetime |
61 | param_list.self_param().filter(|p| p.lifetime_token().is_none() && p.amp_token().is_some()); | 60 | param_list.self_param().filter(|p| p.lifetime().is_none() && p.amp_token().is_some()); |
62 | // compute the location which implicitly has the same lifetime as the anonymous lifetime | 61 | // compute the location which implicitly has the same lifetime as the anonymous lifetime |
63 | let loc_needing_lifetime = if let Some(self_param) = self_param { | 62 | let loc_needing_lifetime = if let Some(self_param) = self_param { |
64 | // if we have a self reference, use that | 63 | // if we have a self reference, use that |
@@ -68,9 +67,7 @@ fn generate_fn_def_assist( | |||
68 | let fn_params_without_lifetime: Vec<_> = param_list | 67 | let fn_params_without_lifetime: Vec<_> = param_list |
69 | .params() | 68 | .params() |
70 | .filter_map(|param| match param.ty() { | 69 | .filter_map(|param| match param.ty() { |
71 | Some(ast::Type::RefType(ascribed_type)) | 70 | Some(ast::Type::RefType(ascribed_type)) if ascribed_type.lifetime().is_none() => { |
72 | if ascribed_type.lifetime_token() == None => | ||
73 | { | ||
74 | Some(ascribed_type.amp_token()?.text_range().end()) | 71 | Some(ascribed_type.amp_token()?.text_range().end()) |
75 | } | 72 | } |
76 | _ => None, | 73 | _ => None, |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index b9315f6c0..93869f92e 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -126,7 +126,7 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
126 | let anchor = ctx.name_ref_syntax.as_ref()?; | 126 | let anchor = ctx.name_ref_syntax.as_ref()?; |
127 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; | 127 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; |
128 | 128 | ||
129 | let possible_imports = imports_locator::find_similar_imports( | 129 | let mut all_mod_paths = imports_locator::find_similar_imports( |
130 | &ctx.sema, | 130 | &ctx.sema, |
131 | ctx.krate?, | 131 | ctx.krate?, |
132 | Some(100), | 132 | Some(100), |
@@ -144,15 +144,24 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
144 | }) | 144 | }) |
145 | }) | 145 | }) |
146 | .filter(|(mod_path, _)| mod_path.len() > 1) | 146 | .filter(|(mod_path, _)| mod_path.len() > 1) |
147 | .filter_map(|(import_path, definition)| { | 147 | .collect::<Vec<_>>(); |
148 | |||
149 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { | ||
150 | if let Some(name) = mod_path.segments.last().map(|name| name.to_string().to_lowercase()) { | ||
151 | if name.contains(&potential_import_name.to_lowercase()) { | ||
152 | return 0; | ||
153 | } | ||
154 | } | ||
155 | 1 | ||
156 | }); | ||
157 | |||
158 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| { | ||
148 | render_resolution_with_import( | 159 | render_resolution_with_import( |
149 | RenderContext::new(ctx), | 160 | RenderContext::new(ctx), |
150 | ImportEdit { import_path, import_scope: import_scope.clone() }, | 161 | ImportEdit { import_path, import_scope: import_scope.clone() }, |
151 | &definition, | 162 | &definition, |
152 | ) | 163 | ) |
153 | }); | 164 | })); |
154 | |||
155 | acc.add_all(possible_imports); | ||
156 | Some(()) | 165 | Some(()) |
157 | } | 166 | } |
158 | 167 | ||
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 7ffa79996..3248f6d20 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -267,7 +267,12 @@ impl ModuleDef { | |||
267 | _ => return, | 267 | _ => return, |
268 | }; | 268 | }; |
269 | 269 | ||
270 | hir_ty::diagnostics::validate_module_item(db, id, sink) | 270 | let module = match self.module(db) { |
271 | Some(it) => it, | ||
272 | None => return, | ||
273 | }; | ||
274 | |||
275 | hir_ty::diagnostics::validate_module_item(db, module.id.krate, id, sink) | ||
271 | } | 276 | } |
272 | } | 277 | } |
273 | 278 | ||
@@ -397,9 +402,9 @@ impl Module { | |||
397 | def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect() | 402 | def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect() |
398 | } | 403 | } |
399 | 404 | ||
400 | pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<ImplDef> { | 405 | pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> { |
401 | let def_map = db.crate_def_map(self.id.krate); | 406 | let def_map = db.crate_def_map(self.id.krate); |
402 | def_map[self.id.local_id].scope.impls().map(ImplDef::from).collect() | 407 | def_map[self.id.local_id].scope.impls().map(Impl::from).collect() |
403 | } | 408 | } |
404 | 409 | ||
405 | pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { | 410 | pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { |
@@ -780,8 +785,9 @@ impl Function { | |||
780 | } | 785 | } |
781 | 786 | ||
782 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 787 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
788 | let krate = self.module(db).id.krate; | ||
783 | hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); | 789 | hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); |
784 | hir_ty::diagnostics::validate_module_item(db, self.id.into(), sink); | 790 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); |
785 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | 791 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); |
786 | } | 792 | } |
787 | 793 | ||
@@ -970,7 +976,7 @@ impl MacroDef { | |||
970 | /// defines this macro. The reasons for this is that macros are expanded | 976 | /// defines this macro. The reasons for this is that macros are expanded |
971 | /// early, in `hir_expand`, where modules simply do not exist yet. | 977 | /// early, in `hir_expand`, where modules simply do not exist yet. |
972 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | 978 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { |
973 | let krate = self.id.krate?; | 979 | let krate = self.id.krate; |
974 | let module_id = db.crate_def_map(krate).root; | 980 | let module_id = db.crate_def_map(krate).root; |
975 | Some(Module::new(Crate { id: krate }, module_id)) | 981 | Some(Module::new(Crate { id: krate }, module_id)) |
976 | } | 982 | } |
@@ -1007,7 +1013,7 @@ pub enum AssocItem { | |||
1007 | } | 1013 | } |
1008 | pub enum AssocItemContainer { | 1014 | pub enum AssocItemContainer { |
1009 | Trait(Trait), | 1015 | Trait(Trait), |
1010 | ImplDef(ImplDef), | 1016 | Impl(Impl), |
1011 | } | 1017 | } |
1012 | pub trait AsAssocItem { | 1018 | pub trait AsAssocItem { |
1013 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>; | 1019 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>; |
@@ -1064,7 +1070,7 @@ impl AssocItem { | |||
1064 | }; | 1070 | }; |
1065 | match container { | 1071 | match container { |
1066 | AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), | 1072 | AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), |
1067 | AssocContainerId::ImplId(id) => AssocItemContainer::ImplDef(id.into()), | 1073 | AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()), |
1068 | AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), | 1074 | AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), |
1069 | } | 1075 | } |
1070 | } | 1076 | } |
@@ -1086,7 +1092,7 @@ pub enum GenericDef { | |||
1086 | Adt(Adt), | 1092 | Adt(Adt), |
1087 | Trait(Trait), | 1093 | Trait(Trait), |
1088 | TypeAlias(TypeAlias), | 1094 | TypeAlias(TypeAlias), |
1089 | ImplDef(ImplDef), | 1095 | Impl(Impl), |
1090 | // enum variants cannot have generics themselves, but their parent enums | 1096 | // enum variants cannot have generics themselves, but their parent enums |
1091 | // can, and this makes some code easier to write | 1097 | // can, and this makes some code easier to write |
1092 | EnumVariant(EnumVariant), | 1098 | EnumVariant(EnumVariant), |
@@ -1098,7 +1104,7 @@ impl_from!( | |||
1098 | Adt(Struct, Enum, Union), | 1104 | Adt(Struct, Enum, Union), |
1099 | Trait, | 1105 | Trait, |
1100 | TypeAlias, | 1106 | TypeAlias, |
1101 | ImplDef, | 1107 | Impl, |
1102 | EnumVariant, | 1108 | EnumVariant, |
1103 | Const | 1109 | Const |
1104 | for GenericDef | 1110 | for GenericDef |
@@ -1268,30 +1274,28 @@ impl LifetimeParam { | |||
1268 | 1274 | ||
1269 | // FIXME: rename from `ImplDef` to `Impl` | 1275 | // FIXME: rename from `ImplDef` to `Impl` |
1270 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1276 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1271 | pub struct ImplDef { | 1277 | pub struct Impl { |
1272 | pub(crate) id: ImplId, | 1278 | pub(crate) id: ImplId, |
1273 | } | 1279 | } |
1274 | 1280 | ||
1275 | impl ImplDef { | 1281 | impl Impl { |
1276 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { | 1282 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> { |
1277 | let inherent = db.inherent_impls_in_crate(krate.id); | 1283 | let inherent = db.inherent_impls_in_crate(krate.id); |
1278 | let trait_ = db.trait_impls_in_crate(krate.id); | 1284 | let trait_ = db.trait_impls_in_crate(krate.id); |
1279 | 1285 | ||
1280 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | 1286 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() |
1281 | } | 1287 | } |
1282 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { | 1288 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<Impl> { |
1283 | let impls = db.trait_impls_in_crate(krate.id); | 1289 | let impls = db.trait_impls_in_crate(krate.id); |
1284 | impls.for_trait(trait_.id).map(Self::from).collect() | 1290 | impls.for_trait(trait_.id).map(Self::from).collect() |
1285 | } | 1291 | } |
1286 | 1292 | ||
1293 | // FIXME: the return type is wrong. This should be a hir version of | ||
1294 | // `TraitRef` (ie, resolved `TypeRef`). | ||
1287 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1295 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1288 | db.impl_data(self.id).target_trait.clone() | 1296 | db.impl_data(self.id).target_trait.clone() |
1289 | } | 1297 | } |
1290 | 1298 | ||
1291 | pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef { | ||
1292 | db.impl_data(self.id).target_type.clone() | ||
1293 | } | ||
1294 | |||
1295 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { | 1299 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { |
1296 | let impl_data = db.impl_data(self.id); | 1300 | let impl_data = db.impl_data(self.id); |
1297 | let resolver = self.id.resolver(db.upcast()); | 1301 | let resolver = self.id.resolver(db.upcast()); |
@@ -1325,6 +1329,7 @@ impl ImplDef { | |||
1325 | let item = src.file_id.is_builtin_derive(db.upcast())?; | 1329 | let item = src.file_id.is_builtin_derive(db.upcast())?; |
1326 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); | 1330 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); |
1327 | 1331 | ||
1332 | // FIXME: handle `cfg_attr` | ||
1328 | let attr = item | 1333 | let attr = item |
1329 | .value | 1334 | .value |
1330 | .attrs() | 1335 | .attrs() |
@@ -1904,7 +1909,7 @@ pub enum ScopeDef { | |||
1904 | ModuleDef(ModuleDef), | 1909 | ModuleDef(ModuleDef), |
1905 | MacroDef(MacroDef), | 1910 | MacroDef(MacroDef), |
1906 | GenericParam(TypeParam), | 1911 | GenericParam(TypeParam), |
1907 | ImplSelfType(ImplDef), | 1912 | ImplSelfType(Impl), |
1908 | AdtSelfType(Adt), | 1913 | AdtSelfType(Adt), |
1909 | Local(Local), | 1914 | Local(Local), |
1910 | Unknown, | 1915 | Unknown, |
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 8d949b264..d01e1b33d 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -6,8 +6,8 @@ pub use hir_def::db::{ | |||
6 | FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, InternConstQuery, | 6 | FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, InternConstQuery, |
7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, | 7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, |
8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, | 8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, |
9 | ItemTreeQuery, LangItemQuery, ModuleLangItemsQuery, StaticDataQuery, StructDataQuery, | 9 | ItemTreeQuery, LangItemQuery, StaticDataQuery, StructDataQuery, TraitDataQuery, |
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | 10 | TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index dd3fcfe4a..8d0f84508 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs | |||
@@ -39,7 +39,7 @@ from_id![ | |||
39 | (hir_def::StaticId, crate::Static), | 39 | (hir_def::StaticId, crate::Static), |
40 | (hir_def::ConstId, crate::Const), | 40 | (hir_def::ConstId, crate::Const), |
41 | (hir_def::FunctionId, crate::Function), | 41 | (hir_def::FunctionId, crate::Function), |
42 | (hir_def::ImplId, crate::ImplDef), | 42 | (hir_def::ImplId, crate::Impl), |
43 | (hir_def::TypeParamId, crate::TypeParam), | 43 | (hir_def::TypeParamId, crate::TypeParam), |
44 | (hir_def::LifetimeParamId, crate::LifetimeParam), | 44 | (hir_def::LifetimeParamId, crate::LifetimeParam), |
45 | (hir_expand::MacroDefId, crate::MacroDef) | 45 | (hir_expand::MacroDefId, crate::MacroDef) |
@@ -146,7 +146,7 @@ impl From<GenericDef> for GenericDefId { | |||
146 | GenericDef::Adt(it) => GenericDefId::AdtId(it.into()), | 146 | GenericDef::Adt(it) => GenericDefId::AdtId(it.into()), |
147 | GenericDef::Trait(it) => GenericDefId::TraitId(it.id), | 147 | GenericDef::Trait(it) => GenericDefId::TraitId(it.id), |
148 | GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), | 148 | GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), |
149 | GenericDef::ImplDef(it) => GenericDefId::ImplId(it.id), | 149 | GenericDef::Impl(it) => GenericDefId::ImplId(it.id), |
150 | GenericDef::EnumVariant(it) => { | 150 | GenericDef::EnumVariant(it) => { |
151 | GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) | 151 | GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) |
152 | } | 152 | } |
@@ -162,7 +162,7 @@ impl From<GenericDefId> for GenericDef { | |||
162 | GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), | 162 | GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), |
163 | GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), | 163 | GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), |
164 | GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), | 164 | GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), |
165 | GenericDefId::ImplId(it) => GenericDef::ImplDef(it.into()), | 165 | GenericDefId::ImplId(it) => GenericDef::Impl(it.into()), |
166 | GenericDefId::EnumVariantId(it) => { | 166 | GenericDefId::EnumVariantId(it) => { |
167 | GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id }) | 167 | GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id }) |
168 | } | 168 | } |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 04845037f..c5b81b252 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, | 13 | db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, Impl, LifetimeParam, |
14 | LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, | 14 | MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub trait HasSource { | 17 | pub trait HasSource { |
@@ -110,15 +110,15 @@ impl HasSource for TypeAlias { | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | impl HasSource for MacroDef { | 112 | impl HasSource for MacroDef { |
113 | type Ast = ast::MacroRules; | 113 | type Ast = ast::Macro; |
114 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> { | 114 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> { |
115 | InFile { | 115 | InFile { |
116 | file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, | 116 | file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, |
117 | value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), | 117 | value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), |
118 | } | 118 | } |
119 | } | 119 | } |
120 | } | 120 | } |
121 | impl HasSource for ImplDef { | 121 | impl HasSource for Impl { |
122 | type Ast = ast::Impl; | 122 | type Ast = ast::Impl; |
123 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> { | 123 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> { |
124 | self.id.lookup(db.upcast()).source(db.upcast()) | 124 | self.id.lookup(db.upcast()).source(db.upcast()) |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0f399a2c6..3f4f8d8e4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -35,7 +35,7 @@ pub use crate::{ | |||
35 | code_model::{ | 35 | code_model::{ |
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | 36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, |
37 | Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, | 37 | Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, |
38 | GenericDef, HasVisibility, ImplDef, LifetimeParam, Local, MacroDef, Module, ModuleDef, | 38 | GenericDef, HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, |
39 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, | 39 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, |
40 | }, | 40 | }, |
41 | has_source::HasSource, | 41 | has_source::HasSource, |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 5959ac4ca..83ec91f58 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -25,7 +25,7 @@ use crate::{ | |||
25 | diagnostics::Diagnostic, | 25 | diagnostics::Diagnostic, |
26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
28 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local, | 28 | AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, LifetimeParam, Local, |
29 | MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, | 29 | MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, |
30 | VariantDef, | 30 | VariantDef, |
31 | }; | 31 | }; |
@@ -38,7 +38,7 @@ pub enum PathResolution { | |||
38 | Local(Local), | 38 | Local(Local), |
39 | /// A generic parameter | 39 | /// A generic parameter |
40 | TypeParam(TypeParam), | 40 | TypeParam(TypeParam), |
41 | SelfType(ImplDef), | 41 | SelfType(Impl), |
42 | Macro(MacroDef), | 42 | Macro(MacroDef), |
43 | AssocItem(AssocItem), | 43 | AssocItem(AssocItem), |
44 | } | 44 | } |
@@ -178,9 +178,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
178 | 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) |
179 | } | 179 | } |
180 | 180 | ||
181 | // FIXME: Replace the SyntaxToken with a typed ast Node/Token | 181 | pub fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> { |
182 | pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> { | 182 | self.imp.resolve_lifetime_param(lifetime) |
183 | self.imp.resolve_lifetime_param(lifetime_token) | ||
184 | } | 183 | } |
185 | 184 | ||
186 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 185 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
@@ -402,13 +401,9 @@ impl<'db> SemanticsImpl<'db> { | |||
402 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 401 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
403 | } | 402 | } |
404 | 403 | ||
405 | // FIXME: Replace the SyntaxToken with a typed ast Node/Token | 404 | fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> { |
406 | fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> { | 405 | let text = lifetime.text(); |
407 | if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME { | 406 | let lifetime_param = lifetime.syntax().ancestors().find_map(|syn| { |
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! { | 407 | let gpl = match_ast! { |
413 | match syn { | 408 | match syn { |
414 | ast::Fn(it) => it.generic_param_list()?, | 409 | ast::Fn(it) => it.generic_param_list()?, |
@@ -424,7 +419,7 @@ impl<'db> SemanticsImpl<'db> { | |||
424 | } | 419 | } |
425 | }; | 420 | }; |
426 | gpl.lifetime_params() | 421 | gpl.lifetime_params() |
427 | .find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text)) | 422 | .find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()) == Some(text)) |
428 | })?; | 423 | })?; |
429 | let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param); | 424 | let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param); |
430 | ToDef::to_def(self, src) | 425 | ToDef::to_def(self, src) |
@@ -713,7 +708,7 @@ to_def_impls![ | |||
713 | (crate::Enum, ast::Enum, enum_to_def), | 708 | (crate::Enum, ast::Enum, enum_to_def), |
714 | (crate::Union, ast::Union, union_to_def), | 709 | (crate::Union, ast::Union, union_to_def), |
715 | (crate::Trait, ast::Trait, trait_to_def), | 710 | (crate::Trait, ast::Trait, trait_to_def), |
716 | (crate::ImplDef, ast::Impl, impl_to_def), | 711 | (crate::Impl, ast::Impl, impl_to_def), |
717 | (crate::TypeAlias, ast::TypeAlias, type_alias_to_def), | 712 | (crate::TypeAlias, ast::TypeAlias, type_alias_to_def), |
718 | (crate::Const, ast::Const, const_to_def), | 713 | (crate::Const, ast::Const, const_to_def), |
719 | (crate::Static, ast::Static, static_to_def), | 714 | (crate::Static, ast::Static, static_to_def), |
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index a333d7aea..3efca5baa 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -157,8 +157,8 @@ impl SourceToDefCtx<'_, '_> { | |||
157 | let file_id = src.file_id.original_file(self.db.upcast()); | 157 | let file_id = src.file_id.original_file(self.db.upcast()); |
158 | let krate = self.file_to_def(file_id)?.krate; | 158 | let krate = self.file_to_def(file_id)?.krate; |
159 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); | 159 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); |
160 | let ast_id = Some(AstId::new(src.file_id, file_ast_id)); | 160 | let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); |
161 | Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false }) | 161 | Some(MacroDefId { krate, ast_id, kind, local_inner: false }) |
162 | } | 162 | } |
163 | 163 | ||
164 | pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { | 164 | pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { |
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index eafa3abb6..236d6f1b7 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs | |||
@@ -3,6 +3,7 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use arena::{map::ArenaMap, Arena}; | 5 | use arena::{map::ArenaMap, Arena}; |
6 | use base_db::CrateId; | ||
6 | use either::Either; | 7 | use either::Either; |
7 | use hir_expand::{ | 8 | use hir_expand::{ |
8 | name::{AsName, Name}, | 9 | name::{AsName, Name}, |
@@ -66,8 +67,13 @@ pub enum ReprKind { | |||
66 | Other, | 67 | Other, |
67 | } | 68 | } |
68 | 69 | ||
69 | fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> { | 70 | fn repr_from_value( |
70 | item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) | 71 | db: &dyn DefDatabase, |
72 | krate: CrateId, | ||
73 | item_tree: &ItemTree, | ||
74 | of: AttrOwner, | ||
75 | ) -> Option<ReprKind> { | ||
76 | item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt) | ||
71 | } | 77 | } |
72 | 78 | ||
73 | fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | 79 | fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { |
@@ -86,12 +92,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | |||
86 | impl StructData { | 92 | impl StructData { |
87 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { | 93 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { |
88 | let loc = id.lookup(db); | 94 | let loc = id.lookup(db); |
95 | let krate = loc.container.module(db).krate; | ||
89 | let item_tree = db.item_tree(loc.id.file_id); | 96 | let item_tree = db.item_tree(loc.id.file_id); |
90 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | 97 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); |
91 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 98 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
92 | 99 | ||
93 | let strukt = &item_tree[loc.id.value]; | 100 | let strukt = &item_tree[loc.id.value]; |
94 | let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None); | 101 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None); |
95 | Arc::new(StructData { | 102 | Arc::new(StructData { |
96 | name: strukt.name.clone(), | 103 | name: strukt.name.clone(), |
97 | variant_data: Arc::new(variant_data), | 104 | variant_data: Arc::new(variant_data), |
@@ -100,12 +107,13 @@ impl StructData { | |||
100 | } | 107 | } |
101 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { | 108 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { |
102 | let loc = id.lookup(db); | 109 | let loc = id.lookup(db); |
110 | let krate = loc.container.module(db).krate; | ||
103 | let item_tree = db.item_tree(loc.id.file_id); | 111 | let item_tree = db.item_tree(loc.id.file_id); |
104 | let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); | 112 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); |
105 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 113 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); |
106 | 114 | ||
107 | let union = &item_tree[loc.id.value]; | 115 | let union = &item_tree[loc.id.value]; |
108 | let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None); | 116 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None); |
109 | 117 | ||
110 | Arc::new(StructData { | 118 | Arc::new(StructData { |
111 | name: union.name.clone(), | 119 | name: union.name.clone(), |
@@ -118,16 +126,23 @@ impl StructData { | |||
118 | impl EnumData { | 126 | impl EnumData { |
119 | pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { | 127 | pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { |
120 | let loc = e.lookup(db); | 128 | let loc = e.lookup(db); |
129 | let krate = loc.container.module(db).krate; | ||
121 | let item_tree = db.item_tree(loc.id.file_id); | 130 | let item_tree = db.item_tree(loc.id.file_id); |
122 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 131 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); |
123 | 132 | ||
124 | let enum_ = &item_tree[loc.id.value]; | 133 | let enum_ = &item_tree[loc.id.value]; |
125 | let mut variants = Arena::new(); | 134 | let mut variants = Arena::new(); |
126 | for var_id in enum_.variants.clone() { | 135 | for var_id in enum_.variants.clone() { |
127 | if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { | 136 | if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) { |
128 | let var = &item_tree[var_id]; | 137 | let var = &item_tree[var_id]; |
129 | let var_data = | 138 | let var_data = lower_fields( |
130 | lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility)); | 139 | db, |
140 | krate, | ||
141 | &item_tree, | ||
142 | &cfg_options, | ||
143 | &var.fields, | ||
144 | Some(enum_.visibility), | ||
145 | ); | ||
131 | 146 | ||
132 | variants.alloc(EnumVariantData { | 147 | variants.alloc(EnumVariantData { |
133 | name: var.name.clone(), | 148 | name: var.name.clone(), |
@@ -170,7 +185,7 @@ fn lower_enum( | |||
170 | .variant_list() | 185 | .variant_list() |
171 | .into_iter() | 186 | .into_iter() |
172 | .flat_map(|it| it.variants()) | 187 | .flat_map(|it| it.variants()) |
173 | .filter(|var| expander.is_cfg_enabled(var)); | 188 | .filter(|var| expander.is_cfg_enabled(db, var)); |
174 | for var in variants { | 189 | for var in variants { |
175 | trace.alloc( | 190 | trace.alloc( |
176 | || var.clone(), | 191 | || var.clone(), |
@@ -262,7 +277,7 @@ fn lower_struct( | |||
262 | match &ast.value { | 277 | match &ast.value { |
263 | ast::StructKind::Tuple(fl) => { | 278 | ast::StructKind::Tuple(fl) => { |
264 | for (i, fd) in fl.fields().enumerate() { | 279 | for (i, fd) in fl.fields().enumerate() { |
265 | if !expander.is_cfg_enabled(&fd) { | 280 | if !expander.is_cfg_enabled(db, &fd) { |
266 | continue; | 281 | continue; |
267 | } | 282 | } |
268 | 283 | ||
@@ -279,7 +294,7 @@ fn lower_struct( | |||
279 | } | 294 | } |
280 | ast::StructKind::Record(fl) => { | 295 | ast::StructKind::Record(fl) => { |
281 | for fd in fl.fields() { | 296 | for fd in fl.fields() { |
282 | if !expander.is_cfg_enabled(&fd) { | 297 | if !expander.is_cfg_enabled(db, &fd) { |
283 | continue; | 298 | continue; |
284 | } | 299 | } |
285 | 300 | ||
@@ -299,6 +314,8 @@ fn lower_struct( | |||
299 | } | 314 | } |
300 | 315 | ||
301 | fn lower_fields( | 316 | fn lower_fields( |
317 | db: &dyn DefDatabase, | ||
318 | krate: CrateId, | ||
302 | item_tree: &ItemTree, | 319 | item_tree: &ItemTree, |
303 | cfg_options: &CfgOptions, | 320 | cfg_options: &CfgOptions, |
304 | fields: &Fields, | 321 | fields: &Fields, |
@@ -308,7 +325,7 @@ fn lower_fields( | |||
308 | Fields::Record(flds) => { | 325 | Fields::Record(flds) => { |
309 | let mut arena = Arena::new(); | 326 | let mut arena = Arena::new(); |
310 | for field_id in flds.clone() { | 327 | for field_id in flds.clone() { |
311 | if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { | 328 | if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) { |
312 | arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); | 329 | arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); |
313 | } | 330 | } |
314 | } | 331 | } |
@@ -317,7 +334,7 @@ fn lower_fields( | |||
317 | Fields::Tuple(flds) => { | 334 | Fields::Tuple(flds) => { |
318 | let mut arena = Arena::new(); | 335 | let mut arena = Arena::new(); |
319 | for field_id in flds.clone() { | 336 | for field_id in flds.clone() { |
320 | if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { | 337 | if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) { |
321 | arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); | 338 | arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); |
322 | } | 339 | } |
323 | } | 340 | } |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index c64b78445..9cd0b72aa 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::{ops, sync::Arc}; | 3 | use std::{ops, sync::Arc}; |
4 | 4 | ||
5 | use base_db::CrateId; | ||
5 | use cfg::{CfgExpr, CfgOptions}; | 6 | use cfg::{CfgExpr, CfgOptions}; |
6 | use either::Either; | 7 | use either::Either; |
7 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; | 8 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; |
@@ -38,12 +39,16 @@ impl From<Documentation> for String { | |||
38 | } | 39 | } |
39 | } | 40 | } |
40 | 41 | ||
42 | /// Syntactical attributes, without filtering of `cfg_attr`s. | ||
41 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 43 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
42 | pub struct Attrs { | 44 | pub struct RawAttrs { |
43 | entries: Option<Arc<[Attr]>>, | 45 | entries: Option<Arc<[Attr]>>, |
44 | } | 46 | } |
45 | 47 | ||
46 | impl ops::Deref for Attrs { | 48 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
49 | pub struct Attrs(RawAttrs); | ||
50 | |||
51 | impl ops::Deref for RawAttrs { | ||
47 | type Target = [Attr]; | 52 | type Target = [Attr]; |
48 | 53 | ||
49 | fn deref(&self) -> &[Attr] { | 54 | fn deref(&self) -> &[Attr] { |
@@ -54,19 +59,88 @@ impl ops::Deref for Attrs { | |||
54 | } | 59 | } |
55 | } | 60 | } |
56 | 61 | ||
62 | impl ops::Deref for Attrs { | ||
63 | type Target = [Attr]; | ||
64 | |||
65 | fn deref(&self) -> &[Attr] { | ||
66 | match &self.0.entries { | ||
67 | Some(it) => &*it, | ||
68 | None => &[], | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | impl RawAttrs { | ||
74 | pub const EMPTY: Self = Self { entries: None }; | ||
75 | |||
76 | pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self { | ||
77 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) | ||
78 | .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); | ||
79 | |||
80 | let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); | ||
81 | let attrs = outer_attrs | ||
82 | .chain(inner_attrs.into_iter().flatten()) | ||
83 | .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene))); | ||
84 | |||
85 | let outer_docs = | ||
86 | ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); | ||
87 | let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| { | ||
88 | ( | ||
89 | docs_text.syntax().text_range().start(), | ||
90 | docs_text.doc_comment().map(|doc| Attr { | ||
91 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | ||
92 | path: ModPath::from(hir_expand::name!(doc)), | ||
93 | }), | ||
94 | ) | ||
95 | }); | ||
96 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved | ||
97 | let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); | ||
98 | let entries = if attrs.is_empty() { | ||
99 | // Avoid heap allocation | ||
100 | None | ||
101 | } else { | ||
102 | Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect()) | ||
103 | }; | ||
104 | Self { entries } | ||
105 | } | ||
106 | |||
107 | fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self { | ||
108 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); | ||
109 | Self::new(owner.value, &hygiene) | ||
110 | } | ||
111 | |||
112 | pub(crate) fn merge(&self, other: Self) -> Self { | ||
113 | match (&self.entries, &other.entries) { | ||
114 | (None, None) => Self::EMPTY, | ||
115 | (Some(entries), None) | (None, Some(entries)) => { | ||
116 | Self { entries: Some(entries.clone()) } | ||
117 | } | ||
118 | (Some(a), Some(b)) => { | ||
119 | Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) } | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. | ||
125 | pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs { | ||
126 | // FIXME actually implement this | ||
127 | Attrs(self) | ||
128 | } | ||
129 | } | ||
130 | |||
57 | impl Attrs { | 131 | impl Attrs { |
58 | pub const EMPTY: Attrs = Attrs { entries: None }; | 132 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); |
59 | 133 | ||
60 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | 134 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { |
61 | match def { | 135 | let raw_attrs = match def { |
62 | AttrDefId::ModuleId(module) => { | 136 | AttrDefId::ModuleId(module) => { |
63 | let def_map = db.crate_def_map(module.krate); | 137 | let def_map = db.crate_def_map(module.krate); |
64 | let mod_data = &def_map[module.local_id]; | 138 | let mod_data = &def_map[module.local_id]; |
65 | match mod_data.declaration_source(db) { | 139 | match mod_data.declaration_source(db) { |
66 | Some(it) => { | 140 | Some(it) => { |
67 | Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) | 141 | RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) |
68 | } | 142 | } |
69 | None => Attrs::from_attrs_owner( | 143 | None => RawAttrs::from_attrs_owner( |
70 | db, | 144 | db, |
71 | mod_data.definition_source(db).as_ref().map(|src| match src { | 145 | mod_data.definition_source(db).as_ref().map(|src| match src { |
72 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, | 146 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, |
@@ -78,14 +152,14 @@ impl Attrs { | |||
78 | AttrDefId::FieldId(it) => { | 152 | AttrDefId::FieldId(it) => { |
79 | let src = it.parent.child_source(db); | 153 | let src = it.parent.child_source(db); |
80 | match &src.value[it.local_id] { | 154 | match &src.value[it.local_id] { |
81 | Either::Left(_tuple) => Attrs::default(), | 155 | Either::Left(_tuple) => RawAttrs::default(), |
82 | Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)), | 156 | Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)), |
83 | } | 157 | } |
84 | } | 158 | } |
85 | AttrDefId::EnumVariantId(var_id) => { | 159 | AttrDefId::EnumVariantId(var_id) => { |
86 | let src = var_id.parent.child_source(db); | 160 | let src = var_id.parent.child_source(db); |
87 | let src = src.as_ref().map(|it| &it[var_id.local_id]); | 161 | let src = src.as_ref().map(|it| &it[var_id.local_id]); |
88 | Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) | 162 | RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) |
89 | } | 163 | } |
90 | AttrDefId::AdtId(it) => match it { | 164 | AttrDefId::AdtId(it) => match it { |
91 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 165 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
@@ -101,53 +175,19 @@ impl Attrs { | |||
101 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 175 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
102 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 176 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
103 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 177 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
104 | } | ||
105 | } | ||
106 | |||
107 | pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { | ||
108 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); | ||
109 | Attrs::new(owner.value, &hygiene) | ||
110 | } | ||
111 | |||
112 | pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { | ||
113 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) | ||
114 | .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); | ||
115 | |||
116 | let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); | ||
117 | let attrs = outer_attrs | ||
118 | .chain(inner_attrs.into_iter().flatten()) | ||
119 | .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene))); | ||
120 | |||
121 | let outer_docs = | ||
122 | ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); | ||
123 | let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| { | ||
124 | ( | ||
125 | docs_text.syntax().text_range().start(), | ||
126 | docs_text.doc_comment().map(|doc| Attr { | ||
127 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | ||
128 | path: ModPath::from(hir_expand::name!(doc)), | ||
129 | }), | ||
130 | ) | ||
131 | }); | ||
132 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved | ||
133 | let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); | ||
134 | let entries = if attrs.is_empty() { | ||
135 | // Avoid heap allocation | ||
136 | None | ||
137 | } else { | ||
138 | Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect()) | ||
139 | }; | 178 | }; |
140 | Attrs { entries } | 179 | |
180 | raw_attrs.filter(db, def.krate(db)) | ||
141 | } | 181 | } |
142 | 182 | ||
143 | pub fn merge(&self, other: Attrs) -> Attrs { | 183 | pub fn merge(&self, other: Attrs) -> Attrs { |
144 | match (&self.entries, &other.entries) { | 184 | match (&self.0.entries, &other.0.entries) { |
145 | (None, None) => Attrs { entries: None }, | 185 | (None, None) => Attrs::EMPTY, |
146 | (Some(entries), None) | (None, Some(entries)) => { | 186 | (Some(entries), None) | (None, Some(entries)) => { |
147 | Attrs { entries: Some(entries.clone()) } | 187 | Attrs(RawAttrs { entries: Some(entries.clone()) }) |
148 | } | 188 | } |
149 | (Some(a), Some(b)) => { | 189 | (Some(a), Some(b)) => { |
150 | Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) } | 190 | Attrs(RawAttrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }) |
151 | } | 191 | } |
152 | } | 192 | } |
153 | } | 193 | } |
@@ -291,16 +331,16 @@ impl<'a> AttrQuery<'a> { | |||
291 | } | 331 | } |
292 | } | 332 | } |
293 | 333 | ||
294 | fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> Attrs | 334 | fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> RawAttrs |
295 | where | 335 | where |
296 | N: ast::AttrsOwner, | 336 | N: ast::AttrsOwner, |
297 | { | 337 | { |
298 | let src = InFile::new(src.file_id, src.to_node(db.upcast())); | 338 | let src = InFile::new(src.file_id, src.to_node(db.upcast())); |
299 | Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) | 339 | RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) |
300 | } | 340 | } |
301 | 341 | ||
302 | fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs { | 342 | fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs { |
303 | let tree = db.item_tree(id.file_id); | 343 | let tree = db.item_tree(id.file_id); |
304 | let mod_item = N::id_to_mod_item(id.value); | 344 | let mod_item = N::id_to_mod_item(id.value); |
305 | tree.attrs(mod_item.into()).clone() | 345 | tree.raw_attrs(mod_item.into()).clone() |
306 | } | 346 | } |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index c5d6f5fb0..998b82601 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -24,7 +24,7 @@ use test_utils::mark; | |||
24 | pub(crate) use lower::LowerCtx; | 24 | pub(crate) use lower::LowerCtx; |
25 | 25 | ||
26 | use crate::{ | 26 | use crate::{ |
27 | attr::Attrs, | 27 | attr::{Attrs, RawAttrs}, |
28 | db::DefDatabase, | 28 | db::DefDatabase, |
29 | expr::{Expr, ExprId, Pat, PatId}, | 29 | expr::{Expr, ExprId, Pat, PatId}, |
30 | item_scope::BuiltinShadowMode, | 30 | item_scope::BuiltinShadowMode, |
@@ -40,6 +40,7 @@ use crate::{ | |||
40 | pub(crate) struct CfgExpander { | 40 | pub(crate) struct CfgExpander { |
41 | cfg_options: CfgOptions, | 41 | cfg_options: CfgOptions, |
42 | hygiene: Hygiene, | 42 | hygiene: Hygiene, |
43 | krate: CrateId, | ||
43 | } | 44 | } |
44 | 45 | ||
45 | pub(crate) struct Expander { | 46 | pub(crate) struct Expander { |
@@ -65,15 +66,15 @@ impl CfgExpander { | |||
65 | ) -> CfgExpander { | 66 | ) -> CfgExpander { |
66 | let hygiene = Hygiene::new(db.upcast(), current_file_id); | 67 | let hygiene = Hygiene::new(db.upcast(), current_file_id); |
67 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); | 68 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); |
68 | CfgExpander { cfg_options, hygiene } | 69 | CfgExpander { cfg_options, hygiene, krate } |
69 | } | 70 | } |
70 | 71 | ||
71 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | 72 | pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs { |
72 | Attrs::new(owner, &self.hygiene) | 73 | RawAttrs::new(owner, &self.hygiene).filter(db, self.krate) |
73 | } | 74 | } |
74 | 75 | ||
75 | pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { | 76 | pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool { |
76 | let attrs = self.parse_attrs(owner); | 77 | let attrs = self.parse_attrs(db, owner); |
77 | attrs.is_cfg_enabled(&self.cfg_options) | 78 | attrs.is_cfg_enabled(&self.cfg_options) |
78 | } | 79 | } |
79 | } | 80 | } |
@@ -189,8 +190,8 @@ impl Expander { | |||
189 | InFile { file_id: self.current_file_id, value } | 190 | InFile { file_id: self.current_file_id, value } |
190 | } | 191 | } |
191 | 192 | ||
192 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | 193 | pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs { |
193 | self.cfg_expander.parse_attrs(owner) | 194 | self.cfg_expander.parse_attrs(db, owner) |
194 | } | 195 | } |
195 | 196 | ||
196 | pub(crate) fn cfg_options(&self) -> &CfgOptions { | 197 | pub(crate) fn cfg_options(&self) -> &CfgOptions { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bdba4c33e..0f404be1b 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -233,8 +233,7 @@ impl ExprCollector<'_> { | |||
233 | let res = self.collect_block(block); | 233 | let res = self.collect_block(block); |
234 | match &mut self.body.exprs[res] { | 234 | match &mut self.body.exprs[res] { |
235 | Expr::Block { label: block_label, .. } => { | 235 | Expr::Block { label: block_label, .. } => { |
236 | *block_label = | 236 | *block_label = label.lifetime().map(|t| Name::new_lifetime(&t)) |
237 | label.lifetime_token().map(|t| Name::new_lifetime(&t)) | ||
238 | } | 237 | } |
239 | _ => unreachable!(), | 238 | _ => unreachable!(), |
240 | } | 239 | } |
@@ -254,10 +253,7 @@ impl ExprCollector<'_> { | |||
254 | self.alloc_expr( | 253 | self.alloc_expr( |
255 | Expr::Loop { | 254 | Expr::Loop { |
256 | body, | 255 | body, |
257 | label: e | 256 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), |
258 | .label() | ||
259 | .and_then(|l| l.lifetime_token()) | ||
260 | .map(|l| Name::new_lifetime(&l)), | ||
261 | }, | 257 | }, |
262 | syntax_ptr, | 258 | syntax_ptr, |
263 | ) | 259 | ) |
@@ -288,7 +284,7 @@ impl ExprCollector<'_> { | |||
288 | body: match_expr, | 284 | body: match_expr, |
289 | label: e | 285 | label: e |
290 | .label() | 286 | .label() |
291 | .and_then(|l| l.lifetime_token()) | 287 | .and_then(|l| l.lifetime()) |
292 | .map(|l| Name::new_lifetime(&l)), | 288 | .map(|l| Name::new_lifetime(&l)), |
293 | }, | 289 | }, |
294 | syntax_ptr, | 290 | syntax_ptr, |
@@ -301,10 +297,7 @@ impl ExprCollector<'_> { | |||
301 | Expr::While { | 297 | Expr::While { |
302 | condition, | 298 | condition, |
303 | body, | 299 | body, |
304 | label: e | 300 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), |
305 | .label() | ||
306 | .and_then(|l| l.lifetime_token()) | ||
307 | .map(|l| Name::new_lifetime(&l)), | ||
308 | }, | 301 | }, |
309 | syntax_ptr, | 302 | syntax_ptr, |
310 | ) | 303 | ) |
@@ -318,10 +311,7 @@ impl ExprCollector<'_> { | |||
318 | iterable, | 311 | iterable, |
319 | pat, | 312 | pat, |
320 | body, | 313 | body, |
321 | label: e | 314 | label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)), |
322 | .label() | ||
323 | .and_then(|l| l.lifetime_token()) | ||
324 | .map(|l| Name::new_lifetime(&l)), | ||
325 | }, | 315 | }, |
326 | syntax_ptr, | 316 | syntax_ptr, |
327 | ) | 317 | ) |
@@ -380,13 +370,13 @@ impl ExprCollector<'_> { | |||
380 | self.alloc_expr(path, syntax_ptr) | 370 | self.alloc_expr(path, syntax_ptr) |
381 | } | 371 | } |
382 | ast::Expr::ContinueExpr(e) => self.alloc_expr( | 372 | ast::Expr::ContinueExpr(e) => self.alloc_expr( |
383 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | 373 | Expr::Continue { label: e.lifetime().map(|l| Name::new_lifetime(&l)) }, |
384 | syntax_ptr, | 374 | syntax_ptr, |
385 | ), | 375 | ), |
386 | ast::Expr::BreakExpr(e) => { | 376 | ast::Expr::BreakExpr(e) => { |
387 | let expr = e.expr().map(|e| self.collect_expr(e)); | 377 | let expr = e.expr().map(|e| self.collect_expr(e)); |
388 | self.alloc_expr( | 378 | self.alloc_expr( |
389 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | 379 | Expr::Break { expr, label: e.lifetime().map(|l| Name::new_lifetime(&l)) }, |
390 | syntax_ptr, | 380 | syntax_ptr, |
391 | ) | 381 | ) |
392 | } | 382 | } |
@@ -772,7 +762,10 @@ impl ExprCollector<'_> { | |||
772 | | ast::Item::Module(_) | 762 | | ast::Item::Module(_) |
773 | | ast::Item::MacroCall(_) => return None, | 763 | | ast::Item::MacroCall(_) => return None, |
774 | ast::Item::MacroRules(def) => { | 764 | ast::Item::MacroRules(def) => { |
775 | return Some(Either::Right(def)); | 765 | return Some(Either::Right(ast::Macro::from(def))); |
766 | } | ||
767 | ast::Item::MacroDef(def) => { | ||
768 | return Some(Either::Right(ast::Macro::from(def))); | ||
776 | } | 769 | } |
777 | }; | 770 | }; |
778 | 771 | ||
@@ -800,7 +793,7 @@ impl ExprCollector<'_> { | |||
800 | } | 793 | } |
801 | Either::Right(e) => { | 794 | Either::Right(e) => { |
802 | let mac = MacroDefId { | 795 | let mac = MacroDefId { |
803 | krate: Some(self.expander.module.krate), | 796 | krate: self.expander.module.krate, |
804 | ast_id: Some(self.expander.ast_id(&e)), | 797 | ast_id: Some(self.expander.ast_id(&e)), |
805 | kind: MacroDefKind::Declarative, | 798 | kind: MacroDefKind::Declarative, |
806 | local_inner: false, | 799 | local_inner: false, |
@@ -970,7 +963,7 @@ impl ExprCollector<'_> { | |||
970 | /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when | 963 | /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when |
971 | /// not. | 964 | /// not. |
972 | fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> { | 965 | fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> { |
973 | match self.expander.parse_attrs(owner).cfg() { | 966 | match self.expander.parse_attrs(self.db, owner).cfg() { |
974 | Some(cfg) => { | 967 | Some(cfg) => { |
975 | if self.expander.cfg_options().check(&cfg) != Some(false) { | 968 | if self.expander.cfg_options().check(&cfg) != Some(false) { |
976 | return Some(()); | 969 | return Some(()); |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index dd3a906af..e7b7724f7 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -35,6 +35,7 @@ pub struct FunctionData { | |||
35 | impl FunctionData { | 35 | impl FunctionData { |
36 | pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { | 36 | pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { |
37 | let loc = func.lookup(db); | 37 | let loc = func.lookup(db); |
38 | let krate = loc.container.module(db).krate; | ||
38 | let item_tree = db.item_tree(loc.id.file_id); | 39 | let item_tree = db.item_tree(loc.id.file_id); |
39 | let func = &item_tree[loc.id.value]; | 40 | let func = &item_tree[loc.id.value]; |
40 | 41 | ||
@@ -42,7 +43,7 @@ impl FunctionData { | |||
42 | name: func.name.clone(), | 43 | name: func.name.clone(), |
43 | params: func.params.to_vec(), | 44 | params: func.params.to_vec(), |
44 | ret_type: func.ret_type.clone(), | 45 | ret_type: func.ret_type.clone(), |
45 | attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), | 46 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(), |
46 | has_self_param: func.has_self_param, | 47 | has_self_param: func.has_self_param, |
47 | has_body: func.has_body, | 48 | has_body: func.has_body, |
48 | is_unsafe: func.is_unsafe, | 49 | is_unsafe: func.is_unsafe, |
@@ -233,7 +234,7 @@ fn collect_items( | |||
233 | match item { | 234 | match item { |
234 | AssocItem::Function(id) => { | 235 | AssocItem::Function(id) => { |
235 | let item = &item_tree[id]; | 236 | let item = &item_tree[id]; |
236 | let attrs = item_tree.attrs(ModItem::from(id).into()); | 237 | let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into()); |
237 | if !attrs.is_cfg_enabled(&cfg_options) { | 238 | if !attrs.is_cfg_enabled(&cfg_options) { |
238 | continue; | 239 | continue; |
239 | } | 240 | } |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 7f250da33..d1a459066 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -16,8 +16,8 @@ use crate::{ | |||
16 | lang_item::{LangItemTarget, LangItems}, | 16 | lang_item::{LangItemTarget, LangItems}, |
17 | nameres::CrateDefMap, | 17 | nameres::CrateDefMap, |
18 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 18 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, |
19 | GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, | 19 | GenericDefId, ImplId, ImplLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, |
20 | TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, | 20 | TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | #[salsa::query_group(InternDatabaseStorage)] | 23 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -95,9 +95,6 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
95 | #[salsa::invoke(Attrs::attrs_query)] | 95 | #[salsa::invoke(Attrs::attrs_query)] |
96 | fn attrs(&self, def: AttrDefId) -> Attrs; | 96 | fn attrs(&self, def: AttrDefId) -> Attrs; |
97 | 97 | ||
98 | #[salsa::invoke(LangItems::module_lang_items_query)] | ||
99 | fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>; | ||
100 | |||
101 | #[salsa::invoke(LangItems::crate_lang_items_query)] | 98 | #[salsa::invoke(LangItems::crate_lang_items_query)] |
102 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; | 99 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; |
103 | 100 | ||
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 924046435..41134d23b 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -260,9 +260,8 @@ impl GenericParams { | |||
260 | self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); | 260 | self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); |
261 | } | 261 | } |
262 | for lifetime_param in params.lifetime_params() { | 262 | for lifetime_param in params.lifetime_params() { |
263 | let name = lifetime_param | 263 | let name = |
264 | .lifetime_token() | 264 | lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(<)); |
265 | .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); | ||
266 | let param = LifetimeParamData { name: name.clone() }; | 265 | let param = LifetimeParamData { name: name.clone() }; |
267 | let param_id = self.lifetimes.alloc(param); | 266 | let param_id = self.lifetimes.alloc(param); |
268 | sm.lifetime_params.insert(param_id, lifetime_param.clone()); | 267 | sm.lifetime_params.insert(param_id, lifetime_param.clone()); |
@@ -275,8 +274,8 @@ impl GenericParams { | |||
275 | for pred in where_clause.predicates() { | 274 | for pred in where_clause.predicates() { |
276 | let target = if let Some(type_ref) = pred.ty() { | 275 | let target = if let Some(type_ref) = pred.ty() { |
277 | Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) | 276 | Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) |
278 | } else if let Some(lifetime_tok) = pred.lifetime_token() { | 277 | } else if let Some(lifetime) = pred.lifetime() { |
279 | Either::Right(LifetimeRef::from_token(lifetime_tok)) | 278 | Either::Right(LifetimeRef::new(&lifetime)) |
280 | } else { | 279 | } else { |
281 | continue; | 280 | continue; |
282 | }; | 281 | }; |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index a8b3fe844..62ab3b2bd 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -363,7 +363,7 @@ impl ItemInNs { | |||
363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | 363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, |
364 | ModuleDefId::BuiltinType(_) => return None, | 364 | ModuleDefId::BuiltinType(_) => return None, |
365 | }, | 365 | }, |
366 | ItemInNs::Macros(id) => return id.krate, | 366 | ItemInNs::Macros(id) => return Some(id.krate), |
367 | }) | 367 | }) |
368 | } | 368 | } |
369 | } | 369 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 1c9babf37..5eb7cae7f 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -13,6 +13,7 @@ use std::{ | |||
13 | 13 | ||
14 | use arena::{Arena, Idx, RawId}; | 14 | use arena::{Arena, Idx, RawId}; |
15 | use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; | 15 | use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; |
16 | use base_db::CrateId; | ||
16 | use either::Either; | 17 | use either::Either; |
17 | use hir_expand::{ | 18 | use hir_expand::{ |
18 | ast_id_map::FileAstId, | 19 | ast_id_map::FileAstId, |
@@ -26,7 +27,7 @@ use syntax::{ast, match_ast}; | |||
26 | use test_utils::mark; | 27 | use test_utils::mark; |
27 | 28 | ||
28 | use crate::{ | 29 | use crate::{ |
29 | attr::Attrs, | 30 | attr::{Attrs, RawAttrs}, |
30 | db::DefDatabase, | 31 | db::DefDatabase, |
31 | generics::GenericParams, | 32 | generics::GenericParams, |
32 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, | 33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, |
@@ -67,7 +68,7 @@ impl GenericParamsId { | |||
67 | #[derive(Debug, Eq, PartialEq)] | 68 | #[derive(Debug, Eq, PartialEq)] |
68 | pub struct ItemTree { | 69 | pub struct ItemTree { |
69 | top_level: SmallVec<[ModItem; 1]>, | 70 | top_level: SmallVec<[ModItem; 1]>, |
70 | attrs: FxHashMap<AttrOwner, Attrs>, | 71 | attrs: FxHashMap<AttrOwner, RawAttrs>, |
71 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, | 72 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, |
72 | 73 | ||
73 | data: Option<Box<ItemTreeData>>, | 74 | data: Option<Box<ItemTreeData>>, |
@@ -88,7 +89,7 @@ impl ItemTree { | |||
88 | let mut item_tree = match_ast! { | 89 | let mut item_tree = match_ast! { |
89 | match syntax { | 90 | match syntax { |
90 | ast::SourceFile(file) => { | 91 | ast::SourceFile(file) => { |
91 | top_attrs = Some(Attrs::new(&file, &hygiene)); | 92 | top_attrs = Some(RawAttrs::new(&file, &hygiene)); |
92 | ctx.lower_module_items(&file) | 93 | ctx.lower_module_items(&file) |
93 | }, | 94 | }, |
94 | ast::MacroItems(items) => { | 95 | ast::MacroItems(items) => { |
@@ -143,6 +144,7 @@ impl ItemTree { | |||
143 | mods, | 144 | mods, |
144 | macro_calls, | 145 | macro_calls, |
145 | macro_rules, | 146 | macro_rules, |
147 | macro_defs, | ||
146 | exprs, | 148 | exprs, |
147 | vis, | 149 | vis, |
148 | generics, | 150 | generics, |
@@ -164,6 +166,7 @@ impl ItemTree { | |||
164 | mods.shrink_to_fit(); | 166 | mods.shrink_to_fit(); |
165 | macro_calls.shrink_to_fit(); | 167 | macro_calls.shrink_to_fit(); |
166 | macro_rules.shrink_to_fit(); | 168 | macro_rules.shrink_to_fit(); |
169 | macro_defs.shrink_to_fit(); | ||
167 | exprs.shrink_to_fit(); | 170 | exprs.shrink_to_fit(); |
168 | 171 | ||
169 | vis.arena.shrink_to_fit(); | 172 | vis.arena.shrink_to_fit(); |
@@ -178,12 +181,16 @@ impl ItemTree { | |||
178 | } | 181 | } |
179 | 182 | ||
180 | /// Returns the inner attributes of the source file. | 183 | /// Returns the inner attributes of the source file. |
181 | pub fn top_level_attrs(&self) -> &Attrs { | 184 | pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs { |
182 | self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) | 185 | self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate) |
183 | } | 186 | } |
184 | 187 | ||
185 | pub fn attrs(&self, of: AttrOwner) -> &Attrs { | 188 | pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs { |
186 | self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) | 189 | self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) |
190 | } | ||
191 | |||
192 | pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs { | ||
193 | self.raw_attrs(of).clone().filter(db, krate) | ||
187 | } | 194 | } |
188 | 195 | ||
189 | /// Returns the lowered inner items that `ast` corresponds to. | 196 | /// Returns the lowered inner items that `ast` corresponds to. |
@@ -283,6 +290,7 @@ struct ItemTreeData { | |||
283 | mods: Arena<Mod>, | 290 | mods: Arena<Mod>, |
284 | macro_calls: Arena<MacroCall>, | 291 | macro_calls: Arena<MacroCall>, |
285 | macro_rules: Arena<MacroRules>, | 292 | macro_rules: Arena<MacroRules>, |
293 | macro_defs: Arena<MacroDef>, | ||
286 | exprs: Arena<Expr>, | 294 | exprs: Arena<Expr>, |
287 | 295 | ||
288 | vis: ItemVisibilities, | 296 | vis: ItemVisibilities, |
@@ -431,6 +439,7 @@ mod_items! { | |||
431 | Mod in mods -> ast::Module, | 439 | Mod in mods -> ast::Module, |
432 | MacroCall in macro_calls -> ast::MacroCall, | 440 | MacroCall in macro_calls -> ast::MacroCall, |
433 | MacroRules in macro_rules -> ast::MacroRules, | 441 | MacroRules in macro_rules -> ast::MacroRules, |
442 | MacroDef in macro_defs -> ast::MacroDef, | ||
434 | } | 443 | } |
435 | 444 | ||
436 | macro_rules! impl_index { | 445 | macro_rules! impl_index { |
@@ -640,17 +649,19 @@ pub struct MacroCall { | |||
640 | 649 | ||
641 | #[derive(Debug, Clone, Eq, PartialEq)] | 650 | #[derive(Debug, Clone, Eq, PartialEq)] |
642 | pub struct MacroRules { | 651 | pub struct MacroRules { |
643 | /// For `macro_rules!` declarations, this is the name of the declared macro. | 652 | /// The name of the declared macro. |
644 | pub name: Name, | 653 | pub name: Name, |
645 | /// Has `#[macro_export]`. | ||
646 | pub is_export: bool, | ||
647 | /// Has `#[macro_export(local_inner_macros)]`. | ||
648 | pub is_local_inner: bool, | ||
649 | /// Has `#[rustc_builtin_macro]`. | ||
650 | pub is_builtin: bool, | ||
651 | pub ast_id: FileAstId<ast::MacroRules>, | 654 | pub ast_id: FileAstId<ast::MacroRules>, |
652 | } | 655 | } |
653 | 656 | ||
657 | /// "Macros 2.0" macro definition. | ||
658 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
659 | pub struct MacroDef { | ||
660 | pub name: Name, | ||
661 | pub visibility: RawVisibilityId, | ||
662 | pub ast_id: FileAstId<ast::MacroDef>, | ||
663 | } | ||
664 | |||
654 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array | 665 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array |
655 | // lengths, but we don't do much with them yet. | 666 | // lengths, but we don't do much with them yet. |
656 | #[derive(Debug, Clone, Eq, PartialEq)] | 667 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -680,7 +691,8 @@ impl ModItem { | |||
680 | | ModItem::Trait(_) | 691 | | ModItem::Trait(_) |
681 | | ModItem::Impl(_) | 692 | | ModItem::Impl(_) |
682 | | ModItem::Mod(_) | 693 | | ModItem::Mod(_) |
683 | | ModItem::MacroRules(_) => None, | 694 | | ModItem::MacroRules(_) |
695 | | ModItem::MacroDef(_) => None, | ||
684 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), | 696 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), |
685 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), | 697 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), |
686 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), | 698 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), |
@@ -708,6 +720,7 @@ impl ModItem { | |||
708 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), | 720 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), |
709 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), | 721 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), |
710 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), | 722 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), |
723 | ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(), | ||
711 | } | 724 | } |
712 | } | 725 | } |
713 | } | 726 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index b39d7fb7a..c8f090c22 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -10,7 +10,6 @@ use syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | attr::Attrs, | ||
14 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
15 | type_ref::LifetimeRef, | 14 | type_ref::LifetimeRef, |
16 | }; | 15 | }; |
@@ -101,10 +100,11 @@ impl Ctx { | |||
101 | | ast::Item::ExternCrate(_) | 100 | | ast::Item::ExternCrate(_) |
102 | | ast::Item::Use(_) | 101 | | ast::Item::Use(_) |
103 | | ast::Item::MacroCall(_) | 102 | | ast::Item::MacroCall(_) |
104 | | ast::Item::MacroRules(_) => {} | 103 | | ast::Item::MacroRules(_) |
104 | | ast::Item::MacroDef(_) => {} | ||
105 | }; | 105 | }; |
106 | 106 | ||
107 | let attrs = Attrs::new(item, &self.hygiene); | 107 | let attrs = RawAttrs::new(item, &self.hygiene); |
108 | let items = match item { | 108 | let items = match item { |
109 | ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), | 109 | ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), |
110 | ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), | 110 | ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), |
@@ -122,6 +122,7 @@ impl Ctx { | |||
122 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), | 122 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), |
123 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), | 123 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
124 | ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), | 124 | ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), |
125 | ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into), | ||
125 | ast::Item::ExternBlock(ast) => { | 126 | ast::Item::ExternBlock(ast) => { |
126 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | 127 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) |
127 | } | 128 | } |
@@ -136,7 +137,7 @@ impl Ctx { | |||
136 | items | 137 | items |
137 | } | 138 | } |
138 | 139 | ||
139 | fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) { | 140 | fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) { |
140 | match self.tree.attrs.entry(item) { | 141 | match self.tree.attrs.entry(item) { |
141 | Entry::Occupied(mut entry) => { | 142 | Entry::Occupied(mut entry) => { |
142 | *entry.get_mut() = entry.get().merge(attrs); | 143 | *entry.get_mut() = entry.get().merge(attrs); |
@@ -203,7 +204,7 @@ impl Ctx { | |||
203 | for field in fields.fields() { | 204 | for field in fields.fields() { |
204 | if let Some(data) = self.lower_record_field(&field) { | 205 | if let Some(data) = self.lower_record_field(&field) { |
205 | let idx = self.data().fields.alloc(data); | 206 | let idx = self.data().fields.alloc(data); |
206 | self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); | 207 | self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene)); |
207 | } | 208 | } |
208 | } | 209 | } |
209 | let end = self.next_field_idx(); | 210 | let end = self.next_field_idx(); |
@@ -223,7 +224,7 @@ impl Ctx { | |||
223 | for (i, field) in fields.fields().enumerate() { | 224 | for (i, field) in fields.fields().enumerate() { |
224 | let data = self.lower_tuple_field(i, &field); | 225 | let data = self.lower_tuple_field(i, &field); |
225 | let idx = self.data().fields.alloc(data); | 226 | let idx = self.data().fields.alloc(data); |
226 | self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); | 227 | self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene)); |
227 | } | 228 | } |
228 | let end = self.next_field_idx(); | 229 | let end = self.next_field_idx(); |
229 | IdRange::new(start..end) | 230 | IdRange::new(start..end) |
@@ -268,7 +269,7 @@ impl Ctx { | |||
268 | for variant in variants.variants() { | 269 | for variant in variants.variants() { |
269 | if let Some(data) = self.lower_variant(&variant) { | 270 | if let Some(data) = self.lower_variant(&variant) { |
270 | let idx = self.data().variants.alloc(data); | 271 | let idx = self.data().variants.alloc(data); |
271 | self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene)); | 272 | self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene)); |
272 | } | 273 | } |
273 | } | 274 | } |
274 | let end = self.next_variant_idx(); | 275 | let end = self.next_variant_idx(); |
@@ -298,12 +299,12 @@ impl Ctx { | |||
298 | ast::SelfParamKind::Owned => self_type, | 299 | ast::SelfParamKind::Owned => self_type, |
299 | ast::SelfParamKind::Ref => TypeRef::Reference( | 300 | ast::SelfParamKind::Ref => TypeRef::Reference( |
300 | Box::new(self_type), | 301 | Box::new(self_type), |
301 | self_param.lifetime_token().map(LifetimeRef::from_token), | 302 | self_param.lifetime().as_ref().map(LifetimeRef::new), |
302 | Mutability::Shared, | 303 | Mutability::Shared, |
303 | ), | 304 | ), |
304 | ast::SelfParamKind::MutRef => TypeRef::Reference( | 305 | ast::SelfParamKind::MutRef => TypeRef::Reference( |
305 | Box::new(self_type), | 306 | Box::new(self_type), |
306 | self_param.lifetime_token().map(LifetimeRef::from_token), | 307 | self_param.lifetime().as_ref().map(LifetimeRef::new), |
307 | Mutability::Mut, | 308 | Mutability::Mut, |
308 | ), | 309 | ), |
309 | } | 310 | } |
@@ -436,7 +437,7 @@ impl Ctx { | |||
436 | self.with_inherited_visibility(visibility, |this| { | 437 | self.with_inherited_visibility(visibility, |this| { |
437 | list.assoc_items() | 438 | list.assoc_items() |
438 | .filter_map(|item| { | 439 | .filter_map(|item| { |
439 | let attrs = Attrs::new(&item, &this.hygiene); | 440 | let attrs = RawAttrs::new(&item, &this.hygiene); |
440 | this.collect_inner_items(item.syntax()); | 441 | this.collect_inner_items(item.syntax()); |
441 | this.lower_assoc_item(&item).map(|item| { | 442 | this.lower_assoc_item(&item).map(|item| { |
442 | this.add_attrs(ModItem::from(item).into(), attrs); | 443 | this.add_attrs(ModItem::from(item).into(), attrs); |
@@ -473,7 +474,7 @@ impl Ctx { | |||
473 | .filter_map(|item| { | 474 | .filter_map(|item| { |
474 | self.collect_inner_items(item.syntax()); | 475 | self.collect_inner_items(item.syntax()); |
475 | let assoc = self.lower_assoc_item(&item)?; | 476 | let assoc = self.lower_assoc_item(&item)?; |
476 | let attrs = Attrs::new(&item, &self.hygiene); | 477 | let attrs = RawAttrs::new(&item, &self.hygiene); |
477 | self.add_attrs(ModItem::from(assoc).into(), attrs); | 478 | self.add_attrs(ModItem::from(assoc).into(), attrs); |
478 | Some(assoc) | 479 | Some(assoc) |
479 | }) | 480 | }) |
@@ -537,28 +538,20 @@ impl Ctx { | |||
537 | 538 | ||
538 | fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> { | 539 | fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> { |
539 | let name = m.name().map(|it| it.as_name())?; | 540 | let name = m.name().map(|it| it.as_name())?; |
540 | let attrs = Attrs::new(m, &self.hygiene); | ||
541 | |||
542 | let ast_id = self.source_ast_id_map.ast_id(m); | 541 | let ast_id = self.source_ast_id_map.ast_id(m); |
543 | 542 | ||
544 | // FIXME: cfg_attr | 543 | let res = MacroRules { name, ast_id }; |
545 | let export_attr = attrs.by_key("macro_export"); | 544 | Some(id(self.data().macro_rules.alloc(res))) |
545 | } | ||
546 | 546 | ||
547 | let is_export = export_attr.exists(); | 547 | fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> { |
548 | let is_local_inner = if is_export { | 548 | let name = m.name().map(|it| it.as_name())?; |
549 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
550 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
551 | ident.text.contains("local_inner_macros") | ||
552 | } | ||
553 | _ => false, | ||
554 | }) | ||
555 | } else { | ||
556 | false | ||
557 | }; | ||
558 | 549 | ||
559 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | 550 | let ast_id = self.source_ast_id_map.ast_id(m); |
560 | let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id }; | 551 | let visibility = self.lower_visibility(m); |
561 | Some(id(self.data().macro_rules.alloc(res))) | 552 | |
553 | let res = MacroDef { name, ast_id, visibility }; | ||
554 | Some(id(self.data().macro_defs.alloc(res))) | ||
562 | } | 555 | } |
563 | 556 | ||
564 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { | 557 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { |
@@ -566,7 +559,7 @@ impl Ctx { | |||
566 | list.extern_items() | 559 | list.extern_items() |
567 | .filter_map(|item| { | 560 | .filter_map(|item| { |
568 | self.collect_inner_items(item.syntax()); | 561 | self.collect_inner_items(item.syntax()); |
569 | let attrs = Attrs::new(&item, &self.hygiene); | 562 | let attrs = RawAttrs::new(&item, &self.hygiene); |
570 | let id: ModItem = match item { | 563 | let id: ModItem = match item { |
571 | ast::ExternItem::Fn(ast) => { | 564 | ast::ExternItem::Fn(ast) => { |
572 | let func_id = self.lower_function(&ast)?; | 565 | let func_id = self.lower_function(&ast)?; |
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 063eadccb..30188b740 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -8,8 +8,8 @@ use rustc_hash::FxHashMap; | |||
8 | use syntax::SmolStr; | 8 | use syntax::SmolStr; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId, | 11 | db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, StaticId, |
12 | StaticId, StructId, TraitId, | 12 | StructId, TraitId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 15 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -84,27 +84,34 @@ impl LangItems { | |||
84 | 84 | ||
85 | let crate_def_map = db.crate_def_map(krate); | 85 | let crate_def_map = db.crate_def_map(krate); |
86 | 86 | ||
87 | crate_def_map | 87 | for (_, module_data) in crate_def_map.modules.iter() { |
88 | .modules | 88 | for impl_def in module_data.scope.impls() { |
89 | .iter() | 89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) |
90 | .filter_map(|(local_id, _)| db.module_lang_items(ModuleId { krate, local_id })) | 90 | } |
91 | .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v)))); | ||
92 | |||
93 | Arc::new(lang_items) | ||
94 | } | ||
95 | 91 | ||
96 | pub(crate) fn module_lang_items_query( | 92 | for def in module_data.scope.declarations() { |
97 | db: &dyn DefDatabase, | 93 | match def { |
98 | module: ModuleId, | 94 | ModuleDefId::TraitId(trait_) => { |
99 | ) -> Option<Arc<LangItems>> { | 95 | lang_items.collect_lang_item(db, trait_, LangItemTarget::TraitId) |
100 | let _p = profile::span("module_lang_items_query"); | 96 | } |
101 | let mut lang_items = LangItems::default(); | 97 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
102 | lang_items.collect_lang_items(db, module); | 98 | lang_items.collect_lang_item(db, e, LangItemTarget::EnumId) |
103 | if lang_items.items.is_empty() { | 99 | } |
104 | None | 100 | ModuleDefId::AdtId(AdtId::StructId(s)) => { |
105 | } else { | 101 | lang_items.collect_lang_item(db, s, LangItemTarget::StructId) |
106 | Some(Arc::new(lang_items)) | 102 | } |
103 | ModuleDefId::FunctionId(f) => { | ||
104 | lang_items.collect_lang_item(db, f, LangItemTarget::FunctionId) | ||
105 | } | ||
106 | ModuleDefId::StaticId(s) => { | ||
107 | lang_items.collect_lang_item(db, s, LangItemTarget::StaticId) | ||
108 | } | ||
109 | _ => {} | ||
110 | } | ||
111 | } | ||
107 | } | 112 | } |
113 | |||
114 | Arc::new(lang_items) | ||
108 | } | 115 | } |
109 | 116 | ||
110 | /// Salsa query. Look for a lang item, starting from the specified crate and recursively | 117 | /// Salsa query. Look for a lang item, starting from the specified crate and recursively |
@@ -126,34 +133,6 @@ impl LangItems { | |||
126 | .find_map(|dep| db.lang_item(dep.crate_id, item.clone())) | 133 | .find_map(|dep| db.lang_item(dep.crate_id, item.clone())) |
127 | } | 134 | } |
128 | 135 | ||
129 | fn collect_lang_items(&mut self, db: &dyn DefDatabase, module: ModuleId) { | ||
130 | // Look for impl targets | ||
131 | let def_map = db.crate_def_map(module.krate); | ||
132 | let module_data = &def_map[module.local_id]; | ||
133 | for impl_def in module_data.scope.impls() { | ||
134 | self.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) | ||
135 | } | ||
136 | |||
137 | for def in module_data.scope.declarations() { | ||
138 | match def { | ||
139 | ModuleDefId::TraitId(trait_) => { | ||
140 | self.collect_lang_item(db, trait_, LangItemTarget::TraitId) | ||
141 | } | ||
142 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | ||
143 | self.collect_lang_item(db, e, LangItemTarget::EnumId) | ||
144 | } | ||
145 | ModuleDefId::AdtId(AdtId::StructId(s)) => { | ||
146 | self.collect_lang_item(db, s, LangItemTarget::StructId) | ||
147 | } | ||
148 | ModuleDefId::FunctionId(f) => { | ||
149 | self.collect_lang_item(db, f, LangItemTarget::FunctionId) | ||
150 | } | ||
151 | ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId), | ||
152 | _ => {} | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | |||
157 | fn collect_lang_item<T>( | 136 | fn collect_lang_item<T>( |
158 | &mut self, | 137 | &mut self, |
159 | db: &dyn DefDatabase, | 138 | db: &dyn DefDatabase, |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 7e2199a9c..ba09a9126 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -425,6 +425,16 @@ impl HasModule for AdtId { | |||
425 | } | 425 | } |
426 | } | 426 | } |
427 | 427 | ||
428 | impl HasModule for VariantId { | ||
429 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
430 | match self { | ||
431 | VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), | ||
432 | VariantId::StructId(it) => it.lookup(db).container.module(db), | ||
433 | VariantId::UnionId(it) => it.lookup(db).container.module(db), | ||
434 | } | ||
435 | } | ||
436 | } | ||
437 | |||
428 | impl HasModule for DefWithBodyId { | 438 | impl HasModule for DefWithBodyId { |
429 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | 439 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { |
430 | match self { | 440 | match self { |
@@ -465,6 +475,26 @@ impl HasModule for StaticLoc { | |||
465 | } | 475 | } |
466 | } | 476 | } |
467 | 477 | ||
478 | impl AttrDefId { | ||
479 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { | ||
480 | match self { | ||
481 | AttrDefId::ModuleId(it) => it.krate, | ||
482 | AttrDefId::FieldId(it) => it.parent.module(db).krate, | ||
483 | AttrDefId::AdtId(it) => it.module(db).krate, | ||
484 | AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, | ||
485 | AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate, | ||
486 | AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, | ||
487 | AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, | ||
488 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, | ||
489 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, | ||
490 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, | ||
491 | // FIXME: `MacroDefId` should store the defining module, then this can implement | ||
492 | // `HasModule` | ||
493 | AttrDefId::MacroDefId(it) => it.krate, | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | |||
468 | /// A helper trait for converting to MacroCallId | 498 | /// A helper trait for converting to MacroCallId |
469 | pub trait AsMacroCall { | 499 | pub trait AsMacroCall { |
470 | fn as_call_id( | 500 | fn as_call_id( |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 85cc342c4..b114a6fe4 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -26,7 +26,8 @@ use crate::{ | |||
26 | db::DefDatabase, | 26 | db::DefDatabase, |
27 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
28 | item_tree::{ | 28 | item_tree::{ |
29 | self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, |
30 | StructDefKind, | ||
30 | }, | 31 | }, |
31 | nameres::{ | 32 | nameres::{ |
32 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 33 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
@@ -220,17 +221,20 @@ impl DefCollector<'_> { | |||
220 | let item_tree = self.db.item_tree(file_id.into()); | 221 | let item_tree = self.db.item_tree(file_id.into()); |
221 | let module_id = self.def_map.root; | 222 | let module_id = self.def_map.root; |
222 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | 223 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; |
223 | let mut root_collector = ModCollector { | 224 | if item_tree |
224 | def_collector: &mut *self, | 225 | .top_level_attrs(self.db, self.def_map.krate) |
225 | macro_depth: 0, | 226 | .cfg() |
226 | module_id, | 227 | .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) |
227 | file_id: file_id.into(), | ||
228 | item_tree: &item_tree, | ||
229 | mod_dir: ModDir::root(), | ||
230 | }; | ||
231 | if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg)) | ||
232 | { | 228 | { |
233 | root_collector.collect(item_tree.top_level_items()); | 229 | ModCollector { |
230 | def_collector: &mut *self, | ||
231 | macro_depth: 0, | ||
232 | module_id, | ||
233 | file_id: file_id.into(), | ||
234 | item_tree: &item_tree, | ||
235 | mod_dir: ModDir::root(), | ||
236 | } | ||
237 | .collect(item_tree.top_level_items()); | ||
234 | } | 238 | } |
235 | 239 | ||
236 | // main name resolution fixed-point loop. | 240 | // main name resolution fixed-point loop. |
@@ -309,13 +313,13 @@ impl DefCollector<'_> { | |||
309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { | 313 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { |
310 | Some((_, expander)) => MacroDefId { | 314 | Some((_, expander)) => MacroDefId { |
311 | ast_id: None, | 315 | ast_id: None, |
312 | krate: Some(self.def_map.krate), | 316 | krate: self.def_map.krate, |
313 | kind: MacroDefKind::ProcMacro(*expander), | 317 | kind: MacroDefKind::ProcMacro(*expander), |
314 | local_inner: false, | 318 | local_inner: false, |
315 | }, | 319 | }, |
316 | None => MacroDefId { | 320 | None => MacroDefId { |
317 | ast_id: None, | 321 | ast_id: None, |
318 | krate: Some(self.def_map.krate), | 322 | krate: self.def_map.krate, |
319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), | 323 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), |
320 | local_inner: false, | 324 | local_inner: false, |
321 | }, | 325 | }, |
@@ -784,14 +788,6 @@ impl DefCollector<'_> { | |||
784 | directive: &DeriveDirective, | 788 | directive: &DeriveDirective, |
785 | path: &ModPath, | 789 | path: &ModPath, |
786 | ) -> Option<MacroDefId> { | 790 | ) -> Option<MacroDefId> { |
787 | if let Some(name) = path.as_ident() { | ||
788 | // FIXME this should actually be handled with the normal name | ||
789 | // resolution; the std lib defines built-in stubs for the derives, | ||
790 | // but these are new-style `macro`s, which we don't support yet | ||
791 | if let Some(def_id) = find_builtin_derive(name) { | ||
792 | return Some(def_id); | ||
793 | } | ||
794 | } | ||
795 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 791 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 792 | self.db, |
797 | ResolveMode::Other, | 793 | ResolveMode::Other, |
@@ -912,6 +908,8 @@ struct ModCollector<'a, 'b> { | |||
912 | 908 | ||
913 | impl ModCollector<'_, '_> { | 909 | impl ModCollector<'_, '_> { |
914 | fn collect(&mut self, items: &[ModItem]) { | 910 | fn collect(&mut self, items: &[ModItem]) { |
911 | let krate = self.def_collector.def_map.krate; | ||
912 | |||
915 | // Note: don't assert that inserted value is fresh: it's simply not true | 913 | // Note: don't assert that inserted value is fresh: it's simply not true |
916 | // for macros. | 914 | // for macros. |
917 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); | 915 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); |
@@ -928,7 +926,7 @@ impl ModCollector<'_, '_> { | |||
928 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 926 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
929 | // any other items. | 927 | // any other items. |
930 | for item in items { | 928 | for item in items { |
931 | let attrs = self.item_tree.attrs((*item).into()); | 929 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into()); |
932 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { | 930 | if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { |
933 | if let ModItem::ExternCrate(id) = item { | 931 | if let ModItem::ExternCrate(id) = item { |
934 | let import = self.item_tree[*id].clone(); | 932 | let import = self.item_tree[*id].clone(); |
@@ -940,7 +938,7 @@ impl ModCollector<'_, '_> { | |||
940 | } | 938 | } |
941 | 939 | ||
942 | for &item in items { | 940 | for &item in items { |
943 | let attrs = self.item_tree.attrs(item.into()); | 941 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into()); |
944 | if let Some(cfg) = attrs.cfg() { | 942 | if let Some(cfg) = attrs.cfg() { |
945 | if !self.is_cfg_enabled(&cfg) { | 943 | if !self.is_cfg_enabled(&cfg) { |
946 | self.emit_unconfigured_diagnostic(item, &cfg); | 944 | self.emit_unconfigured_diagnostic(item, &cfg); |
@@ -953,7 +951,7 @@ impl ModCollector<'_, '_> { | |||
953 | 951 | ||
954 | let mut def = None; | 952 | let mut def = None; |
955 | match item { | 953 | match item { |
956 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), | 954 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs), |
957 | ModItem::Import(import_id) => { | 955 | ModItem::Import(import_id) => { |
958 | self.def_collector.unresolved_imports.push(ImportDirective { | 956 | self.def_collector.unresolved_imports.push(ImportDirective { |
959 | module_id: self.module_id, | 957 | module_id: self.module_id, |
@@ -975,7 +973,41 @@ impl ModCollector<'_, '_> { | |||
975 | }) | 973 | }) |
976 | } | 974 | } |
977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 975 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), | 976 | ModItem::MacroRules(id) => self.collect_macro_rules(id), |
977 | ModItem::MacroDef(id) => { | ||
978 | let mac = &self.item_tree[id]; | ||
979 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
980 | |||
981 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
982 | // to define builtin macros, so we support at least that part. | ||
983 | let attrs = self.item_tree.attrs( | ||
984 | self.def_collector.db, | ||
985 | krate, | ||
986 | ModItem::from(id).into(), | ||
987 | ); | ||
988 | if attrs.by_key("rustc_builtin_macro").exists() { | ||
989 | let krate = self.def_collector.def_map.krate; | ||
990 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
991 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
992 | if let Some(macro_id) = macro_id { | ||
993 | let vis = self | ||
994 | .def_collector | ||
995 | .def_map | ||
996 | .resolve_visibility( | ||
997 | self.def_collector.db, | ||
998 | self.module_id, | ||
999 | &self.item_tree[mac.visibility], | ||
1000 | ) | ||
1001 | .unwrap_or(Visibility::Public); | ||
1002 | self.def_collector.update( | ||
1003 | self.module_id, | ||
1004 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
1005 | vis, | ||
1006 | ImportType::Named, | ||
1007 | ); | ||
1008 | } | ||
1009 | } | ||
1010 | } | ||
979 | ModItem::Impl(imp) => { | 1011 | ModItem::Impl(imp) => { |
980 | let module = ModuleId { | 1012 | let module = ModuleId { |
981 | krate: self.def_collector.def_map.krate, | 1013 | krate: self.def_collector.def_map.krate, |
@@ -989,7 +1021,7 @@ impl ModCollector<'_, '_> { | |||
989 | ModItem::Function(id) => { | 1021 | ModItem::Function(id) => { |
990 | let func = &self.item_tree[id]; | 1022 | let func = &self.item_tree[id]; |
991 | 1023 | ||
992 | self.collect_proc_macro_def(&func.name, attrs); | 1024 | self.collect_proc_macro_def(&func.name, &attrs); |
993 | 1025 | ||
994 | def = Some(DefData { | 1026 | def = Some(DefData { |
995 | id: FunctionLoc { | 1027 | id: FunctionLoc { |
@@ -1009,7 +1041,7 @@ impl ModCollector<'_, '_> { | |||
1009 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1041 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1010 | // in which case we don't add the invocation, just a single attribute | 1042 | // in which case we don't add the invocation, just a single attribute |
1011 | // macro invocation | 1043 | // macro invocation |
1012 | self.collect_derives(attrs, it.ast_id.upcast()); | 1044 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1013 | 1045 | ||
1014 | def = Some(DefData { | 1046 | def = Some(DefData { |
1015 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1047 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1026,7 +1058,7 @@ impl ModCollector<'_, '_> { | |||
1026 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1058 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1027 | // in which case we don't add the invocation, just a single attribute | 1059 | // in which case we don't add the invocation, just a single attribute |
1028 | // macro invocation | 1060 | // macro invocation |
1029 | self.collect_derives(attrs, it.ast_id.upcast()); | 1061 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1030 | 1062 | ||
1031 | def = Some(DefData { | 1063 | def = Some(DefData { |
1032 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1064 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1043,7 +1075,7 @@ impl ModCollector<'_, '_> { | |||
1043 | // FIXME: check attrs to see if this is an attribute macro invocation; | 1075 | // FIXME: check attrs to see if this is an attribute macro invocation; |
1044 | // in which case we don't add the invocation, just a single attribute | 1076 | // in which case we don't add the invocation, just a single attribute |
1045 | // macro invocation | 1077 | // macro invocation |
1046 | self.collect_derives(attrs, it.ast_id.upcast()); | 1078 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1047 | 1079 | ||
1048 | def = Some(DefData { | 1080 | def = Some(DefData { |
1049 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1081 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } |
@@ -1279,18 +1311,35 @@ impl ModCollector<'_, '_> { | |||
1279 | self.def_collector.resolve_proc_macro(¯o_name); | 1311 | self.def_collector.resolve_proc_macro(¯o_name); |
1280 | } | 1312 | } |
1281 | 1313 | ||
1282 | fn collect_macro_rules(&mut self, mac: &MacroRules) { | 1314 | fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { |
1283 | let ast_id = InFile::new(self.file_id, mac.ast_id); | 1315 | let krate = self.def_collector.def_map.krate; |
1316 | let mac = &self.item_tree[id]; | ||
1317 | let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); | ||
1318 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
1319 | |||
1320 | let export_attr = attrs.by_key("macro_export"); | ||
1321 | |||
1322 | let is_export = export_attr.exists(); | ||
1323 | let is_local_inner = if is_export { | ||
1324 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
1325 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
1326 | ident.text.contains("local_inner_macros") | ||
1327 | } | ||
1328 | _ => false, | ||
1329 | }) | ||
1330 | } else { | ||
1331 | false | ||
1332 | }; | ||
1284 | 1333 | ||
1285 | // Case 1: builtin macros | 1334 | // Case 1: builtin macros |
1286 | if mac.is_builtin { | 1335 | if attrs.by_key("rustc_builtin_macro").exists() { |
1287 | let krate = self.def_collector.def_map.krate; | 1336 | let krate = self.def_collector.def_map.krate; |
1288 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1337 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { |
1289 | self.def_collector.define_macro( | 1338 | self.def_collector.define_macro( |
1290 | self.module_id, | 1339 | self.module_id, |
1291 | mac.name.clone(), | 1340 | mac.name.clone(), |
1292 | macro_id, | 1341 | macro_id, |
1293 | mac.is_export, | 1342 | is_export, |
1294 | ); | 1343 | ); |
1295 | return; | 1344 | return; |
1296 | } | 1345 | } |
@@ -1299,11 +1348,11 @@ impl ModCollector<'_, '_> { | |||
1299 | // Case 2: normal `macro_rules!` macro | 1348 | // Case 2: normal `macro_rules!` macro |
1300 | let macro_id = MacroDefId { | 1349 | let macro_id = MacroDefId { |
1301 | ast_id: Some(ast_id), | 1350 | ast_id: Some(ast_id), |
1302 | krate: Some(self.def_collector.def_map.krate), | 1351 | krate: self.def_collector.def_map.krate, |
1303 | kind: MacroDefKind::Declarative, | 1352 | kind: MacroDefKind::Declarative, |
1304 | local_inner: mac.is_local_inner, | 1353 | local_inner: is_local_inner, |
1305 | }; | 1354 | }; |
1306 | self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export); | 1355 | self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); |
1307 | } | 1356 | } |
1308 | 1357 | ||
1309 | fn collect_macro_call(&mut self, mac: &MacroCall) { | 1358 | fn collect_macro_call(&mut self, mac: &MacroCall) { |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 305fca0f9..6fe2ee78a 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -633,15 +633,44 @@ pub struct bar; | |||
633 | fn expand_derive() { | 633 | fn expand_derive() { |
634 | let map = compute_crate_def_map( | 634 | let map = compute_crate_def_map( |
635 | " | 635 | " |
636 | //- /main.rs | 636 | //- /main.rs crate:main deps:core |
637 | use core::*; | ||
638 | |||
637 | #[derive(Copy, Clone)] | 639 | #[derive(Copy, Clone)] |
638 | struct Foo; | 640 | struct Foo; |
641 | |||
642 | //- /core.rs crate:core | ||
643 | #[rustc_builtin_macro] | ||
644 | pub macro Copy {} | ||
645 | |||
646 | #[rustc_builtin_macro] | ||
647 | pub macro Clone {} | ||
639 | ", | 648 | ", |
640 | ); | 649 | ); |
641 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); | 650 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); |
642 | } | 651 | } |
643 | 652 | ||
644 | #[test] | 653 | #[test] |
654 | fn resolve_builtin_derive() { | ||
655 | check( | ||
656 | r#" | ||
657 | //- /main.rs crate:main deps:core | ||
658 | use core::*; | ||
659 | |||
660 | //- /core.rs crate:core | ||
661 | #[rustc_builtin_macro] | ||
662 | pub macro Clone {} | ||
663 | |||
664 | pub trait Clone {} | ||
665 | "#, | ||
666 | expect![[r#" | ||
667 | crate | ||
668 | Clone: t m | ||
669 | "#]], | ||
670 | ); | ||
671 | } | ||
672 | |||
673 | #[test] | ||
645 | fn macro_expansion_overflow() { | 674 | fn macro_expansion_overflow() { |
646 | mark::check!(macro_expansion_overflow); | 675 | mark::check!(macro_expansion_overflow); |
647 | check( | 676 | check( |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 609925012..8a01e6eea 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -169,8 +169,8 @@ pub(super) fn lower_generic_args( | |||
169 | } | 169 | } |
170 | } | 170 | } |
171 | ast::GenericArg::LifetimeArg(lifetime_arg) => { | 171 | ast::GenericArg::LifetimeArg(lifetime_arg) => { |
172 | if let Some(lifetime) = lifetime_arg.lifetime_token() { | 172 | if let Some(lifetime) = lifetime_arg.lifetime() { |
173 | let lifetime_ref = LifetimeRef::from_token(lifetime); | 173 | let lifetime_ref = LifetimeRef::new(&lifetime); |
174 | args.push(GenericArg::Lifetime(lifetime_ref)) | 174 | args.push(GenericArg::Lifetime(lifetime_ref)) |
175 | } | 175 | } |
176 | } | 176 | } |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 347ceabb9..ae93d0d10 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | use hir_expand::name::Name; | 3 | use hir_expand::name::Name; |
4 | use syntax::{ast, SyntaxToken}; | 4 | use syntax::ast; |
5 | 5 | ||
6 | use crate::{body::LowerCtx, path::Path}; | 6 | use crate::{body::LowerCtx, path::Path}; |
7 | 7 | ||
@@ -80,8 +80,8 @@ impl LifetimeRef { | |||
80 | LifetimeRef { name } | 80 | LifetimeRef { name } |
81 | } | 81 | } |
82 | 82 | ||
83 | pub(crate) fn from_token(token: SyntaxToken) -> Self { | 83 | pub(crate) fn new(lifetime: &ast::Lifetime) -> Self { |
84 | LifetimeRef { name: Name::new_lifetime(&token) } | 84 | LifetimeRef { name: Name::new_lifetime(lifetime) } |
85 | } | 85 | } |
86 | 86 | ||
87 | pub fn missing() -> LifetimeRef { | 87 | pub fn missing() -> LifetimeRef { |
@@ -127,7 +127,7 @@ impl TypeRef { | |||
127 | } | 127 | } |
128 | ast::Type::RefType(inner) => { | 128 | ast::Type::RefType(inner) => { |
129 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 129 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
130 | let lifetime = inner.lifetime_token().map(|t| LifetimeRef::from_token(t)); | 130 | let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<)); |
131 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 131 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
132 | TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) | 132 | TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) |
133 | } | 133 | } |
@@ -259,7 +259,7 @@ impl TypeBound { | |||
259 | } | 259 | } |
260 | ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType | 260 | ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType |
261 | ast::TypeBoundKind::Lifetime(lifetime) => { | 261 | ast::TypeBoundKind::Lifetime(lifetime) => { |
262 | TypeBound::Lifetime(LifetimeRef::from_token(lifetime)) | 262 | TypeBound::Lifetime(LifetimeRef::new(&lifetime)) |
263 | } | 263 | } |
264 | } | 264 | } |
265 | } | 265 | } |
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index 988a60d56..ad378762a 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -8,7 +8,7 @@ use syntax::{ | |||
8 | match_ast, | 8 | match_ast, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind}; | 11 | use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind}; |
12 | 12 | ||
13 | macro_rules! register_builtin { | 13 | macro_rules! register_builtin { |
14 | ( $($trait:ident => $expand:ident),* ) => { | 14 | ( $($trait:ident => $expand:ident),* ) => { |
@@ -29,16 +29,15 @@ macro_rules! register_builtin { | |||
29 | }; | 29 | }; |
30 | expander(db, id, tt) | 30 | expander(db, id, tt) |
31 | } | 31 | } |
32 | } | ||
33 | |||
34 | pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> { | ||
35 | let kind = match ident { | ||
36 | $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )* | ||
37 | _ => return None, | ||
38 | }; | ||
39 | 32 | ||
40 | Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false }) | 33 | fn find_by_name(name: &name::Name) -> Option<Self> { |
34 | match name { | ||
35 | $( id if id == &name::name![$trait] => Some(BuiltinDeriveExpander::$trait), )* | ||
36 | _ => None, | ||
37 | } | ||
38 | } | ||
41 | } | 39 | } |
40 | |||
42 | }; | 41 | }; |
43 | } | 42 | } |
44 | 43 | ||
@@ -54,6 +53,20 @@ register_builtin! { | |||
54 | PartialEq => partial_eq_expand | 53 | PartialEq => partial_eq_expand |
55 | } | 54 | } |
56 | 55 | ||
56 | pub fn find_builtin_derive( | ||
57 | ident: &name::Name, | ||
58 | krate: CrateId, | ||
59 | ast_id: AstId<ast::Macro>, | ||
60 | ) -> Option<MacroDefId> { | ||
61 | let expander = BuiltinDeriveExpander::find_by_name(ident)?; | ||
62 | Some(MacroDefId { | ||
63 | krate, | ||
64 | ast_id: Some(ast_id), | ||
65 | kind: MacroDefKind::BuiltInDerive(expander), | ||
66 | local_inner: false, | ||
67 | }) | ||
68 | } | ||
69 | |||
57 | struct BasicAdtInfo { | 70 | struct BasicAdtInfo { |
58 | name: tt::Ident, | 71 | name: tt::Ident, |
59 | type_params: usize, | 72 | type_params: usize, |
@@ -261,7 +274,7 @@ mod tests { | |||
261 | use super::*; | 274 | use super::*; |
262 | 275 | ||
263 | fn expand_builtin_derive(s: &str, name: Name) -> String { | 276 | fn expand_builtin_derive(s: &str, name: Name) -> String { |
264 | let def = find_builtin_derive(&name).unwrap(); | 277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
265 | let fixture = format!( | 278 | let fixture = format!( |
266 | r#"//- /main.rs crate:main deps:core | 279 | r#"//- /main.rs crate:main deps:core |
267 | <|> | 280 | <|> |
@@ -283,7 +296,12 @@ mod tests { | |||
283 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); | 296 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); |
284 | 297 | ||
285 | let loc = MacroCallLoc { | 298 | let loc = MacroCallLoc { |
286 | def, | 299 | def: MacroDefId { |
300 | krate: CrateId(0), | ||
301 | ast_id: None, | ||
302 | kind: MacroDefKind::BuiltInDerive(expander), | ||
303 | local_inner: false, | ||
304 | }, | ||
287 | krate: CrateId(0), | 305 | krate: CrateId(0), |
288 | kind: MacroCallKind::Attr(attr_id, name.to_string()), | 306 | kind: MacroCallKind::Attr(attr_id, name.to_string()), |
289 | }; | 307 | }; |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index bd9223825..dddbbcdac 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -63,19 +63,19 @@ macro_rules! register_builtin { | |||
63 | pub fn find_builtin_macro( | 63 | pub fn find_builtin_macro( |
64 | ident: &name::Name, | 64 | ident: &name::Name, |
65 | krate: CrateId, | 65 | krate: CrateId, |
66 | ast_id: AstId<ast::MacroRules>, | 66 | ast_id: AstId<ast::Macro>, |
67 | ) -> Option<MacroDefId> { | 67 | ) -> Option<MacroDefId> { |
68 | let kind = find_by_name(ident)?; | 68 | let kind = find_by_name(ident)?; |
69 | 69 | ||
70 | match kind { | 70 | match kind { |
71 | Either::Left(kind) => Some(MacroDefId { | 71 | Either::Left(kind) => Some(MacroDefId { |
72 | krate: Some(krate), | 72 | krate, |
73 | ast_id: Some(ast_id), | 73 | ast_id: Some(ast_id), |
74 | kind: MacroDefKind::BuiltIn(kind), | 74 | kind: MacroDefKind::BuiltIn(kind), |
75 | local_inner: false, | 75 | local_inner: false, |
76 | }), | 76 | }), |
77 | Either::Right(kind) => Some(MacroDefId { | 77 | Either::Right(kind) => Some(MacroDefId { |
78 | krate: Some(krate), | 78 | krate, |
79 | ast_id: Some(ast_id), | 79 | ast_id: Some(ast_id), |
80 | kind: MacroDefKind::BuiltInEager(kind), | 80 | kind: MacroDefKind::BuiltInEager(kind), |
81 | local_inner: false, | 81 | local_inner: false, |
@@ -515,24 +515,27 @@ mod tests { | |||
515 | fn expand_builtin_macro(ra_fixture: &str) -> String { | 515 | fn expand_builtin_macro(ra_fixture: &str) -> String { |
516 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); | 516 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); |
517 | let parsed = db.parse(file_id); | 517 | let parsed = db.parse(file_id); |
518 | let macro_rules: Vec<_> = | 518 | let mut macro_rules: Vec<_> = |
519 | parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); | 519 | parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); |
520 | let macro_calls: Vec<_> = | 520 | let mut macro_calls: Vec<_> = |
521 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); | 521 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); |
522 | 522 | ||
523 | let ast_id_map = db.ast_id_map(file_id.into()); | 523 | let ast_id_map = db.ast_id_map(file_id.into()); |
524 | 524 | ||
525 | assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); | 525 | assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); |
526 | assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); | 526 | assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); |
527 | let expander = find_by_name(¯o_rules[0].name().unwrap().as_name()).unwrap(); | 527 | let macro_rules = ast::Macro::from(macro_rules.pop().unwrap()); |
528 | let macro_call = macro_calls.pop().unwrap(); | ||
529 | |||
530 | let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); | ||
528 | 531 | ||
529 | let krate = CrateId(0); | 532 | let krate = CrateId(0); |
530 | let file_id = match expander { | 533 | let file_id = match expander { |
531 | Either::Left(expander) => { | 534 | Either::Left(expander) => { |
532 | // the first one should be a macro_rules | 535 | // the first one should be a macro_rules |
533 | let def = MacroDefId { | 536 | let def = MacroDefId { |
534 | krate: Some(CrateId(0)), | 537 | krate: CrateId(0), |
535 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules[0]))), | 538 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), |
536 | kind: MacroDefKind::BuiltIn(expander), | 539 | kind: MacroDefKind::BuiltIn(expander), |
537 | local_inner: false, | 540 | local_inner: false, |
538 | }; | 541 | }; |
@@ -542,7 +545,7 @@ mod tests { | |||
542 | krate, | 545 | krate, |
543 | kind: MacroCallKind::FnLike(AstId::new( | 546 | kind: MacroCallKind::FnLike(AstId::new( |
544 | file_id.into(), | 547 | file_id.into(), |
545 | ast_id_map.ast_id(¯o_calls[0]), | 548 | ast_id_map.ast_id(¯o_call), |
546 | )), | 549 | )), |
547 | }; | 550 | }; |
548 | 551 | ||
@@ -552,13 +555,13 @@ mod tests { | |||
552 | Either::Right(expander) => { | 555 | Either::Right(expander) => { |
553 | // the first one should be a macro_rules | 556 | // the first one should be a macro_rules |
554 | let def = MacroDefId { | 557 | let def = MacroDefId { |
555 | krate: Some(krate), | 558 | krate, |
556 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules[0]))), | 559 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), |
557 | kind: MacroDefKind::BuiltInEager(expander), | 560 | kind: MacroDefKind::BuiltInEager(expander), |
558 | local_inner: false, | 561 | local_inner: false, |
559 | }; | 562 | }; |
560 | 563 | ||
561 | let args = macro_calls[0].token_tree().unwrap(); | 564 | let args = macro_call.token_tree().unwrap(); |
562 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; | 565 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; |
563 | 566 | ||
564 | let arg_id = db.intern_eager_expansion({ | 567 | let arg_id = db.intern_eager_expansion({ |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 11b5b98c8..4477d867f 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -129,7 +129,10 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | |||
129 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 129 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
130 | match id.kind { | 130 | match id.kind { |
131 | MacroDefKind::Declarative => { | 131 | MacroDefKind::Declarative => { |
132 | let macro_call = id.ast_id?.to_node(db); | 132 | let macro_call = match id.ast_id?.to_node(db) { |
133 | syntax::ast::Macro::MacroRules(mac) => mac, | ||
134 | syntax::ast::Macro::MacroDef(_) => return None, | ||
135 | }; | ||
133 | let arg = macro_call.token_tree()?; | 136 | let arg = macro_call.token_tree()?; |
134 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 137 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { |
135 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | 138 | log::warn!("fail on macro_def to token tree: {:#?}", arg); |
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 5d3fa0518..7ab0a5e52 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -29,8 +29,8 @@ impl Hygiene { | |||
29 | MacroCallId::LazyMacro(id) => { | 29 | MacroCallId::LazyMacro(id) => { |
30 | let loc = db.lookup_intern_macro(id); | 30 | let loc = db.lookup_intern_macro(id); |
31 | match loc.def.kind { | 31 | match loc.def.kind { |
32 | MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), | 32 | MacroDefKind::Declarative => (Some(loc.def.krate), loc.def.local_inner), |
33 | MacroDefKind::BuiltIn(_) => (loc.def.krate, false), | 33 | MacroDefKind::BuiltIn(_) => (Some(loc.def.krate), false), |
34 | MacroDefKind::BuiltInDerive(_) => (None, false), | 34 | MacroDefKind::BuiltInDerive(_) => (None, false), |
35 | MacroDefKind::BuiltInEager(_) => (None, false), | 35 | MacroDefKind::BuiltInEager(_) => (None, false), |
36 | MacroDefKind::ProcMacro(_) => (None, false), | 36 | MacroDefKind::ProcMacro(_) => (None, false), |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index ae3086a95..d486186e5 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -145,7 +145,10 @@ impl HirFileId { | |||
145 | let arg_tt = loc.kind.arg(db)?; | 145 | let arg_tt = loc.kind.arg(db)?; |
146 | 146 | ||
147 | let def = loc.def.ast_id.and_then(|id| { | 147 | let def = loc.def.ast_id.and_then(|id| { |
148 | let def_tt = id.to_node(db).token_tree()?; | 148 | let def_tt = match id.to_node(db) { |
149 | ast::Macro::MacroRules(mac) => mac.token_tree()?, | ||
150 | ast::Macro::MacroDef(_) => return None, | ||
151 | }; | ||
149 | Some(InFile::new(id.file_id, def_tt)) | 152 | Some(InFile::new(id.file_id, def_tt)) |
150 | }); | 153 | }); |
151 | 154 | ||
@@ -221,14 +224,8 @@ impl From<EagerMacroId> for MacroCallId { | |||
221 | 224 | ||
222 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 225 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
223 | pub struct MacroDefId { | 226 | pub struct MacroDefId { |
224 | // FIXME: krate and ast_id are currently optional because we don't have a | 227 | pub krate: CrateId, |
225 | // definition location for built-in derives. There is one, though: the | 228 | pub ast_id: Option<AstId<ast::Macro>>, |
226 | // standard library defines them. The problem is that it uses the new | ||
227 | // `macro` syntax for this, which we don't support yet. As soon as we do | ||
228 | // (which will probably require touching this code), we can instead use | ||
229 | // that (and also remove the hacks for resolving built-in derives). | ||
230 | pub krate: Option<CrateId>, | ||
231 | pub ast_id: Option<AstId<ast::MacroRules>>, | ||
232 | pub kind: MacroDefKind, | 229 | pub kind: MacroDefKind, |
233 | 230 | ||
234 | pub local_inner: bool, | 231 | pub local_inner: bool, |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 69d8e6803..7fb4caea3 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -37,9 +37,8 @@ impl Name { | |||
37 | Name(Repr::TupleField(idx)) | 37 | Name(Repr::TupleField(idx)) |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn new_lifetime(lt: &syntax::SyntaxToken) -> Name { | 40 | pub fn new_lifetime(lt: &ast::Lifetime) -> Name { |
41 | assert_eq!(lt.kind(), syntax::SyntaxKind::LIFETIME); | 41 | Self::new_text(lt.text().clone()) |
42 | Name(Repr::Text(lt.text().clone())) | ||
43 | } | 42 | } |
44 | 43 | ||
45 | /// Shortcut to create inline plain text name | 44 | /// Shortcut to create inline plain text name |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 1c72f766e..14e18f5a1 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -6,6 +6,7 @@ mod decl_check; | |||
6 | 6 | ||
7 | use std::{any::Any, fmt}; | 7 | use std::{any::Any, fmt}; |
8 | 8 | ||
9 | use base_db::CrateId; | ||
9 | use hir_def::{DefWithBodyId, ModuleDefId}; | 10 | use hir_def::{DefWithBodyId, ModuleDefId}; |
10 | use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink}; | 11 | use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink}; |
11 | use hir_expand::{name::Name, HirFileId, InFile}; | 12 | use hir_expand::{name::Name, HirFileId, InFile}; |
@@ -18,12 +19,13 @@ pub use crate::diagnostics::expr::{record_literal_missing_fields, record_pattern | |||
18 | 19 | ||
19 | pub fn validate_module_item( | 20 | pub fn validate_module_item( |
20 | db: &dyn HirDatabase, | 21 | db: &dyn HirDatabase, |
22 | krate: CrateId, | ||
21 | owner: ModuleDefId, | 23 | owner: ModuleDefId, |
22 | sink: &mut DiagnosticSink<'_>, | 24 | sink: &mut DiagnosticSink<'_>, |
23 | ) { | 25 | ) { |
24 | let _p = profile::span("validate_module_item"); | 26 | let _p = profile::span("validate_module_item"); |
25 | let mut validator = decl_check::DeclValidator::new(owner, sink); | 27 | let mut validator = decl_check::DeclValidator::new(db, krate, sink); |
26 | validator.validate_item(db); | 28 | validator.validate_item(owner); |
27 | } | 29 | } |
28 | 30 | ||
29 | pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { | 31 | pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { |
@@ -407,7 +409,7 @@ mod tests { | |||
407 | for (module_id, _) in crate_def_map.modules.iter() { | 409 | for (module_id, _) in crate_def_map.modules.iter() { |
408 | for decl in crate_def_map[module_id].scope.declarations() { | 410 | for decl in crate_def_map[module_id].scope.declarations() { |
409 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 411 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
410 | validate_module_item(self, decl, &mut sink); | 412 | validate_module_item(self, krate, decl, &mut sink); |
411 | 413 | ||
412 | if let ModuleDefId::FunctionId(f) = decl { | 414 | if let ModuleDefId::FunctionId(f) = decl { |
413 | fns.push(f) | 415 | fns.push(f) |
@@ -419,7 +421,12 @@ mod tests { | |||
419 | for item in impl_data.items.iter() { | 421 | for item in impl_data.items.iter() { |
420 | if let AssocItemId::FunctionId(f) = item { | 422 | if let AssocItemId::FunctionId(f) = item { |
421 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 423 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
422 | validate_module_item(self, ModuleDefId::FunctionId(*f), &mut sink); | 424 | validate_module_item( |
425 | self, | ||
426 | krate, | ||
427 | ModuleDefId::FunctionId(*f), | ||
428 | &mut sink, | ||
429 | ); | ||
423 | fns.push(*f) | 430 | fns.push(*f) |
424 | } | 431 | } |
425 | } | 432 | } |
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 25587e116..eaeb6899f 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | mod case_conv; | 13 | mod case_conv; |
14 | 14 | ||
15 | use base_db::CrateId; | ||
15 | use hir_def::{ | 16 | use hir_def::{ |
16 | adt::VariantData, | 17 | adt::VariantData, |
17 | expr::{Pat, PatId}, | 18 | expr::{Pat, PatId}, |
@@ -40,7 +41,8 @@ mod allow { | |||
40 | } | 41 | } |
41 | 42 | ||
42 | pub(super) struct DeclValidator<'a, 'b: 'a> { | 43 | pub(super) struct DeclValidator<'a, 'b: 'a> { |
43 | owner: ModuleDefId, | 44 | db: &'a dyn HirDatabase, |
45 | krate: CrateId, | ||
44 | sink: &'a mut DiagnosticSink<'b>, | 46 | sink: &'a mut DiagnosticSink<'b>, |
45 | } | 47 | } |
46 | 48 | ||
@@ -53,26 +55,27 @@ struct Replacement { | |||
53 | 55 | ||
54 | impl<'a, 'b> DeclValidator<'a, 'b> { | 56 | impl<'a, 'b> DeclValidator<'a, 'b> { |
55 | pub(super) fn new( | 57 | pub(super) fn new( |
56 | owner: ModuleDefId, | 58 | db: &'a dyn HirDatabase, |
59 | krate: CrateId, | ||
57 | sink: &'a mut DiagnosticSink<'b>, | 60 | sink: &'a mut DiagnosticSink<'b>, |
58 | ) -> DeclValidator<'a, 'b> { | 61 | ) -> DeclValidator<'a, 'b> { |
59 | DeclValidator { owner, sink } | 62 | DeclValidator { db, krate, sink } |
60 | } | 63 | } |
61 | 64 | ||
62 | pub(super) fn validate_item(&mut self, db: &dyn HirDatabase) { | 65 | pub(super) fn validate_item(&mut self, item: ModuleDefId) { |
63 | match self.owner { | 66 | match item { |
64 | ModuleDefId::FunctionId(func) => self.validate_func(db, func), | 67 | ModuleDefId::FunctionId(func) => self.validate_func(func), |
65 | ModuleDefId::AdtId(adt) => self.validate_adt(db, adt), | 68 | ModuleDefId::AdtId(adt) => self.validate_adt(adt), |
66 | ModuleDefId::ConstId(const_id) => self.validate_const(db, const_id), | 69 | ModuleDefId::ConstId(const_id) => self.validate_const(const_id), |
67 | ModuleDefId::StaticId(static_id) => self.validate_static(db, static_id), | 70 | ModuleDefId::StaticId(static_id) => self.validate_static(static_id), |
68 | _ => return, | 71 | _ => return, |
69 | } | 72 | } |
70 | } | 73 | } |
71 | 74 | ||
72 | fn validate_adt(&mut self, db: &dyn HirDatabase, adt: AdtId) { | 75 | fn validate_adt(&mut self, adt: AdtId) { |
73 | match adt { | 76 | match adt { |
74 | AdtId::StructId(struct_id) => self.validate_struct(db, struct_id), | 77 | AdtId::StructId(struct_id) => self.validate_struct(struct_id), |
75 | AdtId::EnumId(enum_id) => self.validate_enum(db, enum_id), | 78 | AdtId::EnumId(enum_id) => self.validate_enum(enum_id), |
76 | AdtId::UnionId(_) => { | 79 | AdtId::UnionId(_) => { |
77 | // Unions aren't yet supported by this validator. | 80 | // Unions aren't yet supported by this validator. |
78 | } | 81 | } |
@@ -82,27 +85,27 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
82 | /// Checks whether not following the convention is allowed for this item. | 85 | /// Checks whether not following the convention is allowed for this item. |
83 | /// | 86 | /// |
84 | /// Currently this method doesn't check parent attributes. | 87 | /// Currently this method doesn't check parent attributes. |
85 | fn allowed(&self, db: &dyn HirDatabase, id: AttrDefId, allow_name: &str) -> bool { | 88 | fn allowed(&self, id: AttrDefId, allow_name: &str) -> bool { |
86 | db.attrs(id).by_key("allow").tt_values().any(|tt| tt.to_string().contains(allow_name)) | 89 | self.db.attrs(id).by_key("allow").tt_values().any(|tt| tt.to_string().contains(allow_name)) |
87 | } | 90 | } |
88 | 91 | ||
89 | fn validate_func(&mut self, db: &dyn HirDatabase, func: FunctionId) { | 92 | fn validate_func(&mut self, func: FunctionId) { |
90 | let data = db.function_data(func); | 93 | let data = self.db.function_data(func); |
91 | if data.is_extern { | 94 | if data.is_extern { |
92 | mark::hit!(extern_func_incorrect_case_ignored); | 95 | mark::hit!(extern_func_incorrect_case_ignored); |
93 | return; | 96 | return; |
94 | } | 97 | } |
95 | 98 | ||
96 | let body = db.body(func.into()); | 99 | let body = self.db.body(func.into()); |
97 | 100 | ||
98 | // Recursively validate inner scope items, such as static variables and constants. | 101 | // Recursively validate inner scope items, such as static variables and constants. |
99 | for (item_id, _) in body.item_scope.values() { | 102 | for (item_id, _) in body.item_scope.values() { |
100 | let mut validator = DeclValidator::new(item_id, self.sink); | 103 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); |
101 | validator.validate_item(db); | 104 | validator.validate_item(item_id); |
102 | } | 105 | } |
103 | 106 | ||
104 | // Check whether non-snake case identifiers are allowed for this function. | 107 | // Check whether non-snake case identifiers are allowed for this function. |
105 | if self.allowed(db, func.into(), allow::NON_SNAKE_CASE) { | 108 | if self.allowed(func.into(), allow::NON_SNAKE_CASE) { |
106 | return; | 109 | return; |
107 | } | 110 | } |
108 | 111 | ||
@@ -169,11 +172,10 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
169 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. | 172 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. |
170 | self.create_incorrect_case_diagnostic_for_func( | 173 | self.create_incorrect_case_diagnostic_for_func( |
171 | func, | 174 | func, |
172 | db, | ||
173 | fn_name_replacement, | 175 | fn_name_replacement, |
174 | fn_param_replacements, | 176 | fn_param_replacements, |
175 | ); | 177 | ); |
176 | self.create_incorrect_case_diagnostic_for_variables(func, db, pats_replacements); | 178 | self.create_incorrect_case_diagnostic_for_variables(func, pats_replacements); |
177 | } | 179 | } |
178 | 180 | ||
179 | /// Given the information about incorrect names in the function declaration, looks up into the source code | 181 | /// Given the information about incorrect names in the function declaration, looks up into the source code |
@@ -181,7 +183,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
181 | fn create_incorrect_case_diagnostic_for_func( | 183 | fn create_incorrect_case_diagnostic_for_func( |
182 | &mut self, | 184 | &mut self, |
183 | func: FunctionId, | 185 | func: FunctionId, |
184 | db: &dyn HirDatabase, | ||
185 | fn_name_replacement: Option<Replacement>, | 186 | fn_name_replacement: Option<Replacement>, |
186 | fn_param_replacements: Vec<Replacement>, | 187 | fn_param_replacements: Vec<Replacement>, |
187 | ) { | 188 | ) { |
@@ -190,8 +191,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
190 | return; | 191 | return; |
191 | } | 192 | } |
192 | 193 | ||
193 | let fn_loc = func.lookup(db.upcast()); | 194 | let fn_loc = func.lookup(self.db.upcast()); |
194 | let fn_src = fn_loc.source(db.upcast()); | 195 | let fn_src = fn_loc.source(self.db.upcast()); |
195 | 196 | ||
196 | // Diagnostic for function name. | 197 | // Diagnostic for function name. |
197 | if let Some(replacement) = fn_name_replacement { | 198 | if let Some(replacement) = fn_name_replacement { |
@@ -282,7 +283,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
282 | fn create_incorrect_case_diagnostic_for_variables( | 283 | fn create_incorrect_case_diagnostic_for_variables( |
283 | &mut self, | 284 | &mut self, |
284 | func: FunctionId, | 285 | func: FunctionId, |
285 | db: &dyn HirDatabase, | ||
286 | pats_replacements: Vec<(PatId, Replacement)>, | 286 | pats_replacements: Vec<(PatId, Replacement)>, |
287 | ) { | 287 | ) { |
288 | // XXX: only look at source_map if we do have missing fields | 288 | // XXX: only look at source_map if we do have missing fields |
@@ -290,12 +290,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
290 | return; | 290 | return; |
291 | } | 291 | } |
292 | 292 | ||
293 | let (_, source_map) = db.body_with_source_map(func.into()); | 293 | let (_, source_map) = self.db.body_with_source_map(func.into()); |
294 | 294 | ||
295 | for (id, replacement) in pats_replacements { | 295 | for (id, replacement) in pats_replacements { |
296 | if let Ok(source_ptr) = source_map.pat_syntax(id) { | 296 | if let Ok(source_ptr) = source_map.pat_syntax(id) { |
297 | if let Some(expr) = source_ptr.value.as_ref().left() { | 297 | if let Some(expr) = source_ptr.value.as_ref().left() { |
298 | let root = source_ptr.file_syntax(db.upcast()); | 298 | let root = source_ptr.file_syntax(self.db.upcast()); |
299 | if let ast::Pat::IdentPat(ident_pat) = expr.to_node(&root) { | 299 | if let ast::Pat::IdentPat(ident_pat) = expr.to_node(&root) { |
300 | let parent = match ident_pat.syntax().parent() { | 300 | let parent = match ident_pat.syntax().parent() { |
301 | Some(parent) => parent, | 301 | Some(parent) => parent, |
@@ -333,12 +333,11 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
336 | fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) { | 336 | fn validate_struct(&mut self, struct_id: StructId) { |
337 | let data = db.struct_data(struct_id); | 337 | let data = self.db.struct_data(struct_id); |
338 | 338 | ||
339 | let non_camel_case_allowed = | 339 | let non_camel_case_allowed = self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES); |
340 | self.allowed(db, struct_id.into(), allow::NON_CAMEL_CASE_TYPES); | 340 | let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE); |
341 | let non_snake_case_allowed = self.allowed(db, struct_id.into(), allow::NON_SNAKE_CASE); | ||
342 | 341 | ||
343 | // Check the structure name. | 342 | // Check the structure name. |
344 | let struct_name = data.name.to_string(); | 343 | let struct_name = data.name.to_string(); |
@@ -379,7 +378,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
379 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. | 378 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. |
380 | self.create_incorrect_case_diagnostic_for_struct( | 379 | self.create_incorrect_case_diagnostic_for_struct( |
381 | struct_id, | 380 | struct_id, |
382 | db, | ||
383 | struct_name_replacement, | 381 | struct_name_replacement, |
384 | struct_fields_replacements, | 382 | struct_fields_replacements, |
385 | ); | 383 | ); |
@@ -390,7 +388,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
390 | fn create_incorrect_case_diagnostic_for_struct( | 388 | fn create_incorrect_case_diagnostic_for_struct( |
391 | &mut self, | 389 | &mut self, |
392 | struct_id: StructId, | 390 | struct_id: StructId, |
393 | db: &dyn HirDatabase, | ||
394 | struct_name_replacement: Option<Replacement>, | 391 | struct_name_replacement: Option<Replacement>, |
395 | struct_fields_replacements: Vec<Replacement>, | 392 | struct_fields_replacements: Vec<Replacement>, |
396 | ) { | 393 | ) { |
@@ -399,8 +396,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
399 | return; | 396 | return; |
400 | } | 397 | } |
401 | 398 | ||
402 | let struct_loc = struct_id.lookup(db.upcast()); | 399 | let struct_loc = struct_id.lookup(self.db.upcast()); |
403 | let struct_src = struct_loc.source(db.upcast()); | 400 | let struct_src = struct_loc.source(self.db.upcast()); |
404 | 401 | ||
405 | if let Some(replacement) = struct_name_replacement { | 402 | if let Some(replacement) = struct_name_replacement { |
406 | let ast_ptr = match struct_src.value.name() { | 403 | let ast_ptr = match struct_src.value.name() { |
@@ -473,11 +470,11 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
473 | } | 470 | } |
474 | } | 471 | } |
475 | 472 | ||
476 | fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) { | 473 | fn validate_enum(&mut self, enum_id: EnumId) { |
477 | let data = db.enum_data(enum_id); | 474 | let data = self.db.enum_data(enum_id); |
478 | 475 | ||
479 | // Check whether non-camel case names are allowed for this enum. | 476 | // Check whether non-camel case names are allowed for this enum. |
480 | if self.allowed(db, enum_id.into(), allow::NON_CAMEL_CASE_TYPES) { | 477 | if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES) { |
481 | return; | 478 | return; |
482 | } | 479 | } |
483 | 480 | ||
@@ -512,7 +509,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
512 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. | 509 | // If there is at least one element to spawn a warning on, go to the source map and generate a warning. |
513 | self.create_incorrect_case_diagnostic_for_enum( | 510 | self.create_incorrect_case_diagnostic_for_enum( |
514 | enum_id, | 511 | enum_id, |
515 | db, | ||
516 | enum_name_replacement, | 512 | enum_name_replacement, |
517 | enum_fields_replacements, | 513 | enum_fields_replacements, |
518 | ) | 514 | ) |
@@ -523,7 +519,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
523 | fn create_incorrect_case_diagnostic_for_enum( | 519 | fn create_incorrect_case_diagnostic_for_enum( |
524 | &mut self, | 520 | &mut self, |
525 | enum_id: EnumId, | 521 | enum_id: EnumId, |
526 | db: &dyn HirDatabase, | ||
527 | enum_name_replacement: Option<Replacement>, | 522 | enum_name_replacement: Option<Replacement>, |
528 | enum_variants_replacements: Vec<Replacement>, | 523 | enum_variants_replacements: Vec<Replacement>, |
529 | ) { | 524 | ) { |
@@ -532,8 +527,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
532 | return; | 527 | return; |
533 | } | 528 | } |
534 | 529 | ||
535 | let enum_loc = enum_id.lookup(db.upcast()); | 530 | let enum_loc = enum_id.lookup(self.db.upcast()); |
536 | let enum_src = enum_loc.source(db.upcast()); | 531 | let enum_src = enum_loc.source(self.db.upcast()); |
537 | 532 | ||
538 | if let Some(replacement) = enum_name_replacement { | 533 | if let Some(replacement) = enum_name_replacement { |
539 | let ast_ptr = match enum_src.value.name() { | 534 | let ast_ptr = match enum_src.value.name() { |
@@ -608,10 +603,10 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
608 | } | 603 | } |
609 | } | 604 | } |
610 | 605 | ||
611 | fn validate_const(&mut self, db: &dyn HirDatabase, const_id: ConstId) { | 606 | fn validate_const(&mut self, const_id: ConstId) { |
612 | let data = db.const_data(const_id); | 607 | let data = self.db.const_data(const_id); |
613 | 608 | ||
614 | if self.allowed(db, const_id.into(), allow::NON_UPPER_CASE_GLOBAL) { | 609 | if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL) { |
615 | return; | 610 | return; |
616 | } | 611 | } |
617 | 612 | ||
@@ -632,8 +627,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
632 | return; | 627 | return; |
633 | }; | 628 | }; |
634 | 629 | ||
635 | let const_loc = const_id.lookup(db.upcast()); | 630 | let const_loc = const_id.lookup(self.db.upcast()); |
636 | let const_src = const_loc.source(db.upcast()); | 631 | let const_src = const_loc.source(self.db.upcast()); |
637 | 632 | ||
638 | let ast_ptr = match const_src.value.name() { | 633 | let ast_ptr = match const_src.value.name() { |
639 | Some(name) => name, | 634 | Some(name) => name, |
@@ -652,14 +647,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
652 | self.sink.push(diagnostic); | 647 | self.sink.push(diagnostic); |
653 | } | 648 | } |
654 | 649 | ||
655 | fn validate_static(&mut self, db: &dyn HirDatabase, static_id: StaticId) { | 650 | fn validate_static(&mut self, static_id: StaticId) { |
656 | let data = db.static_data(static_id); | 651 | let data = self.db.static_data(static_id); |
657 | if data.is_extern { | 652 | if data.is_extern { |
658 | mark::hit!(extern_static_incorrect_case_ignored); | 653 | mark::hit!(extern_static_incorrect_case_ignored); |
659 | return; | 654 | return; |
660 | } | 655 | } |
661 | 656 | ||
662 | if self.allowed(db, static_id.into(), allow::NON_UPPER_CASE_GLOBAL) { | 657 | if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL) { |
663 | return; | 658 | return; |
664 | } | 659 | } |
665 | 660 | ||
@@ -680,8 +675,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
680 | return; | 675 | return; |
681 | }; | 676 | }; |
682 | 677 | ||
683 | let static_loc = static_id.lookup(db.upcast()); | 678 | let static_loc = static_id.lookup(self.db.upcast()); |
684 | let static_src = static_loc.source(db.upcast()); | 679 | let static_src = static_loc.source(self.db.upcast()); |
685 | 680 | ||
686 | let ast_ptr = match static_src.value.name() { | 681 | let ast_ptr = match static_src.value.name() { |
687 | Some(name) => name, | 682 | Some(name) => name, |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index de97ec3c2..a7656b864 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -686,6 +686,8 @@ mod clone { | |||
686 | trait Clone { | 686 | trait Clone { |
687 | fn clone(&self) -> Self; | 687 | fn clone(&self) -> Self; |
688 | } | 688 | } |
689 | #[rustc_builtin_macro] | ||
690 | macro Clone {} | ||
689 | } | 691 | } |
690 | "#, | 692 | "#, |
691 | ); | 693 | ); |
@@ -702,6 +704,8 @@ mod clone { | |||
702 | trait Clone { | 704 | trait Clone { |
703 | fn clone(&self) -> Self; | 705 | fn clone(&self) -> Self; |
704 | } | 706 | } |
707 | #[rustc_builtin_macro] | ||
708 | macro Clone {} | ||
705 | } | 709 | } |
706 | #[derive(Clone)] | 710 | #[derive(Clone)] |
707 | pub struct S; | 711 | pub struct S; |
@@ -737,6 +741,8 @@ mod clone { | |||
737 | trait Clone { | 741 | trait Clone { |
738 | fn clone(&self) -> Self; | 742 | fn clone(&self) -> Self; |
739 | } | 743 | } |
744 | #[rustc_builtin_macro] | ||
745 | macro Clone {} | ||
740 | } | 746 | } |
741 | "#, | 747 | "#, |
742 | ); | 748 | ); |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 73fc73619..48acb8c93 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -1,15 +1,13 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{ | 4 | use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource}; |
5 | AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirFileId, InFile, ModuleSource, | ||
6 | }; | ||
7 | use ide_db::base_db::{FileId, SourceDatabase}; | 5 | use ide_db::base_db::{FileId, SourceDatabase}; |
8 | use ide_db::{defs::Definition, RootDatabase}; | 6 | use ide_db::{defs::Definition, RootDatabase}; |
9 | use syntax::{ | 7 | use syntax::{ |
10 | ast::{self, NameOwner}, | 8 | ast::{self, NameOwner}, |
11 | match_ast, AstNode, SmolStr, | 9 | match_ast, AstNode, SmolStr, |
12 | SyntaxKind::{self, IDENT_PAT, TYPE_PARAM}, | 10 | SyntaxKind::{self, IDENT_PAT, LIFETIME_PARAM, TYPE_PARAM}, |
13 | TextRange, | 11 | TextRange, |
14 | }; | 12 | }; |
15 | 13 | ||
@@ -119,25 +117,6 @@ impl NavigationTarget { | |||
119 | ) | 117 | ) |
120 | } | 118 | } |
121 | 119 | ||
122 | /// Allows `NavigationTarget` to be created from a `DocCommentsOwner` and a `NameOwner` | ||
123 | pub(crate) fn from_doc_commented( | ||
124 | db: &RootDatabase, | ||
125 | named: InFile<&dyn ast::NameOwner>, | ||
126 | node: InFile<&dyn ast::DocCommentsOwner>, | ||
127 | ) -> NavigationTarget { | ||
128 | let name = | ||
129 | named.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_")); | ||
130 | let frange = node.map(|it| it.syntax()).original_file_range(db); | ||
131 | |||
132 | NavigationTarget::from_syntax( | ||
133 | frange.file_id, | ||
134 | name, | ||
135 | None, | ||
136 | frange.range, | ||
137 | node.value.syntax().kind(), | ||
138 | ) | ||
139 | } | ||
140 | |||
141 | fn from_syntax( | 120 | fn from_syntax( |
142 | file_id: FileId, | 121 | file_id: FileId, |
143 | name: SmolStr, | 122 | name: SmolStr, |
@@ -168,7 +147,7 @@ impl ToNav for FileSymbol { | |||
168 | focus_range: self.name_range, | 147 | focus_range: self.name_range, |
169 | container_name: self.container_name.clone(), | 148 | container_name: self.container_name.clone(), |
170 | description: description_from_symbol(db, self), | 149 | description: description_from_symbol(db, self), |
171 | docs: docs_from_symbol(db, self), | 150 | docs: None, |
172 | } | 151 | } |
173 | } | 152 | } |
174 | } | 153 | } |
@@ -190,6 +169,7 @@ impl TryToNav for Definition { | |||
190 | Definition::SelfType(it) => Some(it.to_nav(db)), | 169 | Definition::SelfType(it) => Some(it.to_nav(db)), |
191 | Definition::Local(it) => Some(it.to_nav(db)), | 170 | Definition::Local(it) => Some(it.to_nav(db)), |
192 | Definition::TypeParam(it) => Some(it.to_nav(db)), | 171 | Definition::TypeParam(it) => Some(it.to_nav(db)), |
172 | Definition::LifetimeParam(it) => Some(it.to_nav(db)), | ||
193 | } | 173 | } |
194 | } | 174 | } |
195 | } | 175 | } |
@@ -252,7 +232,7 @@ impl ToNav for hir::Module { | |||
252 | } | 232 | } |
253 | } | 233 | } |
254 | 234 | ||
255 | impl ToNav for hir::ImplDef { | 235 | impl ToNav for hir::Impl { |
256 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 236 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
257 | let src = self.source(db); | 237 | let src = self.source(db); |
258 | let derive_attr = self.is_builtin_derive(db); | 238 | let derive_attr = self.is_builtin_derive(db); |
@@ -384,28 +364,21 @@ impl ToNav for hir::TypeParam { | |||
384 | } | 364 | } |
385 | } | 365 | } |
386 | 366 | ||
387 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<Documentation> { | 367 | impl ToNav for hir::LifetimeParam { |
388 | let parse = db.parse(symbol.file_id); | 368 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
389 | let node = symbol.ptr.to_node(parse.tree().syntax()); | 369 | let src = self.source(db); |
390 | let file_id = HirFileId::from(symbol.file_id); | 370 | let full_range = src.value.syntax().text_range(); |
391 | 371 | NavigationTarget { | |
392 | let it = match_ast! { | 372 | file_id: src.file_id.original_file(db), |
393 | match node { | 373 | name: self.name(db).to_string().into(), |
394 | ast::Fn(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 374 | kind: LIFETIME_PARAM, |
395 | ast::Struct(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 375 | full_range, |
396 | ast::Enum(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 376 | focus_range: Some(full_range), |
397 | ast::Trait(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 377 | container_name: None, |
398 | ast::Module(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 378 | description: None, |
399 | ast::TypeAlias(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | 379 | docs: None, |
400 | ast::Const(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | ||
401 | ast::Static(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | ||
402 | ast::RecordField(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | ||
403 | ast::Variant(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | ||
404 | ast::MacroCall(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), | ||
405 | _ => return None, | ||
406 | } | 380 | } |
407 | }; | 381 | } |
408 | it.docs() | ||
409 | } | 382 | } |
410 | 383 | ||
411 | /// Get a description of a symbol. | 384 | /// Get a description of a symbol. |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 10263537a..79c081cac 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -112,7 +112,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | |||
112 | .as_assoc_item(db) | 112 | .as_assoc_item(db) |
113 | .and_then(|assoc| match assoc.container(db) { |