Less lifetines: derive SemanticsScope in place

This commit is contained in:
Kirill Bulatov 2021-03-08 00:25:45 +02:00
parent db61d4ea13
commit dccbb38d2e
7 changed files with 49 additions and 50 deletions

View file

@ -774,7 +774,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
/// ///
/// Note that if you are wondering "what does this specific existing name mean?", /// Note that if you are wondering "what does this specific existing name mean?",
/// you'd better use the `resolve_` family of methods. /// you'd better use the `resolve_` family of methods.
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct SemanticsScope<'a> { pub struct SemanticsScope<'a> {
pub db: &'a dyn HirDatabase, pub db: &'a dyn HirDatabase,
file_id: HirFileId, file_id: HirFileId,

View file

@ -112,9 +112,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
Some(()) Some(())
} }
pub(super) fn find_importable_node<'a>( pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets, SyntaxNode)> {
ctx: &'a AssistContext,
) -> Option<(ImportAssets<'a>, SyntaxNode)> {
if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
ImportAssets::for_exact_path(&path_under_caret, &ctx.sema) ImportAssets::for_exact_path(&path_under_caret, &ctx.sema)
.zip(Some(path_under_caret.syntax().clone())) .zip(Some(path_under_caret.syntax().clone()))

View file

@ -65,11 +65,8 @@ pub(crate) fn replace_derive_with_manual_impl(
let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; let current_module = ctx.sema.scope(annotated_name.syntax()).module()?;
let current_crate = current_module.krate(); let current_crate = current_module.krate();
let found_traits = items_locator::with_for_exact_name( let found_traits =
&ctx.sema, items_locator::with_exact_name(&ctx.sema, current_crate, trait_token.text().to_string())
current_crate,
trait_token.text().to_string(),
)
.into_iter() .into_iter()
.filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) {
ModuleDef::Trait(trait_) => Some(trait_), ModuleDef::Trait(trait_) => Some(trait_),

View file

@ -169,23 +169,28 @@ pub(crate) fn position_for_import<'a>(
}) })
} }
fn import_assets<'a>(ctx: &'a CompletionContext, fuzzy_name: String) -> Option<ImportAssets<'a>> { fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
let current_module = ctx.scope.module()?; let current_module = ctx.scope.module()?;
if let Some(dot_receiver) = &ctx.dot_receiver { if let Some(dot_receiver) = &ctx.dot_receiver {
ImportAssets::for_fuzzy_method_call( ImportAssets::for_fuzzy_method_call(
current_module, current_module,
ctx.sema.type_of_expr(dot_receiver)?, ctx.sema.type_of_expr(dot_receiver)?,
fuzzy_name, fuzzy_name,
ctx.scope.clone(), dot_receiver.syntax().clone(),
) )
} else { } else {
let fuzzy_name_length = fuzzy_name.len(); let fuzzy_name_length = fuzzy_name.len();
let approximate_node = match current_module.definition_source(ctx.db).value {
hir::ModuleSource::SourceFile(s) => s.syntax().clone(),
hir::ModuleSource::Module(m) => m.syntax().clone(),
hir::ModuleSource::BlockExpr(b) => b.syntax().clone(),
};
let assets_for_path = ImportAssets::for_fuzzy_path( let assets_for_path = ImportAssets::for_fuzzy_path(
current_module, current_module,
ctx.path_qual.clone(), ctx.path_qual.clone(),
fuzzy_name, fuzzy_name,
&ctx.sema, &ctx.sema,
ctx.scope.clone(), approximate_node,
)?; )?;
if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_)) if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_))

View file

