diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-08-19 12:27:02 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-08-19 12:27:02 +0100 |
commit | 529ca7e5e0573e15b23cd0067a691bf1ffebae84 (patch) | |
tree | 0cc09513805718a7c31cadb1776ff4eb865caaef /crates/hir/src | |
parent | c1cfd010096daa85f8acd6f1ea15d92097816e14 (diff) | |
parent | 3456e2eec7c1e18734f8fa41924a83b4c676dc00 (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.rs | 15 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 50 |
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 | ||
44 | pub use hir_def::{ | 44 | pub 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 | ||
7 | use base_db::{FileId, FileRange}; | 7 | use base_db::{FileId, FileRange}; |
8 | use hir_def::{ | 8 | use 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 | }; |
12 | use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; | 14 | use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; |
13 | use hir_ty::associated_type_shorthand_candidates; | 15 | use hir_ty::associated_type_shorthand_candidates; |
@@ -15,7 +17,7 @@ use itertools::Itertools; | |||
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | use syntax::{ | 18 | use 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 | ||
21 | use crate::{ | 23 | use crate::{ |
@@ -79,6 +81,13 @@ impl PathResolution { | |||
79 | } | 81 | } |
80 | } | 82 | } |
81 | 83 | ||
84 | pub 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. |
83 | pub struct Semantics<'db, DB> { | 92 | pub 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, ¶m) | 423 | self.analyze(param.syntax()).type_of_self(self.db, ¶m) |
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| { |