2020-02-18 17:35:10 +00:00
use hir ::{ Adt , HirDisplay , Semantics , Type } ;
2020-02-06 11:52:32 +00:00
use ra_ide_db ::RootDatabase ;
2019-12-21 17:45:46 +00:00
use ra_prof ::profile ;
2019-07-19 21:20:09 +00:00
use ra_syntax ::{
2020-01-14 17:02:01 +00:00
ast ::{ self , ArgListOwner , AstNode , TypeAscriptionOwner } ,
2020-03-24 19:31:02 +00:00
match_ast , Direction , NodeOrToken , SmolStr , SyntaxKind , TextRange ,
2019-07-19 21:20:09 +00:00
} ;
2020-02-06 11:52:32 +00:00
use crate ::{ FileId , FunctionSignature } ;
2020-05-03 18:35:21 +00:00
use stdx ::to_lower_snake_case ;
2019-12-21 17:45:46 +00:00
2020-03-10 18:21:56 +00:00
#[ derive(Clone, Debug, PartialEq, Eq) ]
2020-03-31 14:02:55 +00:00
pub struct InlayHintsConfig {
2020-03-12 03:14:39 +00:00
pub type_hints : bool ,
pub parameter_hints : bool ,
2020-03-23 19:32:05 +00:00
pub chaining_hints : bool ,
2020-03-10 18:21:56 +00:00
pub max_length : Option < usize > ,
}
2020-03-31 14:02:55 +00:00
impl Default for InlayHintsConfig {
2020-03-10 18:21:56 +00:00
fn default ( ) -> Self {
2020-03-24 19:31:02 +00:00
Self { type_hints : true , parameter_hints : true , chaining_hints : true , max_length : None }
2020-03-10 18:21:56 +00:00
}
}
#[ derive(Clone, Debug, PartialEq, Eq) ]
2019-07-19 21:20:09 +00:00
pub enum InlayKind {
2019-08-04 21:28:36 +00:00
TypeHint ,
2020-01-14 17:02:01 +00:00
ParameterHint ,
2020-03-23 19:32:05 +00:00
ChainingHint ,
2019-07-19 21:20:09 +00:00
}
#[ derive(Debug) ]
pub struct InlayHint {
pub range : TextRange ,
2019-07-22 18:52:47 +00:00
pub kind : InlayKind ,
pub label : SmolStr ,
2019-07-19 21:20:09 +00:00
}
2020-05-31 09:29:19 +00:00
// Feature: Inlay Hints
//
// rust-analyzer shows additional information inline with the source code.
// Editors usually render this using read-only virtual text snippets interspersed with code.
//
// rust-analyzer shows hits for
//
// * types of local variables
// * names of function arguments
// * types of chained expressions
//
// **Note:** VS Code does not have native support for inlay hints https://github.com/microsoft/vscode/issues/16221[yet] and the hints are implemented using decorations.
// This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
// https://github.com/rust-analyzer/rust-analyzer/issues/1623[1], https://github.com/rust-analyzer/rust-analyzer/issues/3453[2].
//
// |===
// | Editor | Action Name
//
// | VS Code | **Rust Analyzer: Toggle inlay hints*
// |===
2019-11-18 17:02:28 +00:00
pub ( crate ) fn inlay_hints (
db : & RootDatabase ,
file_id : FileId ,
2020-03-31 14:02:55 +00:00
config : & InlayHintsConfig ,
2019-11-18 17:02:28 +00:00
) -> Vec < InlayHint > {
2020-02-29 22:24:50 +00:00
let _p = profile ( " inlay_hints " ) ;
2020-02-18 17:35:10 +00:00
let sema = Semantics ::new ( db ) ;
let file = sema . parse ( file_id ) ;
2020-02-29 22:24:50 +00:00
2020-01-16 13:31:34 +00:00
let mut res = Vec ::new ( ) ;
for node in file . syntax ( ) . descendants ( ) {
2020-03-23 19:32:05 +00:00
if let Some ( expr ) = ast ::Expr ::cast ( node . clone ( ) ) {
2020-03-31 14:02:55 +00:00
get_chaining_hints ( & mut res , & sema , config , expr ) ;
2020-03-23 19:32:05 +00:00
}
2020-02-29 22:24:50 +00:00
match_ast! {
match node {
2020-03-31 14:02:55 +00:00
ast ::CallExpr ( it ) = > { get_param_name_hints ( & mut res , & sema , config , ast ::Expr ::from ( it ) ) ; } ,
ast ::MethodCallExpr ( it ) = > { get_param_name_hints ( & mut res , & sema , config , ast ::Expr ::from ( it ) ) ; } ,
ast ::BindPat ( it ) = > { get_bind_pat_hints ( & mut res , & sema , config , it ) ; } ,
2020-02-29 22:24:50 +00:00
_ = > ( ) ,
}
}
2020-01-16 13:31:34 +00:00
}
res
2019-07-19 21:20:09 +00:00
}
2020-03-24 18:33:00 +00:00
fn get_chaining_hints (
acc : & mut Vec < InlayHint > ,
sema : & Semantics < RootDatabase > ,
2020-03-31 14:02:55 +00:00
config : & InlayHintsConfig ,
2020-03-24 18:33:00 +00:00
expr : ast ::Expr ,
) -> Option < ( ) > {
2020-03-31 14:02:55 +00:00
if ! config . chaining_hints {
2020-03-24 18:33:00 +00:00
return None ;
}
2020-03-31 18:25:03 +00:00
if matches! ( expr , ast ::Expr ::RecordLit ( _ ) ) {
2020-03-24 18:33:00 +00:00
return None ;
}
2020-03-24 19:31:02 +00:00
let mut tokens = expr
. syntax ( )
2020-03-24 18:33:00 +00:00
. siblings_with_tokens ( Direction ::Next )
. filter_map ( NodeOrToken ::into_token )
. filter ( | t | match t . kind ( ) {
SyntaxKind ::WHITESPACE if ! t . text ( ) . contains ( '\n' ) = > false ,
SyntaxKind ::COMMENT = > false ,
_ = > true ,
} ) ;
// Chaining can be defined as an expression whose next sibling tokens are newline and dot
// Ignoring extra whitespace and comments
let next = tokens . next ( ) ? . kind ( ) ;
let next_next = tokens . next ( ) ? . kind ( ) ;
2020-03-24 19:31:02 +00:00
if next = = SyntaxKind ::WHITESPACE & & next_next = = SyntaxKind ::DOT {
2020-03-31 18:25:03 +00:00
let ty = sema . type_of_expr ( & expr ) ? ;
if ty . is_unknown ( ) {
return None ;
}
if matches! ( expr , ast ::Expr ::PathExpr ( _ ) ) {
if let Some ( Adt ::Struct ( st ) ) = ty . as_adt ( ) {
if st . fields ( sema . db ) . is_empty ( ) {
return None ;
}
}
}
2020-03-31 14:02:55 +00:00
let label = ty . display_truncated ( sema . db , config . max_length ) . to_string ( ) ;
2020-03-24 18:33:00 +00:00
acc . push ( InlayHint {
range : expr . syntax ( ) . text_range ( ) ,
kind : InlayKind ::ChainingHint ,
label : label . into ( ) ,
} ) ;
}
Some ( ( ) )
}
2020-02-29 22:24:50 +00:00
fn get_param_name_hints (
2020-01-16 13:31:34 +00:00
acc : & mut Vec < InlayHint > ,
2020-02-18 17:35:10 +00:00
sema : & Semantics < RootDatabase > ,
2020-03-31 14:02:55 +00:00
config : & InlayHintsConfig ,
2020-02-29 22:24:50 +00:00
expr : ast ::Expr ,
2020-01-16 13:31:34 +00:00
) -> Option < ( ) > {
2020-03-31 14:02:55 +00:00
if ! config . parameter_hints {
2020-03-10 18:21:56 +00:00
return None ;
2020-03-10 07:55:46 +00:00
}
2020-02-29 22:24:50 +00:00
let args = match & expr {
ast ::Expr ::CallExpr ( expr ) = > expr . arg_list ( ) ? . args ( ) ,
ast ::Expr ::MethodCallExpr ( expr ) = > expr . arg_list ( ) ? . args ( ) ,
_ = > return None ,
2020-01-16 13:31:34 +00:00
} ;
2020-02-29 22:24:50 +00:00
let fn_signature = get_fn_signature ( sema , & expr ) ? ;
let n_params_to_skip =
2020-06-05 11:58:52 +00:00
if fn_signature . has_self_param & & matches! ( & expr , ast ::Expr ::MethodCallExpr ( _ ) ) {
2020-02-29 22:24:50 +00:00
1
} else {
0
} ;
let hints = fn_signature
. parameter_names
. iter ( )
. skip ( n_params_to_skip )
. zip ( args )
2020-05-03 12:50:35 +00:00
. filter ( | ( param , arg ) | should_show_param_name_hint ( sema , & fn_signature , param , & arg ) )
2020-02-29 22:24:50 +00:00
. map ( | ( param_name , arg ) | InlayHint {
range : arg . syntax ( ) . text_range ( ) ,
kind : InlayKind ::ParameterHint ,
label : param_name . into ( ) ,
} ) ;
acc . extend ( hints ) ;
Some ( ( ) )
}
fn get_bind_pat_hints (
acc : & mut Vec < InlayHint > ,
sema : & Semantics < RootDatabase > ,
2020-03-31 14:02:55 +00:00
config : & InlayHintsConfig ,
2020-02-29 22:24:50 +00:00
pat : ast ::BindPat ,
) -> Option < ( ) > {
2020-03-31 14:02:55 +00:00
if ! config . type_hints {
2020-03-10 18:21:56 +00:00
return None ;
2020-03-10 07:55:46 +00:00
}
2020-02-29 22:24:50 +00:00
let ty = sema . type_of_pat ( & pat . clone ( ) . into ( ) ) ? ;
if should_not_display_type_hint ( sema . db , & pat , & ty ) {
return None ;
}
acc . push ( InlayHint {
range : pat . syntax ( ) . text_range ( ) ,
kind : InlayKind ::TypeHint ,
2020-03-31 14:02:55 +00:00
label : ty . display_truncated ( sema . db , config . max_length ) . to_string ( ) . into ( ) ,
2020-02-29 22:24:50 +00:00
} ) ;
2020-01-16 13:31:34 +00:00
Some ( ( ) )
2019-07-21 20:28:05 +00:00
}
2020-01-16 13:31:34 +00:00
2020-02-24 07:29:34 +00:00
fn pat_is_enum_variant ( db : & RootDatabase , bind_pat : & ast ::BindPat , pat_ty : & Type ) -> bool {
if let Some ( Adt ::Enum ( enum_data ) ) = pat_ty . as_adt ( ) {
2020-05-03 12:07:57 +00:00
let pat_text = bind_pat . to_string ( ) ;
2020-02-24 07:29:34 +00:00
enum_data
. variants ( db )
. into_iter ( )
. map ( | variant | variant . name ( db ) . to_string ( ) )
. any ( | enum_name | enum_name = = pat_text )
} else {
false
}
}
fn should_not_display_type_hint ( db : & RootDatabase , bind_pat : & ast ::BindPat , pat_ty : & Type ) -> bool {
if pat_ty . is_unknown ( ) {
return true ;
}
2020-03-08 21:21:08 +00:00
if let Some ( Adt ::Struct ( s ) ) = pat_ty . as_adt ( ) {
2020-05-03 12:07:57 +00:00
if s . fields ( db ) . is_empty ( ) & & s . name ( db ) . to_string ( ) = = bind_pat . to_string ( ) {
2020-03-08 21:21:08 +00:00
return true ;
}
}
2020-02-22 20:07:09 +00:00
for node in bind_pat . syntax ( ) . ancestors ( ) {
match_ast! {
match node {
ast ::LetStmt ( it ) = > {
return it . ascribed_type ( ) . is_some ( )
} ,
ast ::Param ( it ) = > {
return it . ascribed_type ( ) . is_some ( )
} ,
2020-02-24 07:29:34 +00:00
ast ::MatchArm ( _it ) = > {
return pat_is_enum_variant ( db , bind_pat , pat_ty ) ;
} ,
ast ::IfExpr ( it ) = > {
return it . condition ( ) . and_then ( | condition | condition . pat ( ) ) . is_some ( )
& & pat_is_enum_variant ( db , bind_pat , pat_ty ) ;
} ,
ast ::WhileExpr ( it ) = > {
return it . condition ( ) . and_then ( | condition | condition . pat ( ) ) . is_some ( )
& & pat_is_enum_variant ( db , bind_pat , pat_ty ) ;
} ,
2020-02-22 20:07:09 +00:00
_ = > ( ) ,
}
}
}
false
}
2020-05-03 12:07:57 +00:00
fn should_show_param_name_hint (
2020-05-03 12:50:35 +00:00
sema : & Semantics < RootDatabase > ,
2020-02-23 09:49:53 +00:00
fn_signature : & FunctionSignature ,
param_name : & str ,
2020-02-24 07:29:34 +00:00
argument : & ast ::Expr ,
2020-02-23 09:49:53 +00:00
) -> bool {
2020-05-03 12:50:35 +00:00
let param_name = param_name . trim_start_matches ( '_' ) ;
2020-04-09 10:47:48 +00:00
if param_name . is_empty ( )
2020-05-03 12:50:35 +00:00
| | Some ( param_name ) = = fn_signature . name . as_ref ( ) . map ( | s | s . trim_start_matches ( '_' ) )
| | is_argument_similar_to_param_name ( sema , argument , param_name )
2020-06-28 11:11:41 +00:00
| | param_name . starts_with ( " ra_fixture " )
2020-04-09 10:47:48 +00:00
{
2020-02-23 09:49:53 +00:00
return false ;
}
let parameters_len = if fn_signature . has_self_param {
fn_signature . parameters . len ( ) - 1
} else {
fn_signature . parameters . len ( )
} ;
2020-04-08 21:48:16 +00:00
2020-02-23 09:49:53 +00:00
// avoid displaying hints for common functions like map, filter, etc.
2020-04-08 21:48:16 +00:00
// or other obvious words used in std
2020-06-28 11:11:41 +00:00
! ( parameters_len = = 1 & & is_obvious_param ( param_name ) )
2020-04-09 14:35:07 +00:00
}
2020-05-03 12:50:35 +00:00
fn is_argument_similar_to_param_name (
sema : & Semantics < RootDatabase > ,
argument : & ast ::Expr ,
param_name : & str ,
) -> bool {
if is_enum_name_similar_to_param_name ( sema , argument , param_name ) {
return true ;
2020-05-04 07:58:21 +00:00
}
match get_string_representation ( argument ) {
None = > false ,
Some ( repr ) = > {
let argument_string = repr . trim_start_matches ( '_' ) ;
argument_string . starts_with ( param_name ) | | argument_string . ends_with ( param_name )
}
2020-05-03 12:50:35 +00:00
}
}
fn is_enum_name_similar_to_param_name (
sema : & Semantics < RootDatabase > ,
argument : & ast ::Expr ,
param_name : & str ,
) -> bool {
match sema . type_of_expr ( argument ) . and_then ( | t | t . as_adt ( ) ) {
2020-05-03 18:35:21 +00:00
Some ( Adt ::Enum ( e ) ) = > to_lower_snake_case ( & e . name ( sema . db ) . to_string ( ) ) = = param_name ,
2020-05-03 12:50:35 +00:00
_ = > false ,
}
}
2020-05-03 12:07:57 +00:00
fn get_string_representation ( expr : & ast ::Expr ) -> Option < String > {
match expr {
ast ::Expr ::MethodCallExpr ( method_call_expr ) = > {
Some ( method_call_expr . name_ref ( ) ? . to_string ( ) )
2020-04-09 16:26:49 +00:00
}
2020-05-03 12:07:57 +00:00
ast ::Expr ::RefExpr ( ref_expr ) = > get_string_representation ( & ref_expr . expr ( ) ? ) ,
_ = > Some ( expr . to_string ( ) ) ,
2020-04-09 16:26:49 +00:00
}
}
2020-04-09 14:35:07 +00:00
fn is_obvious_param ( param_name : & str ) -> bool {
2020-06-28 01:02:03 +00:00
let is_obvious_param_name =
matches! ( param_name , " predicate " | " value " | " pat " | " rhs " | " other " ) ;
2020-04-09 14:35:07 +00:00
param_name . len ( ) = = 1 | | is_obvious_param_name
2020-02-23 09:49:53 +00:00
}
2020-02-18 17:35:10 +00:00
fn get_fn_signature ( sema : & Semantics < RootDatabase > , expr : & ast ::Expr ) -> Option < FunctionSignature > {
2020-01-14 17:02:01 +00:00
match expr {
ast ::Expr ::CallExpr ( expr ) = > {
// FIXME: Type::as_callable is broken for closures
2020-02-18 17:35:10 +00:00
let callable_def = sema . type_of_expr ( & expr . expr ( ) ? ) ? . as_callable ( ) ? ;
2020-01-14 17:02:01 +00:00
match callable_def {
hir ::CallableDef ::FunctionId ( it ) = > {
2020-02-18 17:35:10 +00:00
Some ( FunctionSignature ::from_hir ( sema . db , it . into ( ) ) )
}
hir ::CallableDef ::StructId ( it ) = > {
FunctionSignature ::from_struct ( sema . db , it . into ( ) )
2020-01-14 17:02:01 +00:00
}
hir ::CallableDef ::EnumVariantId ( it ) = > {
2020-02-18 17:35:10 +00:00
FunctionSignature ::from_enum_variant ( sema . db , it . into ( ) )
2020-01-14 17:02:01 +00:00
}
}
}
ast ::Expr ::MethodCallExpr ( expr ) = > {
2020-02-18 17:35:10 +00:00
let fn_def = sema . resolve_method_call ( & expr ) ? ;
Some ( FunctionSignature ::from_hir ( sema . db , fn_def ) )
2020-01-14 17:02:01 +00:00
}
_ = > None ,
}
}
2019-07-21 20:28:05 +00:00
2019-07-19 21:20:09 +00:00
#[ cfg(test) ]
mod tests {
2020-03-31 14:02:55 +00:00
use crate ::inlay_hints ::InlayHintsConfig ;
2019-08-29 13:49:10 +00:00
use insta ::assert_debug_snapshot ;
2019-07-19 21:20:09 +00:00
2019-12-07 18:14:01 +00:00
use crate ::mock_analysis ::single_file ;
2020-03-10 07:55:46 +00:00
#[ test ]
fn param_hints_only ( ) {
let ( analysis , file_id ) = single_file (
r #"
fn foo ( a : i32 , b : i32 ) -> i32 { a + b }
fn main ( ) {
let _x = foo ( 4 , 4 ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { parameter_hints : true , type_hints : false , chaining_hints : false , max_length : None } ) . unwrap ( ) , @ r ###"
2020-03-10 07:55:46 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 69 .. 70 ,
2020-03-10 07:55:46 +00:00
kind : ParameterHint ,
label : " a " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 72 .. 73 ,
2020-03-10 07:55:46 +00:00
kind : ParameterHint ,
label : " b " ,
} ,
2020-06-24 09:05:47 +00:00
]
" ###);
2020-03-10 07:55:46 +00:00
}
#[ test ]
fn hints_disabled ( ) {
let ( analysis , file_id ) = single_file (
r #"
fn foo ( a : i32 , b : i32 ) -> i32 { a + b }
fn main ( ) {
let _x = foo ( 4 , 4 ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { type_hints : false , parameter_hints : false , chaining_hints : false , max_length : None } ) . unwrap ( ) , @ r ### "[]"### ) ;
2020-03-10 07:55:46 +00:00
}
#[ test ]
fn type_hints_only ( ) {
let ( analysis , file_id ) = single_file (
r #"
fn foo ( a : i32 , b : i32 ) -> i32 { a + b }
fn main ( ) {
let _x = foo ( 4 , 4 ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { type_hints : true , parameter_hints : false , chaining_hints : false , max_length : None } ) . unwrap ( ) , @ r ###"
2020-03-10 07:55:46 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 60 .. 62 ,
2020-03-10 07:55:46 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
2020-06-24 09:05:47 +00:00
]
" ###);
2020-03-10 07:55:46 +00:00
}
2019-12-07 22:54:18 +00:00
#[ test ]
2019-12-19 14:18:09 +00:00
fn default_generic_types_should_not_be_displayed ( ) {
2019-12-07 22:54:18 +00:00
let ( analysis , file_id ) = single_file (
r #"
struct Test < K , T = u8 > {
2019-12-19 10:45:00 +00:00
k : K ,
2019-12-07 22:54:18 +00:00
t : T ,
}
fn main ( ) {
2020-05-29 17:14:04 +00:00
let zz = Test { t : 23 u8 , k : 33 } ;
2020-01-22 14:44:05 +00:00
let zz_ref = & zz ;
2019-12-07 22:54:18 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-12-07 22:54:18 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 68 .. 70 ,
2019-12-07 22:54:18 +00:00
kind : TypeHint ,
label : " Test<i32> " ,
} ,
2020-01-22 14:44:05 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 106 .. 112 ,
2020-01-22 14:44:05 +00:00
kind : TypeHint ,
label : " &Test<i32> " ,
} ,
2019-12-07 22:54:18 +00:00
]
" ###
) ;
}
2019-07-19 21:20:09 +00:00
#[ test ]
2019-07-27 21:50:26 +00:00
fn let_statement ( ) {
2019-07-21 20:28:05 +00:00
let ( analysis , file_id ) = single_file (
2019-07-19 21:20:09 +00:00
r #"
2019-07-27 21:50:26 +00:00
#[ derive(PartialEq) ]
enum CustomOption < T > {
None ,
Some ( T ) ,
}
#[ derive(PartialEq) ]
struct Test {
a : CustomOption < u32 > ,
b : u8 ,
}
2019-07-19 21:20:09 +00:00
fn main ( ) {
struct InnerStruct { }
let test = 54 ;
2019-07-26 11:10:29 +00:00
let test : i32 = 33 ;
let mut test = 33 ;
let _ = 22 ;
let test = " test " ;
2019-07-19 21:20:09 +00:00
let test = InnerStruct { } ;
2019-07-26 11:10:29 +00:00
2019-07-19 21:20:09 +00:00
let test = vec! [ 222 ] ;
2019-07-26 11:10:29 +00:00
let test : Vec < _ > = ( 0 .. 3 ) . collect ( ) ;
2019-07-27 21:50:26 +00:00
let test = ( 0 .. 3 ) . collect ::< Vec < i128 > > ( ) ;
let test = ( 0 .. 3 ) . collect ::< Vec < _ > > ( ) ;
2019-07-26 11:10:29 +00:00
2019-07-19 21:20:09 +00:00
let mut test = Vec ::new ( ) ;
test . push ( 333 ) ;
2019-07-26 11:10:29 +00:00
2019-07-19 21:20:09 +00:00
let test = ( 42 , 'a' ) ;
2019-07-26 11:10:29 +00:00
let ( a , ( b , c , ( d , e ) , f ) ) = ( 2 , ( 3 , 4 , ( 6.6 , 7.7 ) , 5 ) ) ;
2019-12-07 18:14:01 +00:00
let & x = & 92 ;
2019-07-27 21:50:26 +00:00
} " #,
2019-07-21 20:28:05 +00:00
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 192 .. 196 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 235 .. 243 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 274 .. 278 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &str " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 538 .. 542 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " (i32, char) " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 565 .. 566 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 569 .. 570 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 572 .. 573 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 576 .. 577 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " f64 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 579 .. 580 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " f64 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 583 .. 584 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
2019-12-07 18:14:01 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 626 .. 627 ,
2019-12-07 18:14:01 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
2019-11-15 09:56:24 +00:00
]
" ###
2019-07-27 21:50:26 +00:00
) ;
}
#[ test ]
2019-12-23 15:53:35 +00:00
fn closure_parameters ( ) {
2019-07-27 21:50:26 +00:00
let ( analysis , file_id ) = single_file (
r #"
fn main ( ) {
let mut start = 0 ;
( 0 .. 2 ) . for_each ( | increment | {
start + = increment ;
2020-02-03 11:35:14 +00:00
} ) ;
2019-12-23 15:53:35 +00:00
let multiply = | a , b , c , d | a * b * c * d ;
let _ : i32 = multiply ( 1 , 2 , 3 , 4 ) ;
2020-01-22 14:44:05 +00:00
let multiply_ref = & multiply ;
2019-12-23 15:53:35 +00:00
let return_42 = | | 42 ;
2019-07-27 21:50:26 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 20 .. 29 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 56 .. 65 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
2019-12-23 15:53:35 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 114 .. 122 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " |…| -> i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 126 .. 127 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 129 .. 130 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 132 .. 133 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 135 .. 136 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 200 .. 212 ,
2020-01-22 14:44:05 +00:00
kind : TypeHint ,
label : " &|…| -> i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 235 .. 244 ,
2019-12-23 15:53:35 +00:00
kind : TypeHint ,
label : " || -> i32 " ,
} ,
2019-11-15 09:56:24 +00:00
]
" ###
2019-07-27 21:50:26 +00:00
) ;
}
#[ test ]
fn for_expression ( ) {
let ( analysis , file_id ) = single_file (
r #"
fn main ( ) {
let mut start = 0 ;
for increment in 0 .. 2 {
start + = increment ;
}
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 20 .. 29 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 43 .. 52 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
]
" ###
2019-07-27 21:50:26 +00:00
) ;
}
#[ test ]
fn if_expr ( ) {
let ( analysis , file_id ) = single_file (
r #"
#[ derive(PartialEq) ]
enum CustomOption < T > {
None ,
Some ( T ) ,
}
#[ derive(PartialEq) ]
struct Test {
a : CustomOption < u32 > ,
b : u8 ,
}
2020-02-24 07:29:34 +00:00
use CustomOption ::* ;
2019-07-27 21:50:26 +00:00
fn main ( ) {
2020-02-24 07:29:34 +00:00
let test = Some ( Test { a : Some ( 3 ) , b : 1 } ) ;
if let None = & test { } ;
2019-07-27 21:50:26 +00:00
if let test = & test { } ;
2020-02-24 07:29:34 +00:00
if let Some ( test ) = & test { } ;
if let Some ( Test { a , b } ) = & test { } ;
if let Some ( Test { a : x , b : y } ) = & test { } ;
if let Some ( Test { a : Some ( x ) , b : y } ) = & test { } ;
if let Some ( Test { a : None , b : y } ) = & test { } ;
if let Some ( Test { b : y , .. } ) = & test { } ;
if test = = None { }
2019-07-27 21:50:26 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 187 .. 191 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " CustomOption<Test> " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 266 .. 270 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &CustomOption<Test> " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 299 .. 303 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &Test " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 340 .. 341 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 343 .. 344 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 386 .. 387 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 392 .. 393 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 440 .. 441 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &u32 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 447 .. 448 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 499 .. 500 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 542 .. 543 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2019-11-15 09:56:24 +00:00
]
" ###
2019-07-27 21:50:26 +00:00
) ;
}
#[ test ]
fn while_expr ( ) {
let ( analysis , file_id ) = single_file (
r #"
#[ derive(PartialEq) ]
enum CustomOption < T > {
None ,
Some ( T ) ,
}
#[ derive(PartialEq) ]
struct Test {
a : CustomOption < u32 > ,
b : u8 ,
}
2020-02-24 07:29:34 +00:00
use CustomOption ::* ;
2019-07-27 21:50:26 +00:00
fn main ( ) {
2020-02-24 07:29:34 +00:00
let test = Some ( Test { a : Some ( 3 ) , b : 1 } ) ;
while let None = & test { } ;
2019-07-27 21:50:26 +00:00
while let test = & test { } ;
2020-02-24 07:29:34 +00:00
while let Some ( test ) = & test { } ;
while let Some ( Test { a , b } ) = & test { } ;
while let Some ( Test { a : x , b : y } ) = & test { } ;
while let Some ( Test { a : Some ( x ) , b : y } ) = & test { } ;
while let Some ( Test { a : None , b : y } ) = & test { } ;
while let Some ( Test { b : y , .. } ) = & test { } ;
while test = = None { }
2019-07-27 21:50:26 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 187 .. 191 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " CustomOption<Test> " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 272 .. 276 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &CustomOption<Test> " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 308 .. 312 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &Test " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 352 .. 353 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 355 .. 356 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 401 .. 402 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 407 .. 408 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 458 .. 459 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " &u32 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 465 .. 466 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 520 .. 521 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 566 .. 567 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " &u8 " ,
} ,
2019-11-15 09:56:24 +00:00
]
2019-08-07 13:14:22 +00:00
" ###
2019-07-27 21:50:26 +00:00
) ;
}
#[ test ]
fn match_arm_list ( ) {
let ( analysis , file_id ) = single_file (
r #"
#[ derive(PartialEq) ]
2019-08-04 21:28:36 +00:00
enum CustomOption < T > {
2019-07-27 21:50:26 +00:00
None ,
Some ( T ) ,
}
#[ derive(PartialEq) ]
struct Test {
a : CustomOption < u32 > ,
b : u8 ,
}
2020-02-24 07:29:34 +00:00
use CustomOption ::* ;
2019-07-27 21:50:26 +00:00
fn main ( ) {
2020-02-24 07:29:34 +00:00
match Some ( Test { a : Some ( 3 ) , b : 1 } ) {
None = > ( ) ,
2019-07-27 21:50:26 +00:00
test = > ( ) ,
2020-02-24 07:29:34 +00:00
Some ( test ) = > ( ) ,
Some ( Test { a , b } ) = > ( ) ,
Some ( Test { a : x , b : y } ) = > ( ) ,
Some ( Test { a : Some ( x ) , b : y } ) = > ( ) ,
Some ( Test { a : None , b : y } ) = > ( ) ,
Some ( Test { b : y , .. } ) = > ( ) ,
2019-07-27 21:50:26 +00:00
_ = > { }
}
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2019-11-15 09:56:24 +00:00
[
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 251 .. 255 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " CustomOption<Test> " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 276 .. 280 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " Test " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 309 .. 310 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 312 .. 313 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " u8 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 347 .. 348 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " CustomOption<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 353 .. 354 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " u8 " ,
} ,
2019-11-15 09:56:24 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 393 .. 394 ,
2019-11-15 09:56:24 +00:00
kind : TypeHint ,
label : " u32 " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 400 .. 401 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 444 .. 445 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " u8 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 479 .. 480 ,
2020-02-22 22:23:33 +00:00
kind : TypeHint ,
label : " u8 " ,
} ,
2019-11-15 09:56:24 +00:00
]
" ###
2019-07-21 17:51:27 +00:00
) ;
2019-07-19 21:20:09 +00:00
}
2019-11-19 16:40:38 +00:00
#[ test ]
fn hint_truncation ( ) {
let ( analysis , file_id ) = single_file (
r #"
struct Smol < T > ( T ) ;
struct VeryLongOuterName < T > ( T ) ;
fn main ( ) {
let a = Smol ( 0 u32 ) ;
let b = VeryLongOuterName ( 0 usize ) ;
let c = Smol ( Smol ( 0 u32 ) )
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { max_length : Some ( 8 ) , .. Default ::default ( ) } ) . unwrap ( ) , @ r ###"
2019-11-19 16:40:38 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 73 .. 74 ,
2019-11-19 16:40:38 +00:00
kind : TypeHint ,
label : " Smol<u32> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 97 .. 98 ,
2019-11-19 16:40:38 +00:00
kind : TypeHint ,
label : " VeryLongOuterName<…> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 136 .. 137 ,
2019-11-19 16:40:38 +00:00
kind : TypeHint ,
label : " Smol<Smol<…>> " ,
} ,
]
" ###
) ;
}
2020-01-14 17:02:01 +00:00
#[ test ]
fn function_call_parameter_hint ( ) {
let ( analysis , file_id ) = single_file (
r #"
2020-02-23 09:49:53 +00:00
enum CustomOption < T > {
None ,
Some ( T ) ,
}
2020-02-24 07:29:34 +00:00
use CustomOption ::* ;
2020-02-23 09:49:53 +00:00
struct FileId { }
struct SmolStr { }
impl From < & str > for SmolStr {
fn from ( _ : & str ) -> Self {
unimplemented! ( )
}
}
struct TextRange { }
struct SyntaxKind { }
struct NavigationTarget { }
2020-01-14 17:02:01 +00:00
struct Test { }
impl Test {
2020-01-18 12:40:32 +00:00
fn method ( & self , mut param : i32 ) -> i32 {
2020-01-14 17:02:01 +00:00
param * 2
}
2020-02-23 09:49:53 +00:00
fn from_syntax (
file_id : FileId ,
name : SmolStr ,
focus_range : CustomOption < TextRange > ,
full_range : TextRange ,
kind : SyntaxKind ,
docs : CustomOption < String > ,
description : CustomOption < String > ,
) -> NavigationTarget {
NavigationTarget { }
}
2020-01-14 17:02:01 +00:00
}
2020-01-18 12:40:32 +00:00
fn test_func ( mut foo : i32 , bar : i32 , msg : & str , _ : i32 , last : i32 ) -> i32 {
2020-01-14 17:02:01 +00:00
foo + bar
}
fn main ( ) {
let not_literal = 1 ;
let _ : i32 = test_func ( 1 , 2 , " hello " , 3 , not_literal ) ;
let t : Test = Test { } ;
t . method ( 123 ) ;
Test ::method ( & t , 3456 ) ;
2020-02-23 09:49:53 +00:00
Test ::from_syntax (
FileId { } ,
" impl " . into ( ) ,
2020-02-24 07:29:34 +00:00
None ,
2020-02-23 09:49:53 +00:00
TextRange { } ,
SyntaxKind { } ,
2020-02-24 07:29:34 +00:00
None ,
None ,
2020-02-23 09:49:53 +00:00
) ;
2020-01-14 17:02:01 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig ::default ( ) ) . unwrap ( ) , @ r ###"
2020-01-14 17:02:01 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 797 .. 808 ,
2020-01-14 17:02:01 +00:00
kind : TypeHint ,
label : " i32 " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 841 .. 842 ,
2020-01-14 17:02:01 +00:00
kind : ParameterHint ,
label : " foo " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 844 .. 845 ,
2020-01-14 17:02:01 +00:00
kind : ParameterHint ,
label : " bar " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 847 .. 854 ,
2020-01-14 17:02:01 +00:00
kind : ParameterHint ,
label : " msg " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 859 .. 870 ,
2020-02-22 22:23:33 +00:00
kind : ParameterHint ,
label : " last " ,
} ,
2020-01-14 17:02:01 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 913 .. 916 ,
2020-01-14 17:02:01 +00:00
kind : ParameterHint ,
label : " param " ,
} ,
2020-02-22 22:23:33 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 936 .. 938 ,
2020-02-22 22:23:33 +00:00
kind : ParameterHint ,
label : " &self " ,
} ,
2020-01-14 17:02:01 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 940 .. 944 ,
2020-01-14 17:02:01 +00:00
kind : ParameterHint ,
label : " param " ,
} ,
2020-02-23 09:49:53 +00:00
InlayHint {
2020-06-24 09:05:47 +00:00
range : 979 .. 988 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " file_id " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 998 .. 1011 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " name " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 1021 .. 1025 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " focus_range " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 1035 .. 1047 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " full_range " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 1057 .. 1070 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " kind " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 1080 .. 1084 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " docs " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 1094 .. 1098 ,
2020-02-23 09:49:53 +00:00
kind : ParameterHint ,
label : " description " ,
} ,
2020-01-14 17:02:01 +00:00
]
" ###
) ;
}
2020-02-23 09:49:53 +00:00
#[ test ]
fn omitted_parameters_hints_heuristics ( ) {
let ( analysis , file_id ) = single_file (
r #"
fn map ( f : i32 ) { }
fn filter ( predicate : i32 ) { }
struct TestVarContainer {
test_var : i32 ,
}
2020-05-03 12:07:57 +00:00
impl TestVarContainer {
fn test_var ( & self ) -> i32 {
self . test_var
}
}
2020-02-23 09:49:53 +00:00
struct Test { }
impl Test {
fn map ( self , f : i32 ) -> Self {
self
}
fn filter ( self , predicate : i32 ) -> Self {
self
}
2020-04-08 21:48:16 +00:00
fn field ( self , value : i32 ) -> Self {
self
}
2020-02-23 09:49:53 +00:00
fn no_hints_expected ( & self , _ : i32 , test_var : i32 ) { }
2020-04-09 10:47:48 +00:00
fn frob ( & self , frob : bool ) { }
2020-02-23 09:49:53 +00:00
}
2020-04-08 21:48:16 +00:00
struct Param { }
2020-04-08 23:07:21 +00:00
fn different_order ( param : & Param ) { }
fn different_order_mut ( param : & mut Param ) { }
2020-04-18 07:53:48 +00:00
fn has_underscore ( _param : bool ) { }
2020-05-03 12:50:35 +00:00
fn enum_matches_param_name ( completion_kind : CompletionKind ) { }
2020-04-08 21:48:16 +00:00
2020-04-09 10:47:48 +00:00
fn twiddle ( twiddle : bool ) { }
2020-04-18 07:53:48 +00:00
fn doo ( _doo : bool ) { }
2020-04-09 10:47:48 +00:00
2020-05-03 12:50:35 +00:00
enum CompletionKind {
Keyword ,
}
2020-02-23 09:49:53 +00:00
fn main ( ) {
let container : TestVarContainer = TestVarContainer { test_var : 42 } ;
let test : Test = Test { } ;
map ( 22 ) ;
filter ( 33 ) ;
2020-04-08 21:48:16 +00:00
let test_processed : Test = test . map ( 1 ) . filter ( 2 ) . field ( 3 ) ;
2020-02-23 09:49:53 +00:00
let test_var : i32 = 55 ;
test_processed . no_hints_expected ( 22 , test_var ) ;
test_processed . no_hints_expected ( 33 , container . test_var ) ;
2020-05-03 12:07:57 +00:00
test_processed . no_hints_expected ( 44 , container . test_var ( ) ) ;
2020-04-09 10:47:48 +00:00
test_processed . frob ( false ) ;
twiddle ( true ) ;
2020-04-18 07:53:48 +00:00
doo ( true ) ;
2020-04-08 21:48:16 +00:00
2020-05-03 12:07:57 +00:00
let mut param_begin : Param = Param { } ;
2020-04-08 23:07:21 +00:00
different_order ( & param_begin ) ;
different_order ( & mut param_begin ) ;
2020-04-08 21:48:16 +00:00
2020-04-18 07:53:48 +00:00
let param : bool = true ;
has_underscore ( param ) ;
2020-05-03 12:50:35 +00:00
enum_matches_param_name ( CompletionKind ::Keyword ) ;
2020-04-08 21:48:16 +00:00
let a : f64 = 7.0 ;
let b : f64 = 4.0 ;
let _ : f64 = a . div_euclid ( b ) ;
let _ : f64 = a . abs_sub ( b ) ;
2020-02-23 09:49:53 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { max_length : Some ( 8 ) , .. Default ::default ( ) } ) . unwrap ( ) , @ r ###"
2020-02-23 09:49:53 +00:00
[ ]
" ###
) ;
}
2020-03-08 21:21:08 +00:00
#[ test ]
fn unit_structs_have_no_type_hints ( ) {
let ( analysis , file_id ) = single_file (
r #"
enum CustomResult < T , E > {
Ok ( T ) ,
Err ( E ) ,
}
use CustomResult ::* ;
struct SyntheticSyntax ;
fn main ( ) {
match Ok ( ( ) ) {
Ok ( _ ) = > ( ) ,
Err ( SyntheticSyntax ) = > ( ) ,
}
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { max_length : Some ( 8 ) , .. Default ::default ( ) } ) . unwrap ( ) , @ r ###"
2020-03-08 21:21:08 +00:00
[ ]
" ###
) ;
}
2020-03-24 18:33:00 +00:00
#[ test ]
fn chaining_hints_ignore_comments ( ) {
let ( analysis , file_id ) = single_file (
r #"
struct A ( B ) ;
impl A { fn into_b ( self ) -> B { self . 0 } }
2020-03-24 22:50:25 +00:00
struct B ( C ) ;
2020-03-24 18:33:00 +00:00
impl B { fn into_c ( self ) -> C { self . 0 } }
struct C ;
fn main ( ) {
let c = A ( B ( C ) )
. into_b ( ) // This is a comment
. into_c ( ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { parameter_hints : false , type_hints : false , chaining_hints : true , max_length : None } ) . unwrap ( ) , @ r ###"
2020-03-24 18:33:00 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 147 .. 172 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " B " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 147 .. 154 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " A " ,
} ,
2020-06-24 09:05:47 +00:00
]
" ###);
2020-03-24 18:33:00 +00:00
}
#[ test ]
fn chaining_hints_without_newlines ( ) {
let ( analysis , file_id ) = single_file (
r #"
struct A ( B ) ;
impl A { fn into_b ( self ) -> B { self . 0 } }
2020-03-24 22:50:25 +00:00
struct B ( C ) ;
2020-03-24 18:33:00 +00:00
impl B { fn into_c ( self ) -> C { self . 0 } }
struct C ;
fn main ( ) {
let c = A ( B ( C ) ) . into_b ( ) . into_c ( ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { parameter_hints : false , type_hints : false , chaining_hints : true , max_length : None } ) . unwrap ( ) , @ r ### "[]"### ) ;
2020-03-24 18:33:00 +00:00
}
#[ test ]
fn struct_access_chaining_hints ( ) {
let ( analysis , file_id ) = single_file (
r #"
struct A { pub b : B }
struct B { pub c : C }
struct C ( pub bool ) ;
2020-03-31 18:25:03 +00:00
struct D ;
impl D {
fn foo ( & self ) -> i32 { 42 }
}
2020-03-24 18:33:00 +00:00
fn main ( ) {
let x = A { b : B { c : C ( true ) } }
. b
. c
. 0 ;
2020-03-31 18:25:03 +00:00
let x = D
. foo ( ) ;
2020-03-24 18:33:00 +00:00
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { parameter_hints : false , type_hints : false , chaining_hints : true , max_length : None } ) . unwrap ( ) , @ r ###"
2020-03-24 18:33:00 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 143 .. 190 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " C " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 143 .. 179 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " B " ,
} ,
2020-03-31 18:25:03 +00:00
]
" ###);
2020-03-24 18:33:00 +00:00
}
#[ test ]
fn generic_chaining_hints ( ) {
let ( analysis , file_id ) = single_file (
r #"
2020-03-24 19:31:02 +00:00
struct A < T > ( T ) ;
2020-03-24 18:33:00 +00:00
struct B < T > ( T ) ;
struct C < T > ( T ) ;
struct X < T , R > ( T , R ) ;
2020-03-24 19:31:02 +00:00
2020-03-24 18:33:00 +00:00
impl < T > A < T > {
fn new ( t : T ) -> Self { A ( t ) }
fn into_b ( self ) -> B < T > { B ( self . 0 ) }
}
impl < T > B < T > {
fn into_c ( self ) -> C < T > { C ( self . 0 ) }
}
fn main ( ) {
let c = A ::new ( X ( 42 , true ) )
. into_b ( )
. into_c ( ) ;
} " #,
) ;
2020-03-31 14:02:55 +00:00
assert_debug_snapshot! ( analysis . inlay_hints ( file_id , & InlayHintsConfig { parameter_hints : false , type_hints : false , chaining_hints : true , max_length : None } ) . unwrap ( ) , @ r ###"
2020-03-24 18:33:00 +00:00
[
InlayHint {
2020-06-24 09:05:47 +00:00
range : 246 .. 283 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " B<X<i32, bool>> " ,
} ,
InlayHint {
2020-06-24 09:05:47 +00:00
range : 246 .. 265 ,
2020-03-24 18:33:00 +00:00
kind : ChainingHint ,
label : " A<X<i32, bool>> " ,
} ,
2020-06-24 09:05:47 +00:00
]
" ###);
2020-03-24 18:33:00 +00:00
}
2019-07-19 21:20:09 +00:00
}