@@ -2,9 +2,10 @@ use std::path::Path;
2
2
3
3
use futures:: future:: Future ;
4
4
use lsp_types:: { * , request:: * , notification:: * } ;
5
+ use serde_json:: json;
5
6
6
- use crate :: support:: basic_bin_manifest;
7
- use crate :: support:: project_builder:: project;
7
+ use crate :: support:: { basic_bin_manifest, fixtures_dir } ;
8
+ use crate :: support:: project_builder:: { project, ProjectBuilder } ;
8
9
9
10
#[ allow( dead_code) ]
10
11
mod support;
@@ -970,3 +971,190 @@ fn client_format_utf16_range() {
970
971
971
972
rls. shutdown ( ) ;
972
973
}
974
+
975
+ #[ test]
976
+ fn client_lens_run ( ) {
977
+ let p = ProjectBuilder :: try_from_fixture ( fixtures_dir ( ) . join ( "lens_run" ) )
978
+ . unwrap ( )
979
+ . build ( ) ;
980
+ let root_path = p. root ( ) ;
981
+ let mut rls = p. spawn_rls_async ( ) ;
982
+
983
+ rls. request :: < Initialize > ( 0 , lsp_types:: InitializeParams {
984
+ process_id : None ,
985
+ root_uri : None ,
986
+ root_path : Some ( root_path. display ( ) . to_string ( ) ) ,
987
+ initialization_options : Some ( json ! ( { "cmdRun" : true } ) ) ,
988
+ capabilities : Default :: default ( ) ,
989
+ trace : None ,
990
+ workspace_folders : None ,
991
+ } ) ;
992
+
993
+ rls. wait_for_indexing ( ) ;
994
+ assert ! ( rls. messages( ) . iter( ) . count( ) >= 7 ) ;
995
+
996
+ let lens = rls. request :: < CodeLensRequest > ( 1 , CodeLensParams {
997
+ text_document : TextDocumentIdentifier {
998
+ uri : Url :: from_file_path ( p. root ( ) . join ( "src/main.rs" ) ) . unwrap ( ) ,
999
+ }
1000
+ } ) ;
1001
+
1002
+ let expected = CodeLens {
1003
+ command : Some ( Command {
1004
+ command : "rls.run" . to_string ( ) ,
1005
+ title : "Run test" . to_string ( ) ,
1006
+ arguments : Some ( vec ! [
1007
+ json!( {
1008
+ "args" : [ "test" , "--" , "--nocapture" , "test_foo" ] ,
1009
+ "binary" : "cargo" ,
1010
+ "env" : { "RUST_BACKTRACE" : "short" }
1011
+ } )
1012
+ ] ) ,
1013
+ } ) ,
1014
+ data : None ,
1015
+ range : Range {
1016
+ start : Position { line : 14 , character : 3 } ,
1017
+ end : Position { line : 14 , character : 11 }
1018
+ }
1019
+ } ;
1020
+
1021
+ assert_eq ! ( lens, Some ( vec![ expected] ) ) ;
1022
+
1023
+ rls. shutdown ( ) ;
1024
+ }
1025
+
1026
+
1027
+ #[ test]
1028
+ fn client_find_definitions ( ) {
1029
+ const SRC : & str = r#"
1030
+ struct Foo {
1031
+ }
1032
+
1033
+ impl Foo {
1034
+ fn new() {
1035
+ }
1036
+ }
1037
+
1038
+ fn main() {
1039
+ Foo::new();
1040
+ }
1041
+ "# ;
1042
+
1043
+ let p = project ( "simple_workspace" )
1044
+ . file ( "Cargo.toml" , & basic_bin_manifest ( "bar" ) )
1045
+ . file ( "src/main.rs" , SRC )
1046
+ . build ( ) ;
1047
+
1048
+ let root_path = p. root ( ) ;
1049
+ let mut rls = p. spawn_rls_async ( ) ;
1050
+
1051
+ rls. request :: < Initialize > ( 0 , lsp_types:: InitializeParams {
1052
+ process_id : None ,
1053
+ root_uri : None ,
1054
+ root_path : Some ( root_path. display ( ) . to_string ( ) ) ,
1055
+ initialization_options : Some ( json ! ( { "settings.rust.racer_completion" : false } ) ) ,
1056
+ capabilities : Default :: default ( ) ,
1057
+ trace : None ,
1058
+ workspace_folders : None ,
1059
+ } ) ;
1060
+
1061
+ rls. wait_for_indexing ( ) ;
1062
+
1063
+ let mut results = vec ! [ ] ;
1064
+ for ( line_index, line) in SRC . lines ( ) . enumerate ( ) {
1065
+ for i in 0 ..line. len ( ) {
1066
+ let id = ( line_index * 100 + i) as u64 ;
1067
+ let result = rls. request :: < GotoDefinition > ( id, TextDocumentPositionParams {
1068
+ position : Position { line : line_index as u64 , character : i as u64 } ,
1069
+ text_document : TextDocumentIdentifier {
1070
+ uri : Url :: from_file_path ( p. root ( ) . join ( "src/main.rs" ) ) . unwrap ( ) ,
1071
+ }
1072
+ } ) ;
1073
+
1074
+ let ranges = result. into_iter ( ) . flat_map ( |x| match x {
1075
+ GotoDefinitionResponse :: Scalar ( loc) => vec ! [ loc] . into_iter ( ) ,
1076
+ GotoDefinitionResponse :: Array ( locs) => locs. into_iter ( ) ,
1077
+ _ => unreachable ! ( ) ,
1078
+ } ) . map ( |x| x. range ) . collect ( ) ;
1079
+
1080
+ if !results. is_empty ( ) {
1081
+ results. push ( ( line_index, i, ranges) ) ;
1082
+ }
1083
+ }
1084
+ }
1085
+ rls. shutdown ( ) ;
1086
+
1087
+ // Foo
1088
+ let foo_definition = Range {
1089
+ start : Position { line : 1 , character : 15 } ,
1090
+ end : Position { line : 1 , character : 18 }
1091
+ } ;
1092
+
1093
+ // Foo::new
1094
+ let foo_new_definition = Range {
1095
+ start : Position { line : 5 , character : 15 } ,
1096
+ end : Position { line : 5 , character : 18 }
1097
+ } ;
1098
+
1099
+ // main
1100
+ let main_definition = Range {
1101
+ start : Position { line : 9 , character : 11 } ,
1102
+ end : Position { line : 9 , character : 15 }
1103
+ } ;
1104
+
1105
+ let expected = [
1106
+ // struct Foo
1107
+ ( 1 , 15 , vec ! [ foo_definition. clone( ) ] ) ,
1108
+ ( 1 , 16 , vec ! [ foo_definition. clone( ) ] ) ,
1109
+ ( 1 , 17 , vec ! [ foo_definition. clone( ) ] ) ,
1110
+ ( 1 , 18 , vec ! [ foo_definition. clone( ) ] ) ,
1111
+ // impl Foo
1112
+ ( 4 , 13 , vec ! [ foo_definition. clone( ) ] ) ,
1113
+ ( 4 , 14 , vec ! [ foo_definition. clone( ) ] ) ,
1114
+ ( 4 , 15 , vec ! [ foo_definition. clone( ) ] ) ,
1115
+ ( 4 , 16 , vec ! [ foo_definition. clone( ) ] ) ,
1116
+
1117
+ // fn new
1118
+ ( 5 , 15 , vec ! [ foo_new_definition. clone( ) ] ) ,
1119
+ ( 5 , 16 , vec ! [ foo_new_definition. clone( ) ] ) ,
1120
+ ( 5 , 17 , vec ! [ foo_new_definition. clone( ) ] ) ,
1121
+ ( 5 , 18 , vec ! [ foo_new_definition. clone( ) ] ) ,
1122
+
1123
+ // fn main
1124
+ ( 9 , 11 , vec ! [ main_definition. clone( ) ] ) ,
1125
+ ( 9 , 12 , vec ! [ main_definition. clone( ) ] ) ,
1126
+ ( 9 , 13 , vec ! [ main_definition. clone( ) ] ) ,
1127
+ ( 9 , 14 , vec ! [ main_definition. clone( ) ] ) ,
1128
+ ( 9 , 15 , vec ! [ main_definition. clone( ) ] ) ,
1129
+
1130
+ // Foo::new()
1131
+ ( 10 , 12 , vec ! [ foo_definition. clone( ) ] ) ,
1132
+ ( 10 , 13 , vec ! [ foo_definition. clone( ) ] ) ,
1133
+ ( 10 , 14 , vec ! [ foo_definition. clone( ) ] ) ,
1134
+ ( 10 , 15 , vec ! [ foo_definition. clone( ) ] ) ,
1135
+ ( 10 , 17 , vec ! [ foo_new_definition. clone( ) ] ) ,
1136
+ ( 10 , 18 , vec ! [ foo_new_definition. clone( ) ] ) ,
1137
+ ( 10 , 19 , vec ! [ foo_new_definition. clone( ) ] ) ,
1138
+ ( 10 , 20 , vec ! [ foo_new_definition. clone( ) ] ) ,
1139
+ ] ;
1140
+
1141
+ if results. len ( ) != expected. len ( ) {
1142
+ panic ! (
1143
+ "Got different amount of completions than expected: {} vs. {}: {:#?}" ,
1144
+ results. len( ) ,
1145
+ expected. len( ) ,
1146
+ results
1147
+ )
1148
+ }
1149
+
1150
+ for ( i, ( actual, expected) ) in results. iter ( ) . zip ( expected. iter ( ) ) . enumerate ( ) {
1151
+ if actual != expected {
1152
+ panic ! (
1153
+ "Found different definition at index {}. Got {:#?}, expected {:#?}" ,
1154
+ i,
1155
+ actual,
1156
+ expected
1157
+ )
1158
+ }
1159
+ }
1160
+ }
0 commit comments