aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-19 12:27:02 +0100
committerGitHub <[email protected]>2020-08-19 12:27:02 +0100
commit529ca7e5e0573e15b23cd0067a691bf1ffebae84 (patch)
tree0cc09513805718a7c31cadb1776ff4eb865caaef /crates/hir/src
parentc1cfd010096daa85f8acd6f1ea15d92097816e14 (diff)
parent3456e2eec7c1e18734f8fa41924a83b4c676dc00 (diff)
Merge #5643
5643: Add new consuming modifier, apply consuming and mutable to methods r=matklad a=Nashenas88 This adds a new `consuming` semantic modifier for syntax highlighters. This also emits `mutable` and `consuming` in two cases: - When a method takes `&mut self`, then it now has `function.mutable` emitted. - When a method takes `self`, and the type of `Self` is not `Copy`, then `function.consuming` is emitted. CC @flodiebold Co-authored-by: Paul Daniel Faria <[email protected]>
Diffstat (limited to 'crates/hir/src')
-rw-r--r--crates/hir/src/code_model.rs15
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir/src/semantics.rs50
3 files changed, 62 insertions, 5 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index c442654dd..31d5276b0 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -670,6 +670,21 @@ impl Function {
670 db.function_data(self.id).has_self_param 670 db.function_data(self.id).has_self_param
671 } 671 }
672 672
673 pub fn mutability_of_self_param(self, db: &dyn HirDatabase) -> Option<Mutability> {
674 let func_data = db.function_data(self.id);
675 if !func_data.has_self_param {
676 return None;
677 }
678
679 func_data.params.first().and_then(|param| {
680 if let TypeRef::Reference(_, mutability) = param {
681 Some(*mutability)
682 } else {
683 None
684 }
685 })
686 }
687
673 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { 688 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> {
674 db.function_data(self.id).params.clone() 689 db.function_data(self.id).params.clone()
675 } 690 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8961ba8fd..fc1c1ccd3 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -38,7 +38,7 @@ pub use crate::{
38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
39 }, 39 },
40 has_source::HasSource, 40 has_source::HasSource,
41 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, SelfKind, 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 c693176fa..aff0e73da 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -6,8 +6,10 @@ 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,
9 resolver::{self, HasResolver, Resolver, TypeNs}, 10 resolver::{self, HasResolver, Resolver, TypeNs},
10 AsMacroCall, FunctionId, TraitId, VariantId, 11 src::HasSource,
12 AsMacroCall, FunctionId, Lookup, TraitId, VariantId,
11}; 13};
12use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; 14use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
13use hir_ty::associated_type_shorthand_candidates; 15use hir_ty::associated_type_shorthand_candidates;
@@ -15,7 +17,7 @@ use itertools::Itertools;
15use rustc_hash::{FxHashMap, FxHashSet}; 17use rustc_hash::{FxHashMap, FxHashSet};
16use syntax::{ 18use syntax::{
17 algo::{find_node_at_offset, skip_trivia_token}, 19 algo::{find_node_at_offset, skip_trivia_token},
18 ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, 20 ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize,
19}; 21};
20 22
21use crate::{ 23use crate::{
@@ -79,6 +81,13 @@ impl PathResolution {
79 } 81 }
80} 82}
81 83
84pub enum SelfKind {
85 Shared,
86 Mutable,
87 Consuming,
88 Copied,
89}
90
82/// Primary API to get semantic information, like types, from syntax trees. 91/// Primary API to get semantic information, like types, from syntax trees.
83pub struct Semantics<'db, DB> { 92pub struct Semantics<'db, DB> {
84 pub db: &'db DB, 93 pub db: &'db DB,
@@ -188,6 +197,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
188 self.imp.type_of_self(param) 197 self.imp.type_of_self(param)
189 } 198 }
190 199
200 pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
201 self.imp.method_receiver_kind(call)
202 }
203
191 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 204 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
192 self.imp.resolve_method_call(call).map(Function::from) 205 self.imp.resolve_method_call(call).map(Function::from)
193 } 206 }
@@ -267,7 +280,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
267 self.imp.assert_contains_node(node) 280 self.imp.assert_contains_node(node)
268 } 281 }
269 282
270 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { 283 pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
271 self.imp.is_unsafe_method_call(method_call_expr) 284 self.imp.is_unsafe_method_call(method_call_expr)
272 } 285 }
273 286
@@ -410,6 +423,35 @@ impl<'db> SemanticsImpl<'db> {
410 self.analyze(param.syntax()).type_of_self(self.db, &param) 423 self.analyze(param.syntax()).type_of_self(self.db, &param)
411 } 424 }
412 425
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
413 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 455 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
414 self.analyze(call.syntax()).resolve_method_call(self.db, call) 456 self.analyze(call.syntax()).resolve_method_call(self.db, call)
415 } 457 }
@@ -571,7 +613,7 @@ impl<'db> SemanticsImpl<'db> {
571 InFile::new(file_id, node) 613 InFile::new(file_id, node)
572 } 614 }
573 615
574 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { 616 pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
575 method_call_expr 617 method_call_expr
576 .expr() 618 .expr()
577 .and_then(|expr| { 619 .and_then(|expr| {