3901: Add more heuristics for hiding obvious param hints r=matklad a=IceSentry

This will now hide `value`, `pat`, `rhs` and `other`. These words were selected from the std because they are used in commonly used functions with only a single param and are obvious by their use.

It will also hide the hint if the passed param **starts** or end with the param_name. Maybe we could also split on '_' and check if one of the string is the param_name.

I think it would be good to also hide `bytes` if the type is `[u8; n]` but I'm not sure how to get the param type signature.

Closes #3900 



Co-authored-by: IceSentry <c.giguere42@gmail.com>
This commit is contained in:
bors[bot] 2020-04-09 18:07:28 +00:00 committed by GitHub
commit 9635d8bc44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,4 +1,4 @@
//! FIXME: write short doc here
//! This module defines multiple types of inlay hints and their visibility
use hir::{Adt, HirDisplay, Semantics, Type};
use ra_ide_db::RootDatabase;
@ -235,8 +235,7 @@ fn should_show_param_hint(
param_name: &str,
argument: &ast::Expr,
) -> bool {
let argument_string = argument.syntax().to_string();
if param_name.is_empty() || argument_string.ends_with(param_name) {
if param_name.is_empty() || is_argument_similar_to_param(argument, param_name) {
return false;
}
@ -245,14 +244,37 @@ fn should_show_param_hint(
} else {
fn_signature.parameters.len()
};
// avoid displaying hints for common functions like map, filter, etc.
if parameters_len == 1 && (param_name.len() == 1 || param_name == "predicate") {
// or other obvious words used in std
if parameters_len == 1 && is_obvious_param(param_name) {
return false;
}
true
}
fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool {
let argument_string = remove_ref(argument.clone()).syntax().to_string();
argument_string.starts_with(&param_name) || argument_string.ends_with(&param_name)
}
fn remove_ref(expr: ast::Expr) -> ast::Expr {
if let ast::Expr::RefExpr(ref_expr) = &expr {
if let Some(inner) = ref_expr.expr() {
return inner;
}
}
expr
}
fn is_obvious_param(param_name: &str) -> bool {
let is_obvious_param_name = match param_name {
"predicate" | "value" | "pat" | "rhs" | "other" => true,
_ => false,
};
param_name.len() == 1 || is_obvious_param_name
}
fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> {
match expr {
ast::Expr::CallExpr(expr) => {
@ -1059,9 +1081,18 @@ impl Test {
self
}
fn field(self, value: i32) -> Self {
self
}
fn no_hints_expected(&self, _: i32, test_var: i32) {}
}
struct Param {}
fn different_order(param: &Param) {}
fn different_order_mut(param: &mut Param) {}
fn main() {
let container: TestVarContainer = TestVarContainer { test_var: 42 };
let test: Test = Test {};
@ -1069,11 +1100,20 @@ fn main() {
map(22);
filter(33);
let test_processed: Test = test.map(1).filter(2);
let test_processed: Test = test.map(1).filter(2).field(3);
let test_var: i32 = 55;
test_processed.no_hints_expected(22, test_var);
test_processed.no_hints_expected(33, container.test_var);
let param_begin: Param = Param {};
different_order(&param_begin);
different_order(&mut param_begin);
let a: f64 = 7.0;
let b: f64 = 4.0;
let _: f64 = a.div_euclid(b);
let _: f64 = a.abs_sub(b);
}"#,
);