diff options
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 464 |
1 files changed, 220 insertions, 244 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 92860fb59..534f1f8e9 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1,39 +1,33 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub(crate) mod src; | 3 | pub(crate) mod src; |
4 | pub(crate) mod docs; | ||
5 | pub(crate) mod attrs; | ||
6 | 4 | ||
7 | use std::sync::Arc; | 5 | use std::sync::Arc; |
8 | 6 | ||
9 | use hir_def::{ | 7 | use hir_def::{ |
10 | adt::VariantData, | 8 | adt::VariantData, |
11 | body::scope::ExprScopes, | ||
12 | builtin_type::BuiltinType, | 9 | builtin_type::BuiltinType, |
13 | nameres::per_ns::PerNs, | 10 | docs::Documentation, |
11 | per_ns::PerNs, | ||
14 | resolver::{HasResolver, TypeNs}, | 12 | resolver::{HasResolver, TypeNs}, |
15 | traits::TraitData, | 13 | type_ref::TypeRef, |
16 | type_ref::{Mutability, TypeRef}, | 14 | AstItemDef, ConstId, ContainerId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, |
17 | ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, | 15 | LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, |
18 | ModuleId, UnionId, | 16 | StaticId, StructId, TraitId, TypeAliasId, UnionId, |
19 | }; | 17 | }; |
20 | use hir_expand::{ | 18 | use hir_expand::{ |
21 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
22 | name::{self, AsName}, | 20 | name::{self, AsName}, |
21 | AstId, MacroDefId, | ||
23 | }; | 22 | }; |
24 | use ra_db::{CrateId, Edition}; | 23 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
25 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 24 | use ra_syntax::{ast, AstNode, SyntaxNode}; |
26 | 25 | ||
27 | use crate::{ | 26 | use crate::{ |
28 | db::{AstDatabase, DefDatabase, HirDatabase}, | 27 | db::{DefDatabase, HirDatabase}, |
29 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, | 28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, |
30 | generics::{GenericDef, HasGenericParams}, | ||
31 | ids::{ | ||
32 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, | ||
33 | TypeAliasId, | ||
34 | }, | ||
35 | ty::{InferenceResult, Namespace, TraitRef}, | 29 | ty::{InferenceResult, Namespace, TraitRef}, |
36 | Either, HasSource, ImportId, Name, Source, Ty, | 30 | Either, Name, Source, Ty, |
37 | }; | 31 | }; |
38 | 32 | ||
39 | /// hir::Crate describes a single crate. It's the main interface with which | 33 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -67,7 +61,7 @@ impl Crate { | |||
67 | } | 61 | } |
68 | 62 | ||
69 | pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> { | 63 | pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> { |
70 | let module_id = db.crate_def_map(self.crate_id).root(); | 64 | let module_id = db.crate_def_map(self.crate_id).root; |
71 | Some(Module::new(self, module_id)) | 65 | Some(Module::new(self, module_id)) |
72 | } | 66 | } |
73 | 67 | ||
@@ -81,6 +75,64 @@ impl Crate { | |||
81 | } | 75 | } |
82 | } | 76 | } |
83 | 77 | ||
78 | pub enum ModuleSource { | ||
79 | SourceFile(ast::SourceFile), | ||
80 | Module(ast::Module), | ||
81 | } | ||
82 | |||
83 | impl ModuleSource { | ||
84 | pub fn new( | ||
85 | db: &impl DefDatabase, | ||
86 | file_id: Option<FileId>, | ||
87 | decl_id: Option<AstId<ast::Module>>, | ||
88 | ) -> ModuleSource { | ||
89 | match (file_id, decl_id) { | ||
90 | (Some(file_id), _) => { | ||
91 | let source_file = db.parse(file_id).tree(); | ||
92 | ModuleSource::SourceFile(source_file) | ||
93 | } | ||
94 | (None, Some(item_id)) => { | ||
95 | let module = item_id.to_node(db); | ||
96 | assert!(module.item_list().is_some(), "expected inline module"); | ||
97 | ModuleSource::Module(module) | ||
98 | } | ||
99 | (None, None) => panic!(), | ||
100 | } | ||
101 | } | ||
102 | |||
103 | // FIXME: this methods do not belong here | ||
104 | pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { | ||
105 | let parse = db.parse(position.file_id); | ||
106 | match &ra_syntax::algo::find_node_at_offset::<ast::Module>( | ||
107 | parse.tree().syntax(), | ||
108 | position.offset, | ||
109 | ) { | ||
110 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
111 | _ => { | ||
112 | let source_file = parse.tree(); | ||
113 | ModuleSource::SourceFile(source_file) | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | pub fn from_child_node(db: &impl DefDatabase, child: Source<&SyntaxNode>) -> ModuleSource { | ||
119 | if let Some(m) = | ||
120 | child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) | ||
121 | { | ||
122 | ModuleSource::Module(m) | ||
123 | } else { | ||
124 | let file_id = child.file_id.original_file(db); | ||
125 | let source_file = db.parse(file_id).tree(); | ||
126 | ModuleSource::SourceFile(source_file) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource { | ||
131 | let source_file = db.parse(file_id).tree(); | ||
132 | ModuleSource::SourceFile(source_file) | ||
133 | } | ||
134 | } | ||
135 | |||
84 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 136 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
85 | pub struct Module { | 137 | pub struct Module { |
86 | pub(crate) id: ModuleId, | 138 | pub(crate) id: ModuleId, |
@@ -112,10 +164,10 @@ impl_froms!( | |||
112 | BuiltinType | 164 | BuiltinType |
113 | ); | 165 | ); |
114 | 166 | ||
115 | pub use hir_def::ModuleSource; | 167 | pub use hir_def::attr::Attrs; |
116 | 168 | ||
117 | impl Module { | 169 | impl Module { |
118 | pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { | 170 | pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { |
119 | Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } | 171 | Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } |
120 | } | 172 | } |
121 | 173 | ||
@@ -132,17 +184,6 @@ impl Module { | |||
132 | }) | 184 | }) |
133 | } | 185 | } |
134 | 186 | ||
135 | /// Returns the syntax of the last path segment corresponding to this import | ||
136 | pub fn import_source( | ||
137 | self, | ||
138 | db: &impl HirDatabase, | ||
139 | import: ImportId, | ||
140 | ) -> Either<ast::UseTree, ast::ExternCrateItem> { | ||
141 | let src = self.definition_source(db); | ||
142 | let (_, source_map) = db.raw_items_with_source_map(src.file_id); | ||
143 | source_map.get(&src.value, import) | ||
144 | } | ||
145 | |||
146 | /// Returns the crate this module is part of. | 187 | /// Returns the crate this module is part of. |
147 | pub fn krate(self) -> Crate { | 188 | pub fn krate(self) -> Crate { |
148 | Crate { crate_id: self.id.krate } | 189 | Crate { crate_id: self.id.krate } |
@@ -153,7 +194,7 @@ impl Module { | |||
153 | /// in the module tree of any target in `Cargo.toml`. | 194 | /// in the module tree of any target in `Cargo.toml`. |
154 | pub fn crate_root(self, db: &impl DefDatabase) -> Module { | 195 | pub fn crate_root(self, db: &impl DefDatabase) -> Module { |
155 | let def_map = db.crate_def_map(self.id.krate); | 196 | let def_map = db.crate_def_map(self.id.krate); |
156 | self.with_module_id(def_map.root()) | 197 | self.with_module_id(def_map.root) |
157 | } | 198 | } |
158 | 199 | ||
159 | /// Finds a child module with the specified name. | 200 | /// Finds a child module with the specified name. |
@@ -192,11 +233,13 @@ impl Module { | |||
192 | } | 233 | } |
193 | 234 | ||
194 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 235 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
195 | pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> { | 236 | pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> { |
196 | db.crate_def_map(self.id.krate)[self.id.module_id] | 237 | db.crate_def_map(self.id.krate)[self.id.module_id] |
197 | .scope | 238 | .scope |
198 | .entries() | 239 | .entries() |
199 | .map(|(name, res)| (name.clone(), res.def.into(), res.import)) | 240 | .map(|(name, res)| { |
241 | (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id })) | ||
242 | }) | ||
200 | .collect() | 243 | .collect() |
201 | } | 244 | } |
202 | 245 | ||
@@ -234,11 +277,16 @@ impl Module { | |||
234 | def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() | 277 | def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() |
235 | } | 278 | } |
236 | 279 | ||
237 | fn with_module_id(self, module_id: CrateModuleId) -> Module { | 280 | fn with_module_id(self, module_id: LocalModuleId) -> Module { |
238 | Module::new(self.krate(), module_id) | 281 | Module::new(self.krate(), module_id) |
239 | } | 282 | } |
240 | } | 283 | } |
241 | 284 | ||
285 | pub struct Import { | ||
286 | pub(crate) parent: Module, | ||
287 | pub(crate) id: LocalImportId, | ||
288 | } | ||
289 | |||
242 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 290 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
243 | pub struct StructField { | 291 | pub struct StructField { |
244 | pub(crate) parent: VariantDef, | 292 | pub(crate) parent: VariantDef, |
@@ -253,11 +301,11 @@ pub enum FieldSource { | |||
253 | 301 | ||
254 | impl StructField { | 302 | impl StructField { |
255 | pub fn name(&self, db: &impl HirDatabase) -> Name { | 303 | pub fn name(&self, db: &impl HirDatabase) -> Name { |
256 | self.parent.variant_data(db).fields().unwrap()[self.id].name.clone() | 304 | self.parent.variant_data(db).fields()[self.id].name.clone() |
257 | } | 305 | } |
258 | 306 | ||
259 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 307 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
260 | db.type_for_field(*self) | 308 | db.field_types(self.parent.into())[self.id].clone() |
261 | } | 309 | } |
262 | 310 | ||
263 | pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef { | 311 | pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef { |
@@ -287,8 +335,7 @@ impl Struct { | |||
287 | db.struct_data(self.id.into()) | 335 | db.struct_data(self.id.into()) |
288 | .variant_data | 336 | .variant_data |
289 | .fields() | 337 | .fields() |
290 | .into_iter() | 338 | .iter() |
291 | .flat_map(|it| it.iter()) | ||
292 | .map(|(id, _)| StructField { parent: self.into(), id }) | 339 | .map(|(id, _)| StructField { parent: self.into(), id }) |
293 | .collect() | 340 | .collect() |
294 | } | 341 | } |
@@ -297,8 +344,7 @@ impl Struct { | |||
297 | db.struct_data(self.id.into()) | 344 | db.struct_data(self.id.into()) |
298 | .variant_data | 345 | .variant_data |
299 | .fields() | 346 | .fields() |
300 | .into_iter() | 347 | .iter() |
301 | .flat_map(|it| it.iter()) | ||
302 | .find(|(_id, data)| data.name == *name) | 348 | .find(|(_id, data)| data.name == *name) |
303 | .map(|(id, _)| StructField { parent: self.into(), id }) | 349 | .map(|(id, _)| StructField { parent: self.into(), id }) |
304 | } | 350 | } |
@@ -395,8 +441,7 @@ impl EnumVariant { | |||
395 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | 441 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
396 | self.variant_data(db) | 442 | self.variant_data(db) |
397 | .fields() | 443 | .fields() |
398 | .into_iter() | 444 | .iter() |
399 | .flat_map(|it| it.iter()) | ||
400 | .map(|(id, _)| StructField { parent: self.into(), id }) | 445 | .map(|(id, _)| StructField { parent: self.into(), id }) |
401 | .collect() | 446 | .collect() |
402 | } | 447 | } |
@@ -404,8 +449,7 @@ impl EnumVariant { | |||
404 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 449 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
405 | self.variant_data(db) | 450 | self.variant_data(db) |
406 | .fields() | 451 | .fields() |
407 | .into_iter() | 452 | .iter() |
408 | .flat_map(|it| it.iter()) | ||
409 | .find(|(_id, data)| data.name == *name) | 453 | .find(|(_id, data)| data.name == *name) |
410 | .map(|(id, _)| StructField { parent: self.into(), id }) | 454 | .map(|(id, _)| StructField { parent: self.into(), id }) |
411 | } | 455 | } |
@@ -461,7 +505,7 @@ impl VariantDef { | |||
461 | } | 505 | } |
462 | } | 506 | } |
463 | 507 | ||
464 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 508 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
465 | match self { | 509 | match self { |
466 | VariantDef::Struct(it) => it.field(db, name), | 510 | VariantDef::Struct(it) => it.field(db, name), |
467 | VariantDef::EnumVariant(it) => it.field(db, name), | 511 | VariantDef::EnumVariant(it) => it.field(db, name), |
@@ -511,128 +555,11 @@ impl DefWithBody { | |||
511 | } | 555 | } |
512 | } | 556 | } |
513 | 557 | ||
514 | pub trait HasBody: Copy { | ||
515 | fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult>; | ||
516 | fn body(self, db: &impl HirDatabase) -> Arc<Body>; | ||
517 | fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap>; | ||
518 | fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes>; | ||
519 | } | ||
520 | |||
521 | impl<T> HasBody for T | ||
522 | where | ||
523 | T: Into<DefWithBody> + Copy + HasSource, | ||
524 | { | ||
525 | fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | ||
526 | db.infer(self.into()) | ||
527 | } | ||
528 | |||
529 | fn body(self, db: &impl HirDatabase) -> Arc<Body> { | ||
530 | self.into().body(db) | ||
531 | } | ||
532 | |||
533 | fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | ||
534 | self.into().body_source_map(db) | ||
535 | } | ||
536 | |||
537 | fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes> { | ||
538 | self.into().expr_scopes(db) | ||
539 | } | ||
540 | } | ||
541 | |||
542 | impl HasBody for DefWithBody { | ||
543 | fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | ||
544 | db.infer(self) | ||
545 | } | ||
546 | |||
547 | fn body(self, db: &impl HirDatabase) -> Arc<Body> { | ||
548 | db.body(self.into()) | ||
549 | } | ||
550 | |||
551 | fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | ||
552 | db.body_with_source_map(self.into()).1 | ||
553 | } | ||
554 | |||
555 | fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes> { | ||
556 | db.expr_scopes(self.into()) | ||
557 | } | ||
558 | } | ||
559 | |||
560 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 558 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
561 | pub struct Function { | 559 | pub struct Function { |
562 | pub(crate) id: FunctionId, | 560 | pub(crate) id: FunctionId, |
563 | } | 561 | } |
564 | 562 | ||
565 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
566 | pub struct FnData { | ||
567 | pub(crate) name: Name, | ||
568 | pub(crate) params: Vec<TypeRef>, | ||
569 | pub(crate) ret_type: TypeRef, | ||
570 | /// True if the first param is `self`. This is relevant to decide whether this | ||
571 | /// can be called as a method. | ||
572 | pub(crate) has_self_param: bool, | ||
573 | } | ||
574 | |||
575 | impl FnData { | ||
576 | pub(crate) fn fn_data_query( | ||
577 | db: &(impl DefDatabase + AstDatabase), | ||
578 | func: Function, | ||
579 | ) -> Arc<FnData> { | ||
580 | let src = func.source(db); | ||
581 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); | ||
582 | let mut params = Vec::new(); | ||
583 | let mut has_self_param = false; | ||
584 | if let Some(param_list) = src.value.param_list() { | ||
585 | if let Some(self_param) = param_list.self_param() { | ||
586 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | ||
587 | TypeRef::from_ast(type_ref) | ||
588 | } else { | ||
589 | let self_type = TypeRef::Path(name::SELF_TYPE.into()); | ||
590 | match self_param.kind() { | ||
591 | ast::SelfParamKind::Owned => self_type, | ||
592 | ast::SelfParamKind::Ref => { | ||
593 | TypeRef::Reference(Box::new(self_type), Mutability::Shared) | ||
594 | } | ||
595 | ast::SelfParamKind::MutRef => { | ||
596 | TypeRef::Reference(Box::new(self_type), Mutability::Mut) | ||
597 | } | ||
598 | } | ||
599 | }; | ||
600 | params.push(self_type); | ||
601 | has_self_param = true; | ||
602 | } | ||
603 | for param in param_list.params() { | ||
604 | let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); | ||
605 | params.push(type_ref); | ||
606 | } | ||
607 | } | ||
608 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { | ||
609 | TypeRef::from_ast(type_ref) | ||
610 | } else { | ||
611 | TypeRef::unit() | ||
612 | }; | ||
613 | |||
614 | let sig = FnData { name, params, ret_type, has_self_param }; | ||
615 | Arc::new(sig) | ||
616 | } | ||
617 | pub fn name(&self) -> &Name { | ||
618 | &self.name | ||
619 | } | ||
620 | |||
621 | pub fn params(&self) -> &[TypeRef] { | ||
622 | &self.params | ||
623 | } | ||
624 | |||
625 | pub fn ret_type(&self) -> &TypeRef { | ||
626 | &self.ret_type | ||
627 | } | ||
628 | |||
629 | /// True if the first arg is `self`. This is relevant to decide whether this | ||
630 | /// can be called as a method. | ||
631 | pub fn has_self_param(&self) -> bool { | ||
632 | self.has_self_param | ||
633 | } | ||
634 | } | ||
635 | |||
636 | impl Function { | 563 | impl Function { |
637 | pub fn module(self, db: &impl DefDatabase) -> Module { | 564 | pub fn module(self, db: &impl DefDatabase) -> Module { |
638 | self.id.lookup(db).module(db).into() | 565 | self.id.lookup(db).module(db).into() |
@@ -643,10 +570,18 @@ impl Function { | |||
643 | } | 570 | } |
644 | 571 | ||
645 | pub fn name(self, db: &impl HirDatabase) -> Name { | 572 | pub fn name(self, db: &impl HirDatabase) -> Name { |
646 | self.data(db).name.clone() | 573 | db.function_data(self.id).name.clone() |
574 | } | ||
575 | |||
576 | pub fn has_self_param(self, db: &impl HirDatabase) -> bool { | ||
577 | db.function_data(self.id).has_self_param | ||
578 | } | ||
579 | |||
580 | pub fn params(self, db: &impl HirDatabase) -> Vec<TypeRef> { | ||
581 | db.function_data(self.id).params.clone() | ||
647 | } | 582 | } |
648 | 583 | ||
649 | pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | 584 | pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { |
650 | db.body_with_source_map(self.id.into()).1 | 585 | db.body_with_source_map(self.id.into()).1 |
651 | } | 586 | } |
652 | 587 | ||
@@ -658,10 +593,6 @@ impl Function { | |||
658 | db.type_for_def(self.into(), Namespace::Values) | 593 | db.type_for_def(self.into(), Namespace::Values) |
659 | } | 594 | } |
660 | 595 | ||
661 | pub fn data(self, db: &impl HirDatabase) -> Arc<FnData> { | ||
662 | db.fn_data(self) | ||
663 | } | ||
664 | |||
665 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 596 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
666 | db.infer(self.into()) | 597 | db.infer(self.into()) |
667 | } | 598 | } |
@@ -712,12 +643,8 @@ impl Const { | |||
712 | Some(self.module(db).krate()) | 643 | Some(self.module(db).krate()) |
713 | } | 644 | } |
714 | 645 | ||
715 | pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { | ||
716 | db.const_data(self) | ||
717 | } | ||
718 | |||
719 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | 646 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
720 | self.data(db).name().cloned() | 647 | db.const_data(self.id).name.clone() |
721 | } | 648 | } |
722 | 649 | ||
723 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 650 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
@@ -749,45 +676,6 @@ impl Const { | |||
749 | } | 676 | } |
750 | } | 677 | } |
751 | 678 | ||
752 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
753 | pub struct ConstData { | ||
754 | pub(crate) name: Option<Name>, | ||
755 | pub(crate) type_ref: TypeRef, | ||
756 | } | ||
757 | |||
758 | impl ConstData { | ||
759 | pub fn name(&self) -> Option<&Name> { | ||
760 | self.name.as_ref() | ||
761 | } | ||
762 | |||
763 | pub fn type_ref(&self) -> &TypeRef { | ||
764 | &self.type_ref | ||
765 | } | ||
766 | |||
767 | pub(crate) fn const_data_query( | ||
768 | db: &(impl DefDatabase + AstDatabase), | ||
769 | konst: Const, | ||
770 | ) -> Arc<ConstData> { | ||
771 | let node = konst.source(db).value; | ||
772 | const_data_for(&node) | ||
773 | } | ||
774 | |||
775 | pub(crate) fn static_data_query( | ||
776 | db: &(impl DefDatabase + AstDatabase), | ||
777 | konst: Static, | ||
778 | ) -> Arc<ConstData> { | ||
779 | let node = konst.source(db).value; | ||
780 | const_data_for(&node) | ||
781 | } | ||
782 | } | ||
783 | |||
784 | fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> { | ||
785 | let name = node.name().map(|n| n.as_name()); | ||
786 | let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); | ||
787 | let sig = ConstData { name, type_ref }; | ||
788 | Arc::new(sig) | ||
789 | } | ||
790 | |||
791 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 679 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
792 | pub struct Static { | 680 | pub struct Static { |
793 | pub(crate) id: StaticId, | 681 | pub(crate) id: StaticId, |
@@ -795,17 +683,13 @@ pub struct Static { | |||
795 | 683 | ||
796 | impl Static { | 684 | impl Static { |
797 | pub fn module(self, db: &impl DefDatabase) -> Module { | 685 | pub fn module(self, db: &impl DefDatabase) -> Module { |
798 | Module { id: self.id.module(db) } | 686 | Module { id: self.id.lookup(db).module(db) } |
799 | } | 687 | } |
800 | 688 | ||
801 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { | 689 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { |
802 | Some(self.module(db).krate()) | 690 | Some(self.module(db).krate()) |
803 | } | 691 | } |
804 | 692 | ||
805 | pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { | ||
806 | db.static_data(self) | ||
807 | } | ||
808 | |||
809 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 693 | pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
810 | db.infer(self.into()) | 694 | db.infer(self.into()) |
811 | } | 695 | } |
@@ -822,11 +706,11 @@ impl Trait { | |||
822 | } | 706 | } |
823 | 707 | ||
824 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 708 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
825 | self.trait_data(db).name.clone() | 709 | db.trait_data(self.id).name.clone() |
826 | } | 710 | } |
827 | 711 | ||
828 | pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { | 712 | pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { |
829 | self.trait_data(db).items.iter().map(|it| (*it).into()).collect() | 713 | db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() |
830 | } | 714 | } |
831 | 715 | ||
832 | fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { | 716 | fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { |
@@ -835,7 +719,7 @@ impl Trait { | |||
835 | // lifetime problems, but since there usually shouldn't be more than a | 719 | // lifetime problems, but since there usually shouldn't be more than a |
836 | // few direct traits this should be fine (we could even use some kind of | 720 | // few direct traits this should be fine (we could even use some kind of |
837 | // SmallVec if performance is a concern) | 721 | // SmallVec if performance is a concern) |
838 | self.generic_params(db) | 722 | db.generic_params(self.id.into()) |
839 | .where_predicates | 723 | .where_predicates |
840 | .iter() | 724 | .iter() |
841 | .filter_map(|pred| match &pred.type_ref { | 725 | .filter_map(|pred| match &pred.type_ref { |
@@ -872,7 +756,7 @@ impl Trait { | |||
872 | } | 756 | } |
873 | 757 | ||
874 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { | 758 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { |
875 | let trait_data = self.trait_data(db); | 759 | let trait_data = db.trait_data(self.id); |
876 | let res = | 760 | let res = |
877 | trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?; | 761 | trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?; |
878 | Some(res) | 762 | Some(res) |
@@ -886,16 +770,12 @@ impl Trait { | |||
886 | self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name)) | 770 | self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name)) |
887 | } | 771 | } |
888 | 772 | ||
889 | pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { | ||
890 | db.trait_data(self.id) | ||
891 | } | ||
892 | |||
893 | pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { | 773 | pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { |
894 | TraitRef::for_trait(db, self) | 774 | TraitRef::for_trait(db, self) |
895 | } | 775 | } |
896 | 776 | ||
897 | pub fn is_auto(self, db: &impl DefDatabase) -> bool { | 777 | pub fn is_auto(self, db: &impl DefDatabase) -> bool { |
898 | self.trait_data(db).auto | 778 | db.trait_data(self.id).auto |
899 | } | 779 | } |
900 | } | 780 | } |
901 | 781 | ||
@@ -938,7 +818,7 @@ impl TypeAlias { | |||
938 | } | 818 | } |
939 | 819 | ||
940 | pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> { | 820 | pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> { |
941 | db.type_alias_data(self).type_ref.clone() | 821 | db.type_alias_data(self.id).type_ref.clone() |
942 | } | 822 | } |
943 | 823 | ||
944 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 824 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
@@ -946,7 +826,7 @@ impl TypeAlias { | |||
946 | } | 826 | } |
947 | 827 | ||
948 | pub fn name(self, db: &impl DefDatabase) -> Name { | 828 | pub fn name(self, db: &impl DefDatabase) -> Name { |
949 | db.type_alias_data(self).name.clone() | 829 | db.type_alias_data(self.id).name.clone() |
950 | } | 830 | } |
951 | } | 831 | } |
952 | 832 | ||
@@ -975,16 +855,6 @@ pub enum AssocItem { | |||
975 | // casting them, and somehow making the constructors private, which would be annoying. | 855 | // casting them, and somehow making the constructors private, which would be annoying. |
976 | impl_froms!(AssocItem: Function, Const, TypeAlias); | 856 | impl_froms!(AssocItem: Function, Const, TypeAlias); |
977 | 857 | ||
978 | impl From<AssocItem> for crate::generics::GenericDef { | ||
979 | fn from(item: AssocItem) -> Self { | ||
980 | match item { | ||
981 | AssocItem::Function(f) => f.into(), | ||
982 | AssocItem::Const(c) => c.into(), | ||
983 | AssocItem::TypeAlias(t) => t.into(), | ||
984 | } | ||
985 | } | ||
986 | } | ||
987 | |||
988 | impl AssocItem { | 858 | impl AssocItem { |
989 | pub fn module(self, db: &impl DefDatabase) -> Module { | 859 | pub fn module(self, db: &impl DefDatabase) -> Module { |
990 | match self { | 860 | match self { |
@@ -1004,6 +874,29 @@ impl AssocItem { | |||
1004 | } | 874 | } |
1005 | } | 875 | } |
1006 | 876 | ||
877 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
878 | pub enum GenericDef { | ||
879 | Function(Function), | ||
880 | Adt(Adt), | ||
881 | Trait(Trait), | ||
882 | TypeAlias(TypeAlias), | ||
883 | ImplBlock(ImplBlock), | ||
884 | // enum variants cannot have generics themselves, but their parent enums | ||
885 | // can, and this makes some code easier to write | ||
886 | EnumVariant(EnumVariant), | ||
887 | // consts can have type parameters from their parents (i.e. associated consts of traits) | ||
888 | Const(Const), | ||
889 | } | ||
890 | impl_froms!( | ||
891 | GenericDef: Function, | ||
892 | Adt(Struct, Enum, Union), | ||
893 | Trait, | ||
894 | TypeAlias, | ||
895 | ImplBlock, | ||
896 | EnumVariant, | ||
897 | Const | ||
898 | ); | ||
899 | |||
1007 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 900 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1008 | pub struct Local { | 901 | pub struct Local { |
1009 | pub(crate) parent: DefWithBody, | 902 | pub(crate) parent: DefWithBody, |
@@ -1012,7 +905,7 @@ pub struct Local { | |||
1012 | 905 | ||
1013 | impl Local { | 906 | impl Local { |
1014 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { | 907 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
1015 | let body = self.parent.body(db); | 908 | let body = db.body(self.parent.into()); |
1016 | match &body[self.pat_id] { | 909 | match &body[self.pat_id] { |
1017 | Pat::Bind { name, .. } => Some(name.clone()), | 910 | Pat::Bind { name, .. } => Some(name.clone()), |
1018 | _ => None, | 911 | _ => None, |
@@ -1024,7 +917,7 @@ impl Local { | |||
1024 | } | 917 | } |
1025 | 918 | ||
1026 | pub fn is_mut(self, db: &impl HirDatabase) -> bool { | 919 | pub fn is_mut(self, db: &impl HirDatabase) -> bool { |
1027 | let body = self.parent.body(db); | 920 | let body = db.body(self.parent.into()); |
1028 | match &body[self.pat_id] { | 921 | match &body[self.pat_id] { |
1029 | Pat::Bind { mode, .. } => match mode { | 922 | Pat::Bind { mode, .. } => match mode { |
1030 | BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, | 923 | BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, |
@@ -1048,7 +941,7 @@ impl Local { | |||
1048 | } | 941 | } |
1049 | 942 | ||
1050 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { | 943 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { |
1051 | let source_map = self.parent.body_source_map(db); | 944 | let (_body, source_map) = db.body_with_source_map(self.parent.into()); |
1052 | let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... | 945 | let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... |
1053 | let root = src.file_syntax(db); | 946 | let root = src.file_syntax(db); |
1054 | src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) | 947 | src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) |
@@ -1057,7 +950,7 @@ impl Local { | |||
1057 | 950 | ||
1058 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 951 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1059 | pub struct GenericParam { | 952 | pub struct GenericParam { |
1060 | pub(crate) parent: GenericDef, | 953 | pub(crate) parent: GenericDefId, |
1061 | pub(crate) idx: u32, | 954 | pub(crate) idx: u32, |
1062 | } | 955 | } |
1063 | 956 | ||
@@ -1066,6 +959,41 @@ pub struct ImplBlock { | |||
1066 | pub(crate) id: ImplId, | 959 | pub(crate) id: ImplId, |
1067 | } | 960 | } |
1068 | 961 | ||
962 | impl ImplBlock { | ||
963 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { | ||
964 | db.impl_data(self.id).target_trait.clone() | ||
965 | } | ||
966 | |||
967 | pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { | ||
968 | db.impl_data(self.id).target_type.clone() | ||
969 | } | ||
970 | |||
971 | pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { | ||
972 | Ty::from_hir(db, &self.id.resolver(db), &self.target_type(db)) | ||
973 | } | ||
974 | |||
975 | pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> { | ||
976 | let target_ty = self.target_ty(db); | ||
977 | TraitRef::from_hir(db, &self.id.resolver(db), &self.target_trait(db)?, Some(target_ty)) | ||
978 | } | ||
979 | |||
980 | pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { | ||
981 | db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() | ||
982 | } | ||
983 | |||
984 | pub fn is_negative(&self, db: &impl DefDatabase) -> bool { | ||
985 | db.impl_data(self.id).is_negative | ||
986 | } | ||
987 | |||
988 | pub fn module(&self, db: &impl DefDatabase) -> Module { | ||
989 | self.id.module(db).into() | ||
990 | } | ||
991 | |||
992 | pub fn krate(&self, db: &impl DefDatabase) -> Crate { | ||
993 | Crate { crate_id: self.module(db).id.krate } | ||
994 | } | ||
995 | } | ||
996 | |||
1069 | /// For IDE only | 997 | /// For IDE only |
1070 | pub enum ScopeDef { | 998 | pub enum ScopeDef { |
1071 | ModuleDef(ModuleDef), | 999 | ModuleDef(ModuleDef), |
@@ -1083,8 +1011,56 @@ impl From<PerNs> for ScopeDef { | |||
1083 | .or_else(|| def.take_values()) | 1011 | .or_else(|| def.take_values()) |
1084 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) | 1012 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) |
1085 | .or_else(|| { | 1013 | .or_else(|| { |
1086 | def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) | 1014 | def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) |
1087 | }) | 1015 | }) |
1088 | .unwrap_or(ScopeDef::Unknown) | 1016 | .unwrap_or(ScopeDef::Unknown) |
1089 | } | 1017 | } |
1090 | } | 1018 | } |
1019 | |||
1020 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1021 | pub enum AttrDef { | ||
1022 | Module(Module), | ||
1023 | StructField(StructField), | ||
1024 | Adt(Adt), | ||
1025 | Function(Function), | ||
1026 | EnumVariant(EnumVariant), | ||
1027 | Static(Static), | ||
1028 | Const(Const), | ||
1029 | Trait(Trait), | ||
1030 | TypeAlias(TypeAlias), | ||
1031 | MacroDef(MacroDef), | ||
1032 | } | ||
1033 | |||
1034 | impl_froms!( | ||
1035 | AttrDef: Module, | ||
1036 | StructField, | ||
1037 | Adt(Struct, Enum, Union), | ||
1038 | EnumVariant, | ||
1039 | Static, | ||
1040 | Const, | ||
1041 | Function, | ||
1042 | Trait, | ||
1043 | TypeAlias, | ||
1044 | MacroDef | ||
1045 | ); | ||
1046 | |||
1047 | pub trait HasAttrs { | ||
1048 | fn attrs(self, db: &impl DefDatabase) -> Attrs; | ||
1049 | } | ||
1050 | |||
1051 | impl<T: Into<AttrDef>> HasAttrs for T { | ||
1052 | fn attrs(self, db: &impl DefDatabase) -> Attrs { | ||
1053 | let def: AttrDef = self.into(); | ||
1054 | db.attrs(def.into()) | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | pub trait Docs { | ||
1059 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>; | ||
1060 | } | ||
1061 | impl<T: Into<AttrDef> + Copy> Docs for T { | ||
1062 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { | ||
1063 | let def: AttrDef = (*self).into(); | ||
1064 | db.documentation(def.into()) | ||
1065 | } | ||
1066 | } | ||