diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 125 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/has_source.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 40 |
5 files changed, 181 insertions, 13 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 1a9f6cc76..a379b9f49 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -26,15 +26,12 @@ use hir_ty::{ | |||
26 | autoderef, | 26 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 27 | display::{HirDisplayError, HirFormatter}, |
28 | expr::ExprValidator, | 28 | expr::ExprValidator, |
29 | method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, | 29 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, |
30 | TyDefId, TypeCtor, | 30 | TraitEnvironment, Ty, TyDefId, TypeCtor, |
31 | }; | 31 | }; |
32 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 32 | use ra_db::{CrateId, CrateName, Edition, FileId}; |
33 | use ra_prof::profile; | 33 | use ra_prof::profile; |
34 | use ra_syntax::{ | 34 | use ra_syntax::ast::{self, AttrsOwner, NameOwner}; |
35 | ast::{self, AttrsOwner, NameOwner}, | ||
36 | AstNode, | ||
37 | }; | ||
38 | use rustc_hash::FxHashSet; | 35 | use rustc_hash::FxHashSet; |
39 | 36 | ||
40 | use crate::{ | 37 | use crate::{ |
@@ -186,10 +183,27 @@ impl ModuleDef { | |||
186 | 183 | ||
187 | module.visibility_of(db, self) | 184 | module.visibility_of(db, self) |
188 | } | 185 | } |
186 | |||
187 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
188 | match self { | ||
189 | ModuleDef::Adt(it) => Some(it.name(db)), | ||
190 | ModuleDef::Trait(it) => Some(it.name(db)), | ||
191 | ModuleDef::Function(it) => Some(it.name(db)), | ||
192 | ModuleDef::EnumVariant(it) => Some(it.name(db)), | ||
193 | ModuleDef::TypeAlias(it) => Some(it.name(db)), | ||
194 | |||
195 | ModuleDef::Module(it) => it.name(db), | ||
196 | ModuleDef::Const(it) => it.name(db), | ||
197 | ModuleDef::Static(it) => it.name(db), | ||
198 | |||
199 | ModuleDef::BuiltinType(it) => Some(it.as_name()), | ||
200 | } | ||
201 | } | ||
189 | } | 202 | } |
190 | 203 | ||
191 | pub use hir_def::{ | 204 | pub use hir_def::{ |
192 | attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, | 205 | attr::Attrs, item_scope::ItemInNs, item_tree::ItemTreeNode, visibility::Visibility, |
206 | AssocItemId, AssocItemLoc, | ||
193 | }; | 207 | }; |
194 | 208 | ||
195 | impl Module { | 209 | impl Module { |
@@ -856,7 +870,7 @@ where | |||
856 | ID: Lookup<Data = AssocItemLoc<AST>>, | 870 | ID: Lookup<Data = AssocItemLoc<AST>>, |
857 | DEF: From<ID>, | 871 | DEF: From<ID>, |
858 | CTOR: FnOnce(DEF) -> AssocItem, | 872 | CTOR: FnOnce(DEF) -> AssocItem, |
859 | AST: AstNode, | 873 | AST: ItemTreeNode, |
860 | { | 874 | { |
861 | match id.lookup(db.upcast()).container { | 875 | match id.lookup(db.upcast()).container { |
862 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | 876 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), |
@@ -1359,6 +1373,27 @@ impl Type { | |||
1359 | Some(adt.into()) | 1373 | Some(adt.into()) |
1360 | } | 1374 | } |
1361 | 1375 | ||
1376 | pub fn as_dyn_trait(&self) -> Option<Trait> { | ||
1377 | self.ty.value.dyn_trait().map(Into::into) | ||
1378 | } | ||
1379 | |||
1380 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | ||
1381 | self.ty.value.impl_trait_bounds(db).map(|it| { | ||
1382 | it.into_iter() | ||
1383 | .filter_map(|pred| match pred { | ||
1384 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1385 | Some(Trait::from(trait_ref.trait_)) | ||
1386 | } | ||
1387 | _ => None, | ||
1388 | }) | ||
1389 | .collect() | ||
1390 | }) | ||
1391 | } | ||
1392 | |||
1393 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1394 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | ||
1395 | } | ||
1396 | |||
1362 | // FIXME: provide required accessors such that it becomes implementable from outside. | 1397 | // FIXME: provide required accessors such that it becomes implementable from outside. |
1363 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | 1398 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { |
1364 | match (&self.ty.value, &other.ty.value) { | 1399 | match (&self.ty.value, &other.ty.value) { |
@@ -1380,6 +1415,80 @@ impl Type { | |||
1380 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | 1415 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, |
1381 | } | 1416 | } |
1382 | } | 1417 | } |
1418 | |||
1419 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | ||
1420 | // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself. | ||
1421 | // We need a different order here. | ||
1422 | |||
1423 | fn walk_substs( | ||
1424 | db: &dyn HirDatabase, | ||
1425 | type_: &Type, | ||
1426 | substs: &Substs, | ||
1427 | cb: &mut impl FnMut(Type), | ||
1428 | ) { | ||
1429 | for ty in substs.iter() { | ||
1430 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1434 | fn walk_bounds( | ||
1435 | db: &dyn HirDatabase, | ||
1436 | type_: &Type, | ||
1437 | bounds: &[GenericPredicate], | ||
1438 | cb: &mut impl FnMut(Type), | ||
1439 | ) { | ||
1440 | for pred in bounds { | ||
1441 | match pred { | ||
1442 | GenericPredicate::Implemented(trait_ref) => { | ||
1443 | cb(type_.clone()); | ||
1444 | walk_substs(db, type_, &trait_ref.substs, cb); | ||
1445 | } | ||
1446 | _ => (), | ||
1447 | } | ||
1448 | } | ||
1449 | } | ||
1450 | |||
1451 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | ||
1452 | let ty = type_.ty.value.strip_references(); | ||
1453 | match ty { | ||
1454 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | ||
1455 | match ctor { | ||
1456 | TypeCtor::Adt(_) => { | ||
1457 | cb(type_.derived(ty.clone())); | ||
1458 | } | ||
1459 | TypeCtor::AssociatedType(_) => { | ||
1460 | if let Some(_) = ty.associated_type_parent_trait(db) { | ||
1461 | cb(type_.derived(ty.clone())); | ||
1462 | } | ||
1463 | } | ||
1464 | _ => (), | ||
1465 | } | ||
1466 | |||
1467 | // adt params, tuples, etc... | ||
1468 | walk_substs(db, type_, parameters, cb); | ||
1469 | } | ||
1470 | Ty::Opaque(opaque_ty) => { | ||
1471 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1472 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1473 | } | ||
1474 | |||
1475 | walk_substs(db, type_, &opaque_ty.parameters, cb); | ||
1476 | } | ||
1477 | Ty::Placeholder(_) => { | ||
1478 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1479 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1480 | } | ||
1481 | } | ||
1482 | Ty::Dyn(bounds) => { | ||
1483 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | ||
1484 | } | ||
1485 | |||
1486 | _ => (), | ||
1487 | } | ||
1488 | } | ||
1489 | |||
1490 | walk_type(db, self, &mut cb); | ||
1491 | } | ||
1383 | } | 1492 | } |
1384 | 1493 | ||
1385 | impl HirDisplay for Type { | 1494 | impl HirDisplay for Type { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index b6b665de1..bb67952de 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -6,7 +6,7 @@ pub use hir_def::db::{ | |||
6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, | 6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, |
7 | InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, | 7 | InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, |
8 | InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, | 8 | InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, |
9 | InternUnionQuery, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, | 9 | InternUnionQuery, ItemTreeQuery, LangItemQuery, ModuleLangItemsQuery, StaticDataQuery, |
10 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | 10 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
@@ -16,7 +16,7 @@ pub use hir_expand::db::{ | |||
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, |
21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, | 21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, |
22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, | 22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, |
diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 63b8fd369..76c32fc17 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir_def::{ | 4 | use hir_def::{ |
5 | nameres::ModuleSource, | 5 | nameres::{ModuleOrigin, ModuleSource}, |
6 | src::{HasChildSource, HasSource as _}, | 6 | src::{HasChildSource, HasSource as _}, |
7 | Lookup, VariantId, | 7 | Lookup, VariantId, |
8 | }; | 8 | }; |
@@ -29,6 +29,14 @@ impl Module { | |||
29 | def_map[self.id.local_id].definition_source(db.upcast()) | 29 | def_map[self.id.local_id].definition_source(db.upcast()) |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn is_mod_rs(self, db: &dyn HirDatabase) -> bool { | ||
33 | let def_map = db.crate_def_map(self.id.krate); | ||
34 | match def_map[self.id.local_id].origin { | ||
35 | ModuleOrigin::File { is_mod_rs, .. } => is_mod_rs, | ||
36 | _ => false, | ||
37 | } | ||
38 | } | ||
39 | |||
32 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 40 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
33 | /// `None` for the crate root. | 41 | /// `None` for the crate root. |
34 | pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> { | 42 | pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> { |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index a232a5856..6a49c424a 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -6,9 +6,9 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
6 | 6 | ||
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, TraitId, | 9 | AsMacroCall, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use ra_db::{FileId, FileRange}; |
@@ -104,6 +104,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
104 | tree | 104 | tree |
105 | } | 105 | } |
106 | 106 | ||
107 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { | ||
108 | let file_id = d.source().file_id; | ||
109 | let root = self.db.parse_or_expand(file_id).unwrap(); | ||
110 | self.cache(root, file_id); | ||
111 | d.ast(self.db) | ||
112 | } | ||
113 | |||
107 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 114 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
108 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 115 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
109 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 116 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
@@ -247,6 +254,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
247 | self.analyze(path.syntax()).resolve_path(self.db, path) | 254 | self.analyze(path.syntax()).resolve_path(self.db, path) |
248 | } | 255 | } |
249 | 256 | ||
257 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { | ||
258 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | ||
259 | } | ||
260 | |||
250 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | 261 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { |
251 | let src = self.find_file(path.syntax().clone()); | 262 | let src = self.find_file(path.syntax().clone()); |
252 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) | 263 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 7c6bbea13..1d6c47103 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -216,13 +216,43 @@ impl SourceAnalyzer { | |||
216 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { | 216 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { |
217 | return Some(PathResolution::AssocItem(assoc.into())); | 217 | return Some(PathResolution::AssocItem(assoc.into())); |
218 | } | 218 | } |
219 | if let Some(VariantId::EnumVariantId(variant)) = | ||
220 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | ||
221 | { | ||
222 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
223 | } | ||
219 | } | 224 | } |
225 | |||
220 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { | 226 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { |
221 | let pat_id = self.pat_id(&path_pat.into())?; | 227 | let pat_id = self.pat_id(&path_pat.into())?; |
222 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { | 228 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { |
223 | return Some(PathResolution::AssocItem(assoc.into())); | 229 | return Some(PathResolution::AssocItem(assoc.into())); |
224 | } | 230 | } |
231 | if let Some(VariantId::EnumVariantId(variant)) = | ||
232 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | ||
233 | { | ||
234 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) { | ||
239 | let expr_id = self.expr_id(db, &rec_lit.into())?; | ||
240 | if let Some(VariantId::EnumVariantId(variant)) = | ||
241 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | ||
242 | { | ||
243 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
244 | } | ||
225 | } | 245 | } |
246 | |||
247 | if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) { | ||
248 | let pat_id = self.pat_id(&rec_pat.into())?; | ||
249 | if let Some(VariantId::EnumVariantId(variant)) = | ||
250 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | ||
251 | { | ||
252 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
253 | } | ||
254 | } | ||
255 | |||
226 | // This must be a normal source file rather than macro file. | 256 | // This must be a normal source file rather than macro file. |
227 | let hir_path = | 257 | let hir_path = |
228 | crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; | 258 | crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; |
@@ -313,6 +343,16 @@ impl SourceAnalyzer { | |||
313 | })?; | 343 | })?; |
314 | Some(macro_call_id.as_file()) | 344 | Some(macro_call_id.as_file()) |
315 | } | 345 | } |
346 | |||
347 | pub(crate) fn resolve_variant( | ||
348 | &self, | ||
349 | db: &dyn HirDatabase, | ||
350 | record_lit: ast::RecordLit, | ||
351 | ) -> Option<VariantId> { | ||
352 | let infer = self.infer.as_ref()?; | ||
353 | let expr_id = self.expr_id(db, &record_lit.into())?; | ||
354 | infer.variant_resolution_for_expr(expr_id) | ||
355 | } | ||
316 | } | 356 | } |
317 | 357 | ||
318 | fn scope_for( | 358 | fn scope_for( |