From 5208c2aa930ae452e062dcdc2563c1bbb67d2e4a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 19 Jan 2019 21:23:26 +0100 Subject: Sketching the resolver API --- crates/ra_hir/src/code_model_api.rs | 15 +++- crates/ra_hir/src/code_model_impl/function.rs | 6 +- crates/ra_hir/src/expr.rs | 11 ++- crates/ra_hir/src/expr/scope.rs | 2 + crates/ra_hir/src/lib.rs | 2 + crates/ra_hir/src/nameres.rs | 2 +- crates/ra_hir/src/resolve.rs | 100 ++++++++++++++++++++++++++ crates/ra_hir/src/source_binder.rs | 7 +- 8 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 crates/ra_hir/src/resolve.rs (limited to 'crates') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 71123a698..73541a8c3 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -9,14 +9,15 @@ use crate::{ type_ref::TypeRef, nameres::{ModuleScope, lower::ImportId}, HirDatabase, PersistentHirDatabase, - expr::BodySyntaxMapping, - ty::{InferenceResult}, + expr::{Body, BodySyntaxMapping}, + ty::InferenceResult, adt::{EnumVariantId, StructFieldId, VariantDef}, generics::GenericParams, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, impl_block::ImplId, + resolve::Resolver, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -175,12 +176,18 @@ impl Module { } pub fn resolve_path(&self, db: &impl PersistentHirDatabase, path: &Path) -> PerNs { + // TODO replace by Resolver::resolve_path db.item_map(self.krate).resolve_path(db, *self, path) } pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc, Problem)> { self.problems_impl(db) } + + #[allow(unused_variables)] + pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + unimplemented!() + } } impl Docs for Module { @@ -449,6 +456,10 @@ impl Function { db.body_syntax_mapping(*self) } + pub fn body(&self, db: &impl HirDatabase) -> Arc { + db.body_hir(*self) + } + pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { let scopes = db.expr_scopes(*self); let syntax_mapping = db.body_syntax_mapping(*self); diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index 5b0b31b1d..8326c02c7 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -5,14 +5,12 @@ use ra_syntax::ast::{self, NameOwner}; use crate::{ HirDatabase, Name, AsName, Function, FnSignature, type_ref::{TypeRef, Mutability}, - expr::Body, PersistentHirDatabase, + PersistentHirDatabase, impl_block::ImplBlock, }; impl Function { - pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc { - db.body_hir(*self) - } + // TODO impl_block should probably also be part of the code model API? /// The containing impl block, if this is a method. pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option { diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index f4a950418..6d124fe2f 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -10,15 +10,15 @@ use ra_syntax::{ }; use crate::{ - Path, Name, Function, - name::AsName, HirDatabase, + Path, Name, HirDatabase, Function, Resolver, + name::AsName, type_ref::{Mutability, TypeRef}, }; use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; -mod scope; +pub(crate) mod scope; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ExprId(RawId); @@ -62,6 +62,11 @@ impl Body { pub fn body_expr(&self) -> ExprId { self.body_expr } + + #[allow(unused_variables)] + pub fn resolver_for_expr(&self, expr_id: ExprId) -> Resolver { + unimplemented!() + } } impl Index for Body { diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index b7971088d..504a087a3 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -73,6 +73,7 @@ impl ExprScopes { context_expr: ExprId, name: Name, ) -> Option<&'a ScopeEntry> { + // TODO replace by Resolver::resolve_name let mut shadowed = FxHashSet::default(); let ret = self .scope_chain_for(context_expr) @@ -179,6 +180,7 @@ impl ScopesWithSyntaxMapping { // XXX: during completion, cursor might be outside of any particular // expression. Try to figure out the correct scope... + // TODO: move this to source binder? fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { let r = ptr.range(); let child_scopes = self diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 905c53c7d..e58658378 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -36,6 +36,7 @@ mod impl_block; mod expr; mod generics; mod docs; +mod resolve; mod code_model_api; mod code_model_impl; @@ -60,6 +61,7 @@ pub use self::{ docs::{Docs, Documentation}, adt::AdtDef, expr::{ExprScopes, ScopesWithSyntaxMapping}, + resolve::Resolver, }; pub use self::code_model_api::{ diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index f8627acbe..e825ec089 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -30,7 +30,7 @@ use crate::{ nameres::lower::{ImportId, LoweredModule, ImportData}, }; -/// `ItemMap` is the result of name resolution. It contains, for each +/// `ItemMap` is the result of module name resolution. It contains, for each /// module, the set of visible items. #[derive(Default, Debug, PartialEq, Eq)] pub struct ItemMap { diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs new file mode 100644 index 000000000..41fcb35bc --- /dev/null +++ b/crates/ra_hir/src/resolve.rs @@ -0,0 +1,100 @@ +#![allow(unused_variables, dead_code)] +//! Name resolution. +use std::sync::Arc; + +use rustc_hash::FxHashMap; + +use crate::{ + ModuleDef, + name::Name, + nameres::{PerNs, lower::ImportId, ItemMap}, + module_tree::ModuleId, + generics::GenericParams, + expr::{Body, scope::{ExprScopes, ScopeId}, PatId}, + impl_block::ImplBlock, + path::Path, +}; + +#[derive(Debug, Clone)] +pub struct Resolver { + scopes: Vec, // maybe a 'linked list' of scopes? or allow linking a Resolver to a parent Resolver? that's an optimization that might not be necessary, though +} + +// TODO how to store these best +#[derive(Debug, Clone)] +pub(crate) struct ModuleItemMap { + item_map: Arc, + module_id: ModuleId, +} + +#[derive(Debug, Clone)] +pub(crate) struct ExprScope { + expr_scopes: Arc, + scope_id: ScopeId, +} + +#[derive(Debug, Clone)] +pub(crate) enum Scope { + /// All the items and imported names of a module + ModuleScope(ModuleItemMap), + /// Brings the generic parameters of an item into scope + GenericParams(Arc), + /// Brings the function parameters into scope + FunctionParams(Arc), + /// Brings `Self` into scope + ImplBlockScope(ImplBlock), + /// Local bindings + ExprScope(ExprScope), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Resolution { + /// An item + Def { + def: ModuleDef, + import: Option, + }, + /// A local binding (only value namespace) + LocalBinding { pat: PatId }, + /// A generic parameter + GenericParam { idx: u32 }, + // TODO how does `Self` resolve? +} + +impl Resolver { + pub fn resolve_name(&self, name: &Name) -> PerNs { + for scope in self.scopes.iter().rev() { + let resolution = scope.resolve_name(name); + if !resolution.is_none() { + return resolution; + } + } + PerNs::none() + } + + pub fn resolve_path(&self, path: &Path) -> PerNs { + unimplemented!() + } + + pub fn all_names(&self) -> FxHashMap { + unimplemented!() + } +} + +impl Resolver { + pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver { + self.scopes.push(scope); + self + } + + pub(crate) fn pop_scope(mut self) -> Resolver { + self.scopes.pop(); + self + } +} + +impl Scope { + fn resolve_name(&self, name: &Name) -> PerNs { + unimplemented!() + } +} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a1b94ed9c..1fdd7d087 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -14,7 +14,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, ModuleDef, Struct, Enum, - AsName, Module, HirFileId, Crate, Trait, + AsName, Module, HirFileId, Crate, Trait, Resolver, ids::{LocationCtx, SourceFileItemId}, }; @@ -201,3 +201,8 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te res } + +#[allow(unused_variables)] +pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { + unimplemented!() +} -- cgit v1.2.3