@ -150,7 +150,7 @@ pub fn resolve_completion_edits(
let current_crate = current_module.krate(); let current_crate = current_module.krate();
let (import_path, item_to_import) = let (import_path, item_to_import) =
items_locator::with_for_exact_name(&ctx.sema, current_crate, imported_name) items_locator::with_exact_name(&ctx.sema, current_crate, imported_name)
.into_iter() .into_iter()
.filter_map(|candidate| { .filter_map(|candidate| {
current_module current_module

View file

@ -1,11 +1,11 @@
//! Look up accessible paths for items. //! Look up accessible paths for items.
use hir::{ use hir::{
AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module, AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, Type,
}; };
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use syntax::{ast, AstNode}; use syntax::{ast, AstNode, SyntaxNode};
use crate::{ use crate::{
items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT}, items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
@ -62,38 +62,37 @@ impl NameToImport {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ImportAssets<'a> { pub struct ImportAssets {
import_candidate: ImportCandidate, import_candidate: ImportCandidate,
candidate_node: SyntaxNode,
module_with_candidate: Module, module_with_candidate: Module,
scope: SemanticsScope<'a>,
} }
impl<'a> ImportAssets<'a> { impl ImportAssets {
pub fn for_method_call( pub fn for_method_call(
method_call: &ast::MethodCallExpr, method_call: &ast::MethodCallExpr,
sema: &'a Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
) -> Option<Self> { ) -> Option<Self> {
let scope = sema.scope(method_call.syntax()); let candidate_node = method_call.syntax().clone();
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_method_call(sema, method_call)?, import_candidate: ImportCandidate::for_method_call(sema, method_call)?,
module_with_candidate: scope.module()?, module_with_candidate: sema.scope(&candidate_node).module()?,
scope, candidate_node,
}) })
} }
pub fn for_exact_path( pub fn for_exact_path(
fully_qualified_path: &ast::Path, fully_qualified_path: &ast::Path,
sema: &'a Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
) -> Option<Self> { ) -> Option<Self> {
let syntax_under_caret = fully_qualified_path.syntax(); let candidate_node = fully_qualified_path.syntax().clone();
if syntax_under_caret.ancestors().find_map(ast::Use::cast).is_some() { if candidate_node.ancestors().find_map(ast::Use::cast).is_some() {
return None; return None;
} }
let scope = sema.scope(syntax_under_caret);
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_regular_path(sema, fully_qualified_path)?, import_candidate: ImportCandidate::for_regular_path(sema, fully_qualified_path)?,
module_with_candidate: scope.module()?, module_with_candidate: sema.scope(&candidate_node).module()?,
scope, candidate_node,
}) })
} }
@ -102,12 +101,12 @@ impl<'a> ImportAssets<'a> {
qualifier: Option<ast::Path>, qualifier: Option<ast::Path>,
fuzzy_name: String, fuzzy_name: String,
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
scope: SemanticsScope<'a>, candidate_node: SyntaxNode,
) -> Option<Self> { ) -> Option<Self> {
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_fuzzy_path(qualifier, fuzzy_name, sema)?, import_candidate: ImportCandidate::for_fuzzy_path(qualifier, fuzzy_name, sema)?,
module_with_candidate, module_with_candidate,
scope, candidate_node,
}) })
} }
@ -115,7 +114,7 @@ impl<'a> ImportAssets<'a> {
module_with_method_call: Module, module_with_method_call: Module,
receiver_ty: Type, receiver_ty: Type,
fuzzy_method_name: String, fuzzy_method_name: String,
scope: SemanticsScope<'a>, candidate_node: SyntaxNode,
) -> Option<Self> { ) -> Option<Self> {
Some(Self { Some(Self {
import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate { import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate {
@ -123,7 +122,7 @@ impl<'a> ImportAssets<'a> {
name: NameToImport::Fuzzy(fuzzy_method_name), name: NameToImport::Fuzzy(fuzzy_method_name),
}), }),
module_with_candidate: module_with_method_call, module_with_candidate: module_with_method_call,
scope, candidate_node,
}) })
} }
} }
@ -156,7 +155,7 @@ impl LocatedImport {
} }
} }
impl<'a> ImportAssets<'a> { impl ImportAssets {
pub fn import_candidate(&self) -> &ImportCandidate { pub fn import_candidate(&self) -> &ImportCandidate {
&self.import_candidate &self.import_candidate
} }
@ -182,7 +181,7 @@ impl<'a> ImportAssets<'a> {
prefixed: Option<PrefixKind>, prefixed: Option<PrefixKind>,
) -> Vec<LocatedImport> { ) -> Vec<LocatedImport> {
let items_with_candidate_name = match self.name_to_import() { let items_with_candidate_name = match self.name_to_import() {
NameToImport::Exact(exact_name) => items_locator::with_for_exact_name( NameToImport::Exact(exact_name) => items_locator::with_exact_name(
sema, sema,
self.module_with_candidate.krate(), self.module_with_candidate.krate(),
exact_name.clone(), exact_name.clone(),
@ -209,7 +208,7 @@ impl<'a> ImportAssets<'a> {
} }
}; };
let scope_definitions = self.scope_definitions(); let scope_definitions = self.scope_definitions(sema);
self.applicable_defs(sema.db, prefixed, items_with_candidate_name) self.applicable_defs(sema.db, prefixed, items_with_candidate_name)
.into_iter() .into_iter()
.filter(|import| import.import_path.len() > 1) .filter(|import| import.import_path.len() > 1)
@ -218,9 +217,9 @@ impl<'a> ImportAssets<'a> {
.collect() .collect()
} }
fn scope_definitions(&self) -> FxHashSet<ScopeDef> { fn scope_definitions(&self, sema: &Semantics<RootDatabase>) -> FxHashSet<ScopeDef> {
let mut scope_definitions = FxHashSet::default(); let mut scope_definitions = FxHashSet::default();
self.scope.process_all_names(&mut |_, scope_def| { sema.scope(&self.candidate_node).process_all_names(&mut |_, scope_def| {
scope_definitions.insert(scope_def); scope_definitions.insert(scope_def);
}); });
scope_definitions scope_definitions

View file

@ -17,7 +17,7 @@ use rustc_hash::FxHashSet;
pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40;
pub fn with_for_exact_name( pub fn with_exact_name(
sema: &Semantics<'_, RootDatabase>, sema: &Semantics<'_, RootDatabase>,
krate: Crate, krate: Crate,
exact_name: String, exact_name: String,