From a044ff0138d6bff9406b94de89fde43e7672ee1b Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 30 Jul 2020 11:07:13 -0400 Subject: Mark mutating functions with `mutable` modifier, and owning functions with `consuming`. --- crates/hir/src/code_model.rs | 15 +++++++++++++++ crates/hir/src/semantics.rs | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'crates/hir/src') 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 { db.function_data(self.id).has_self_param } + pub fn mutability_of_self_param(self, db: &dyn HirDatabase) -> Option { + let func_data = db.function_data(self.id); + if !func_data.has_self_param { + return None; + } + + func_data.params.first().and_then(|param| { + if let TypeRef::Reference(_, mutability) = param { + Some(*mutability) + } else { + None + } + }) + } + pub fn params(self, db: &dyn HirDatabase) -> Vec { db.function_data(self.id).params.clone() } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index c693176fa..9f23315c3 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -267,7 +267,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.assert_contains_node(node) } - pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { + pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { self.imp.is_unsafe_method_call(method_call_expr) } @@ -571,7 +571,7 @@ impl<'db> SemanticsImpl<'db> { InFile::new(file_id, node) } - pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { + pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { method_call_expr .expr() .and_then(|expr| { -- cgit v1.2.3 From 3456e2eec7c1e18734f8fa41924a83b4c676dc00 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 30 Jul 2020 22:31:53 -0400 Subject: Add new method to Semantics, method_receiver_kind, which returns the kind of self The options are Shared, Mutable, Consuming, and Copied. Use this to add proper highlighting to methods based on usage. --- crates/hir/src/lib.rs | 2 +- crates/hir/src/semantics.rs | 46 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'crates/hir/src') 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::{ Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, }, has_source::HasSource, - semantics::{original_range, PathResolution, Semantics, SemanticsScope}, + semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope}, }; pub use hir_def::{ diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 9f23315c3..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}; use base_db::{FileId, FileRange}; use hir_def::{ + lang_item::LangItemTarget, resolver::{self, HasResolver, Resolver, TypeNs}, - AsMacroCall, FunctionId, TraitId, VariantId, + src::HasSource, + AsMacroCall, FunctionId, Lookup, TraitId, VariantId, }; use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; use hir_ty::associated_type_shorthand_candidates; @@ -15,7 +17,7 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ algo::{find_node_at_offset, skip_trivia_token}, - ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, + ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize, }; use crate::{ @@ -79,6 +81,13 @@ impl PathResolution { } } +pub enum SelfKind { + Shared, + Mutable, + Consuming, + Copied, +} + /// Primary API to get semantic information, like types, from syntax trees. pub struct Semantics<'db, DB> { pub db: &'db DB, @@ -188,6 +197,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.type_of_self(param) } + pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option { + self.imp.method_receiver_kind(call) + } + pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { self.imp.resolve_method_call(call).map(Function::from) } @@ -410,6 +423,35 @@ impl<'db> SemanticsImpl<'db> { self.analyze(param.syntax()).type_of_self(self.db, ¶m) } + fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option { + self.resolve_method_call(call).and_then(|func| { + let lookup = func.lookup(self.db.upcast()); + let src = lookup.source(self.db.upcast()); + let param_list = src.value.param_list()?; + let self_param = param_list.self_param()?; + if self_param.amp_token().is_some() { + return Some(if self_param.mut_token().is_some() { + SelfKind::Mutable + } else { + SelfKind::Shared + }); + } + + let ty = self.type_of_expr(&call.expr()?)?; + let krate = Function::from(func).krate(self.db)?; + let lang_item = self.db.lang_item(krate.id, SmolStr::new("copy")); + let copy_trait = match lang_item? { + LangItemTarget::TraitId(copy_trait) => Trait::from(copy_trait), + _ => return None, + }; + Some(if ty.impls_trait(self.db, copy_trait, &[]) { + SelfKind::Copied + } else { + SelfKind::Consuming + }) + }) + } + fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { self.analyze(call.syntax()).resolve_method_call(self.db, call) } -- cgit v1.2.3