Skip to content

Commit 2dd2caf

Browse files
committed
WIP
1 parent 3b35880 commit 2dd2caf

11 files changed

+57
-32
lines changed

crates/ra_assists/src/handlers/auto_import.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl AutoImportAssets {
7878

7979
fn for_method_call(method_call: ast::MethodCallExpr, ctx: &AssistCtx) -> Option<Self> {
8080
let syntax_under_caret = method_call.syntax().to_owned();
81-
let module_with_name_to_import = ctx.sema.containing_module(&syntax_under_caret)?;
81+
let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?;
8282
Some(Self {
8383
import_candidate: ImportCandidate::for_method_call(&ctx.sema, &method_call)?,
8484
module_with_name_to_import,
@@ -92,7 +92,7 @@ impl AutoImportAssets {
9292
return None;
9393
}
9494

95-
let module_with_name_to_import = ctx.sema.containing_module(&syntax_under_caret)?;
95+
let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?;
9696
Some(Self {
9797
import_candidate: ImportCandidate::for_regular_path(&ctx.sema, &path_under_caret)?,
9898
module_with_name_to_import,

crates/ra_assists/src/handlers/fill_match_arms.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> {
4848

4949
let expr = match_expr.expr()?;
5050
let enum_def = resolve_enum_def(&ctx.sema, &expr)?;
51-
let module = ctx.sema.containing_module(expr.syntax())?;
51+
let module = ctx.sema.scope(expr.syntax()).module()?;
5252

5353
let variants = enum_def.variants(ctx.db);
5454
if variants.is_empty() {

crates/ra_hir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub use crate::{
4646
StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef,
4747
},
4848
has_source::HasSource,
49-
semantics::Semantics,
49+
semantics::{Semantics, SemanticsScope},
5050
source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
5151
source_binder::SourceBinder,
5252
};

crates/ra_hir/src/semantics.rs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ use std::{cell::RefCell, fmt, iter::successors};
22

33
use ra_db::{FileId, FileRange};
44
use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange};
5-
use rustc_hash::FxHashMap;
5+
use rustc_hash::{FxHashMap, FxHashSet};
66

77
use crate::{
88
db::HirDatabase, source_analyzer::ReferenceDescriptor, source_binder::ToDef, Function,
9-
HirFileId, InFile, MacroDef, Module, Origin, PathResolution, SourceAnalyzer, SourceBinder,
10-
StructField, Type, VariantDef,
9+
HirFileId, InFile, MacroDef, Module, Name, Origin, PathResolution, ScopeDef, SourceAnalyzer,
10+
SourceBinder, StructField, Type, VariantDef,
1111
};
12+
use hir_def::TraitId;
1213

13-
pub struct Semantics<'a, DB> {
14-
pub db: &'a DB,
15-
sb: RefCell<SourceBinder<'a, DB>>,
14+
pub struct Semantics<'db, DB> {
15+
pub db: &'db DB,
16+
sb: RefCell<SourceBinder<'db, DB>>,
1617
cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
1718
}
1819

@@ -22,7 +23,7 @@ impl<DB> fmt::Debug for Semantics<'_, DB> {
2223
}
2324
}
2425

25-
impl<DB: HirDatabase> Semantics<'_, DB> {
26+
impl<'db, DB: HirDatabase> Semantics<'db, DB> {
2627
pub fn new(db: &DB) -> Semantics<DB> {
2728
let sb = RefCell::new(SourceBinder::new(db));
2829
Semantics { db, sb, cache: RefCell::default() }
@@ -177,9 +178,8 @@ impl<DB: HirDatabase> Semantics<'_, DB> {
177178
sb.to_module_def(file)
178179
}
179180

180-
pub fn containing_module(&self, node: &SyntaxNode) -> Option<Module> {
181-
let src = self.find_file(node.clone());
182-
self.sb.borrow_mut().analyze(src.as_ref(), None).module()
181+
pub fn scope<'a>(&'a self, node: &SyntaxNode) -> SemanticsScope<'a, 'db, DB> {
182+
SemanticsScope { sema: self, node: node.clone() }
183183
}
184184

185185
// FIXME: we only use this in `inline_local_variable` assist, ideally, we
@@ -235,3 +235,28 @@ impl<DB: HirDatabase> Semantics<'_, DB> {
235235
fn find_root(node: &SyntaxNode) -> SyntaxNode {
236236
node.ancestors().last().unwrap()
237237
}
238+
239+
pub struct SemanticsScope<'a, 'db, DB> {
240+
sema: &'a Semantics<'db, DB>,
241+
node: SyntaxNode,
242+
}
243+
244+
impl<'a, 'b, DB: HirDatabase> SemanticsScope<'a, 'b, DB> {
245+
pub fn module(&self) -> Option<Module> {
246+
let src = self.sema.find_file(self.node.clone());
247+
self.sema.sb.borrow_mut().analyze(src.as_ref(), None).module()
248+
}
249+
250+
/// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
251+
// FIXME: rename to visible_traits
252+
pub fn traits_in_scope(&self) -> FxHashSet<TraitId> {
253+
let src = self.sema.find_file(self.node.clone());
254+
self.sema.sb.borrow_mut().analyze(src.as_ref(), None).traits_in_scope(self.sema.db)
255+
}
256+
257+
pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
258+
let src = self.sema.find_file(self.node.clone());
259+
let analyzer = self.sema.sb.borrow_mut().analyze(src.as_ref(), None);
260+
analyzer.process_all_names(self.sema.db, f)
261+
}
262+
}

crates/ra_ide/src/completion/complete_dot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
5555
fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
5656
if let Some(krate) = ctx.module.map(|it| it.krate()) {
5757
let mut seen_methods = FxHashSet::default();
58-
let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
58+
let traits_in_scope = ctx.scope().traits_in_scope();
5959
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
6060
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
6161
acc.add_function(ctx, func);

crates/ra_ide/src/completion/complete_macro_in_item_position.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::completion::{CompletionContext, Completions};
55
pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
66
// Show only macros in top level.
77
if ctx.is_new_item {
8-
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
8+
ctx.scope().process_all_names(&mut |name, res| {
99
if let hir::ScopeDef::MacroDef(mac) = res {
1010
acc.add_macro(ctx, Some(name.to_string()), mac);
1111
}

crates/ra_ide/src/completion/complete_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
4949
// FIXME: complete T::AssocType
5050
let krate = ctx.module.map(|m| m.krate());
5151
if let Some(krate) = krate {
52-
let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
52+
let traits_in_scope = ctx.scope().traits_in_scope();
5353
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
5454
match item {
5555
hir::AssocItem::Function(func) => {

crates/ra_ide/src/completion/complete_pattern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
99
}
1010
// FIXME: ideally, we should look at the type we are matching against and
1111
// suggest variants + auto-imports
12-
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
12+
ctx.scope().process_all_names(&mut |name, res| {
1313
let def = match &res {
1414
hir::ScopeDef::ModuleDef(def) => def,
1515
_ => return,

crates/ra_ide/src/completion/complete_scope.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
77
return;
88
}
99

10-
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
11-
acc.add_resolution(ctx, name.to_string(), &res)
12-
});
10+
ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res));
1311
}
1412

1513
#[cfg(test)]

crates/ra_ide/src/completion/completion_context.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! FIXME: write short doc here
22
3-
use hir::Semantics;
3+
use hir::{Semantics, SemanticsScope};
44
use ra_db::SourceDatabase;
55
use ra_ide_db::RootDatabase;
66
use ra_syntax::{
77
algo::{find_covering_element, find_node_at_offset},
8-
ast, AstNode, Parse, SourceFile,
8+
ast, AstNode, SourceFile,
99
SyntaxKind::*,
1010
SyntaxNode, SyntaxToken, TextRange, TextUnit,
1111
};
@@ -19,7 +19,7 @@ use crate::FilePosition;
1919
pub(crate) struct CompletionContext<'a> {
2020
pub(super) sema: Semantics<'a, RootDatabase>,
2121
pub(super) db: &'a RootDatabase,
22-
pub(super) analyzer: hir::SourceAnalyzer,
22+
pub(crate) analyzer: hir::SourceAnalyzer,
2323
pub(super) offset: TextUnit,
2424
pub(super) token: SyntaxToken,
2525
pub(super) module: Option<hir::Module>,
@@ -115,6 +115,11 @@ impl<'a> CompletionContext<'a> {
115115
}
116116
}
117117

118+
pub(crate) fn scope(&self) -> SemanticsScope<'_, 'a, RootDatabase> {
119+
// TODO: don't forget the offset
120+
self.sema.scope(&self.token.parent())
121+
}
122+
118123
fn fill(
119124
&mut self,
120125
original_file: &ast::SourceFile,

crates/ra_ide/src/hover.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! FIXME: write short doc here
22
33
use hir::{Adt, HasSource, HirDisplay, Semantics};
4-
use ra_db::SourceDatabase;
54
use ra_ide_db::{
65
defs::{classify_name, NameDefinition},
76
RootDatabase,
@@ -198,19 +197,17 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
198197
}
199198

200199
pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
201-
let parse = db.parse(frange.file_id);
202-
let leaf_node = find_covering_element(parse.tree().syntax(), frange.range);
200+
let sema = Semantics::new(db);
201+
let source_file = sema.file_syntax(frange.file_id);
202+
let leaf_node = find_covering_element(source_file.syntax(), frange.range);
203203
// if we picked identifier, expand to pattern/expression
204204
let node = leaf_node
205205
.ancestors()
206206
.take_while(|it| it.text_range() == leaf_node.text_range())
207207
.find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?;
208-
let analyzer =
209-
hir::SourceAnalyzer::new(db, hir::InFile::new(frange.file_id.into(), &node), None);
210-
let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
211-
{
208+
let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| sema.type_of_expr(&e)) {
212209
ty
213-
} else if let Some(ty) = ast::Pat::cast(node).and_then(|p| analyzer.type_of_pat(db, &p)) {
210+
} else if let Some(ty) = ast::Pat::cast(node).and_then(|p| sema.type_of_pat(&p)) {
214211
ty
215212
} else {
216213
return None;

0 commit comments

Comments
 (0)