aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/inlay_hints.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-18 17:35:10 +0000
committerAleksey Kladov <[email protected]>2020-02-26 11:55:50 +0000
commitc3a4c4429de83450654795534e64e878a774a088 (patch)
tree12d89798f61b276f8bd640db07276a7d4e92b1c2 /crates/ra_ide/src/inlay_hints.rs
parent04deae3dba7c9b7054f7a1d64e4b93a05aecc132 (diff)
Refactor primary IDE API
This introduces the new type -- Semantics. Semantics maps SyntaxNodes to various semantic info, such as type, name resolution or macro expansions. To do so, Semantics maintains a HashMap which maps every node it saw to the file from which the node originated. This is enough to get all the necessary hir bits just from syntax.
Diffstat (limited to 'crates/ra_ide/src/inlay_hints.rs')
-rw-r--r--crates/ra_ide/src/inlay_hints.rs48
1 files changed, 21 insertions, 27 deletions
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index b42aa1523..35e3f782d 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -1,12 +1,11 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Adt, HirDisplay, SourceAnalyzer, SourceBinder, Type}; 3use hir::{Adt, HirDisplay, Semantics, Type};
4use once_cell::unsync::Lazy;
5use ra_ide_db::RootDatabase; 4use ra_ide_db::RootDatabase;
6use ra_prof::profile; 5use ra_prof::profile;
7use ra_syntax::{ 6use ra_syntax::{
8 ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, 7 ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
9 match_ast, SmolStr, SourceFile, SyntaxNode, TextRange, 8 match_ast, SmolStr, SyntaxNode, TextRange,
10}; 9};
11 10
12use crate::{FileId, FunctionSignature}; 11use crate::{FileId, FunctionSignature};
@@ -27,38 +26,36 @@ pub struct InlayHint {
27pub(crate) fn inlay_hints( 26pub(crate) fn inlay_hints(
28 db: &RootDatabase, 27 db: &RootDatabase,
29 file_id: FileId, 28 file_id: FileId,
30 file: &SourceFile,
31 max_inlay_hint_length: Option<usize>, 29 max_inlay_hint_length: Option<usize>,
32) -> Vec<InlayHint> { 30) -> Vec<InlayHint> {
33 let mut sb = SourceBinder::new(db); 31 let sema = Semantics::new(db);
32 let file = sema.parse(file_id);
34 let mut res = Vec::new(); 33 let mut res = Vec::new();
35 for node in file.syntax().descendants() { 34 for node in file.syntax().descendants() {
36 get_inlay_hints(&mut res, &mut sb, file_id, &node, max_inlay_hint_length); 35 get_inlay_hints(&mut res, &sema, &node, max_inlay_hint_length);
37 } 36 }
38 res 37 res
39} 38}
40 39
41fn get_inlay_hints( 40fn get_inlay_hints(
42 acc: &mut Vec<InlayHint>, 41 acc: &mut Vec<InlayHint>,
43 sb: &mut SourceBinder<RootDatabase>, 42 sema: &Semantics<RootDatabase>,
44 file_id: FileId,
45 node: &SyntaxNode, 43 node: &SyntaxNode,
46 max_inlay_hint_length: Option<usize>, 44 max_inlay_hint_length: Option<usize>,
47) -> Option<()> { 45) -> Option<()> {
48 let _p = profile("get_inlay_hints"); 46 let _p = profile("get_inlay_hints");
49 let db = sb.db; 47 let db = sema.db;
50 let analyzer = Lazy::new(move || sb.analyze(hir::InFile::new(file_id.into(), node), None));
51 match_ast! { 48 match_ast! {
52 match node { 49 match node {
53 ast::CallExpr(it) => { 50 ast::CallExpr(it) => {
54 get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it)); 51 get_param_name_hints(acc, sema, ast::Expr::from(it));
55 }, 52 },
56 ast::MethodCallExpr(it) => { 53 ast::MethodCallExpr(it) => {
57 get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it)); 54 get_param_name_hints(acc, sema, ast::Expr::from(it));
58 }, 55 },
59 ast::BindPat(it) => { 56 ast::BindPat(it) => {
60 let pat = ast::Pat::from(it.clone()); 57 let pat = ast::Pat::from(it.clone());
61 let ty = analyzer.type_of_pat(db, &pat)?; 58 let ty = sema.type_of_pat(&pat)?;
62 59
63 if should_not_display_type_hint(db, &it, &ty) { 60 if should_not_display_type_hint(db, &it, &ty) {
64 return None; 61 return None;
@@ -125,8 +122,7 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_
125 122
126fn get_param_name_hints( 123fn get_param_name_hints(
127 acc: &mut Vec<InlayHint>, 124 acc: &mut Vec<InlayHint>,
128 db: &RootDatabase, 125 sema: &Semantics<RootDatabase>,
129 analyzer: &SourceAnalyzer,
130 expr: ast::Expr, 126 expr: ast::Expr,
131) -> Option<()> { 127) -> Option<()> {
132 let args = match &expr { 128 let args = match &expr {
@@ -138,7 +134,7 @@ fn get_param_name_hints(
138 // we need args len to determine whether to skip or not the &self parameter 134 // we need args len to determine whether to skip or not the &self parameter
139 .collect::<Vec<_>>(); 135 .collect::<Vec<_>>();
140 136
141 let fn_signature = get_fn_signature(db, analyzer, &expr)?; 137 let fn_signature = get_fn_signature(sema, &expr)?;
142 let n_params_to_skip = 138 let n_params_to_skip =
143 if fn_signature.has_self_param && fn_signature.parameter_names.len() > args.len() { 139 if fn_signature.has_self_param && fn_signature.parameter_names.len() > args.len() {
144 1 140 1
@@ -184,28 +180,26 @@ fn should_show_param_hint(
184 true 180 true
185} 181}
186 182
187fn get_fn_signature( 183fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> {
188 db: &RootDatabase,
189 analyzer: &SourceAnalyzer,
190 expr: &ast::Expr,
191) -> Option<FunctionSignature> {
192 match expr { 184 match expr {
193 ast::Expr::CallExpr(expr) => { 185 ast::Expr::CallExpr(expr) => {
194 // FIXME: Type::as_callable is broken for closures 186 // FIXME: Type::as_callable is broken for closures
195 let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; 187 let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?;
196 match callable_def { 188 match callable_def {
197 hir::CallableDef::FunctionId(it) => { 189 hir::CallableDef::FunctionId(it) => {
198 Some(FunctionSignature::from_hir(db, it.into())) 190 Some(FunctionSignature::from_hir(sema.db, it.into()))
191 }
192 hir::CallableDef::StructId(it) => {
193 FunctionSignature::from_struct(sema.db, it.into())
199 } 194 }
200 hir::CallableDef::StructId(it) => FunctionSignature::from_struct(db, it.into()),
201 hir::CallableDef::EnumVariantId(it) => { 195 hir::CallableDef::EnumVariantId(it) => {
202 FunctionSignature::from_enum_variant(db, it.into()) 196 FunctionSignature::from_enum_variant(sema.db, it.into())
203 } 197 }
204 } 198 }
205 } 199 }
206 ast::Expr::MethodCallExpr(expr) => { 200 ast::Expr::MethodCallExpr(expr) => {
207 let fn_def = analyzer.resolve_method_call(&expr)?; 201 let fn_def = sema.resolve_method_call(&expr)?;
208 Some(FunctionSignature::from_hir(db, fn_def)) 202 Some(FunctionSignature::from_hir(sema.db, fn_def))
209 } 203 }
210 _ => None, 204 _ => None,
211 } 205 }