aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-08-19 16:02:50 +0100
committerAleksey Kladov <[email protected]>2020-08-19 16:02:50 +0100
commit61754678fb4923738c91f2702bba6628230dff6e (patch)
tree1affb36a509f8f6460bf35a53a7f7937338ae805
parent73f4fcbd0fa033947421f827e073bceee86e6447 (diff)
Better API factoring around self access modes
-rw-r--r--crates/hir/src/code_model.rs12
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir/src/semantics.rs46
-rw-r--r--crates/ide/src/syntax_highlighting.rs26
4 files changed, 30 insertions, 56 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 68ccedc60..3d92d0c0d 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -12,6 +12,7 @@ use hir_def::{
12 docs::Documentation, 12 docs::Documentation,
13 expr::{BindingAnnotation, Pat, PatId}, 13 expr::{BindingAnnotation, Pat, PatId},
14 import_map, 14 import_map,
15 lang_item::LangItemTarget,
15 path::ModPath, 16 path::ModPath,
16 per_ns::PerNs, 17 per_ns::PerNs,
17 resolver::{HasResolver, Resolver}, 18 resolver::{HasResolver, Resolver},
@@ -36,7 +37,7 @@ use rustc_hash::FxHashSet;
36use stdx::impl_from; 37use stdx::impl_from;
37use syntax::{ 38use syntax::{
38 ast::{self, AttrsOwner, NameOwner}, 39 ast::{self, AttrsOwner, NameOwner},
39 AstNode, 40 AstNode, SmolStr,
40}; 41};
41 42
42use crate::{ 43use crate::{
@@ -1287,6 +1288,15 @@ impl Type {
1287 db.trait_solve(self.krate, goal).is_some() 1288 db.trait_solve(self.krate, goal).is_some()
1288 } 1289 }
1289 1290
1291 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
1292 let lang_item = db.lang_item(self.krate, SmolStr::new("copy"));
1293 let copy_trait = match lang_item {
1294 Some(LangItemTarget::TraitId(it)) => it,
1295 _ => return false,
1296 };
1297 self.impls_trait(db, copy_trait.into(), &[])
1298 }
1299
1290 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { 1300 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1291 let def = match self.ty.value { 1301 let def = match self.ty.value {
1292 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), 1302 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 447e60698..78d8651cb 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -38,7 +38,7 @@ pub use crate::{
38 ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
39 }, 39 },
40 has_source::HasSource, 40 has_source::HasSource,
41 semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
42}; 42};
43 43
44pub use hir_def::{ 44pub use hir_def::{
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index cabeaaf98..8c5f2ff98 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -6,10 +6,8 @@ use std::{cell::RefCell, fmt, iter::successors};
6 6
7use base_db::{FileId, FileRange}; 7use base_db::{FileId, FileRange};
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget,
10 resolver::{self, HasResolver, Resolver, TypeNs}, 9 resolver::{self, HasResolver, Resolver, TypeNs},
11 src::HasSource, 10 AsMacroCall, FunctionId, TraitId, VariantId,
12 AsMacroCall, FunctionId, Lookup, TraitId, VariantId,
13}; 11};
14use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; 12use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
15use hir_ty::associated_type_shorthand_candidates; 13use hir_ty::associated_type_shorthand_candidates;
@@ -17,7 +15,7 @@ use itertools::Itertools;
17use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
18use syntax::{ 16use syntax::{
19 algo::{find_node_at_offset, skip_trivia_token}, 17 algo::{find_node_at_offset, skip_trivia_token},
20 ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize, 18 ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
21}; 19};
22 20
23use crate::{ 21use crate::{
@@ -81,13 +79,6 @@ impl PathResolution {
81 } 79 }
82} 80}
83 81
84pub enum SelfKind {
85 Shared,
86 Mutable,
87 Consuming,
88 Copied,
89}
90
91/// Primary API to get semantic information, like types, from syntax trees. 82/// Primary API to get semantic information, like types, from syntax trees.
92pub struct Semantics<'db, DB> { 83pub struct Semantics<'db, DB> {
93 pub db: &'db DB, 84 pub db: &'db DB,
@@ -197,10 +188,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197 self.imp.type_of_self(param) 188 self.imp.type_of_self(param)
198 } 189 }
199 190
200 pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
201 self.imp.method_receiver_kind(call)
202 }
203
204 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 191 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
205 self.imp.resolve_method_call(call).map(Function::from) 192 self.imp.resolve_method_call(call).map(Function::from)
206 } 193 }
@@ -423,35 +410,6 @@ impl<'db> SemanticsImpl<'db> {
423 self.analyze(param.syntax()).type_of_self(self.db, &param) 410 self.analyze(param.syntax()).type_of_self(self.db, &param)
424 } 411 }
425 412
426 fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
427 self.resolve_method_call(call).and_then(|func| {
428 let lookup = func.lookup(self.db.upcast());
429 let src = lookup.source(self.db.upcast());
430 let param_list = src.value.param_list()?;
431 let self_param = param_list.self_param()?;
432 if self_param.amp_token().is_some() {
433 return Some(if self_param.mut_token().is_some() {
434 SelfKind::Mutable
435 } else {
436 SelfKind::Shared
437 });
438 }
439
440 let ty = self.type_of_expr(&call.expr()?)?;
441 let krate = Function::from(func).krate(self.db)?;
442 let lang_item = self.db.lang_item(krate.id, SmolStr::new("copy"));
443 let copy_trait = match lang_item? {
444 LangItemTarget::TraitId(copy_trait) => Trait::from(copy_trait),
445 _ => return None,
446 };
447 Some(if ty.impls_trait(self.db, copy_trait, &[]) {
448 SelfKind::Copied
449 } else {
450 SelfKind::Consuming
451 })
452 })
453 }
454
455 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 413 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
456 self.analyze(call.syntax()).resolve_method_call(self.db, call) 414 self.analyze(call.syntax()).resolve_method_call(self.db, call)
457 } 415 }
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index fc4f56550..5521fd2b1 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -4,7 +4,7 @@ mod injection;
4#[cfg(test)] 4#[cfg(test)]
5mod tests; 5mod tests;
6 6
7use hir::{Name, SelfKind, Semantics, VariantDef}; 7use hir::{Name, Semantics, VariantDef};
8use ide_db::{ 8use ide_db::{
9 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, 9 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
10 RootDatabase, 10 RootDatabase,
@@ -720,15 +720,21 @@ fn highlight_method_call(
720 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { 720 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
721 h |= HighlightModifier::Unsafe; 721 h |= HighlightModifier::Unsafe;
722 } 722 }
723 723 if let Some(self_param) = func.self_param(sema.db) {
724 sema.method_reciever_kind(&method_call) 724 match self_param.access(sema.db) {
725 .map(|self_kind| match self_kind { 725 hir::Access::Shared => (),
726 SelfKind::Shared => h, 726 hir::Access::Exclusive => h |= HighlightModifier::Mutable,
727 SelfKind::Mutable => h | HighlightModifier::Mutable, 727 hir::Access::Owned => {
728 SelfKind::Consuming => h | HighlightModifier::Consuming, 728 if let Some(receiver_ty) = method_call.expr().and_then(|it| sema.type_of_expr(&it))
729 SelfKind::Copied => h, 729 {
730 }) 730 if !receiver_ty.is_copy(sema.db) {
731 .or_else(|| Some(h)) 731 h |= HighlightModifier::Consuming
732 }
733 }
734 }
735 }
736 }
737 Some(h)
732} 738}
733 739
734fn highlight_name( 740fn highlight_name(