]> git.lizzy.rs Git - rust.git/blob - crates/ra_lsp_server/tests/heavy_tests/main.rs
translate \n -> \r\n on the way out
[rust.git] / crates / ra_lsp_server / tests / heavy_tests / main.rs
1 mod support;
2
3 use std::{collections::HashMap, time::Instant};
4
5 use lsp_types::{
6     CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions,
7     Position, Range, TextDocumentItem, TextDocumentPositionParams,
8 };
9 use ra_lsp_server::req::{
10     CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
11     Formatting, OnEnter, Runnables, RunnablesParams,
12 };
13 use serde_json::json;
14 use tempfile::TempDir;
15
16 use crate::support::{project, Project};
17
18 const LOG: &'static str = "";
19 const PROFILE: &'static str = "";
20 // const PROFILE: &'static str = "*@3>100";
21
22 #[test]
23 fn completes_items_from_standard_library() {
24     let project_start = Instant::now();
25     let server = Project::with_fixture(
26         r#"
27 //- Cargo.toml
28 [package]
29 name = "foo"
30 version = "0.0.0"
31
32 //- src/lib.rs
33 use std::collections::Spam;
34 "#,
35     )
36     .with_sysroot(true)
37     .server();
38     server.wait_until_workspace_is_loaded();
39     eprintln!("loading took    {:?}", project_start.elapsed());
40     let completion_start = Instant::now();
41     let res = server.send_request::<Completion>(CompletionParams {
42         text_document_position: TextDocumentPositionParams::new(
43             server.doc_id("src/lib.rs"),
44             Position::new(0, 23),
45         ),
46         context: None,
47     });
48     assert!(format!("{}", res).contains("HashMap"));
49     eprintln!("completion took {:?}", completion_start.elapsed());
50 }
51
52 #[test]
53 fn test_runnables_no_project() {
54     let server = project(
55         r"
56 //- lib.rs
57 #[test]
58 fn foo() {
59 }
60 ",
61     );
62     server.wait_until_workspace_is_loaded();
63     server.request::<Runnables>(
64         RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
65         json!([
66           {
67             "args": [ "test", "--", "foo", "--nocapture" ],
68             "bin": "cargo",
69             "env": { "RUST_BACKTRACE": "short" },
70             "cwd": null,
71             "label": "test foo",
72             "range": {
73               "end": { "character": 1, "line": 2 },
74               "start": { "character": 0, "line": 0 }
75             }
76           },
77           {
78             "args": [
79               "check",
80               "--all"
81             ],
82             "bin": "cargo",
83             "env": {},
84             "cwd": null,
85             "label": "cargo check --all",
86             "range": {
87               "end": {
88                 "character": 0,
89                 "line": 0
90               },
91               "start": {
92                 "character": 0,
93                 "line": 0
94               }
95             }
96           }
97         ]),
98     );
99 }
100
101 #[test]
102 fn test_runnables_project() {
103     let code = r#"
104 //- foo/Cargo.toml
105 [package]
106 name = "foo"
107 version = "0.0.0"
108
109 //- foo/src/lib.rs
110 pub fn foo() {}
111
112 //- foo/tests/spam.rs
113 #[test]
114 fn test_eggs() {}
115
116 //- bar/Cargo.toml
117 [package]
118 name = "bar"
119 version = "0.0.0"
120
121 //- bar/src/main.rs
122 fn main() {}
123 "#;
124
125     let server = Project::with_fixture(code).root("foo").root("bar").server();
126
127     server.wait_until_workspace_is_loaded();
128     server.request::<Runnables>(
129         RunnablesParams {
130             text_document: server.doc_id("foo/tests/spam.rs"),
131             position: None,
132         },
133         json!([
134           {
135             "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
136             "bin": "cargo",
137             "env": { "RUST_BACKTRACE": "short" },
138             "label": "test test_eggs",
139             "range": {
140               "end": { "character": 17, "line": 1 },
141               "start": { "character": 0, "line": 0 }
142             },
143             "cwd": server.path().join("foo")
144           },
145           {
146             "args": [
147               "check",
148               "--package",
149               "foo",
150               "--test",
151               "spam"
152             ],
153             "bin": "cargo",
154             "env": {},
155             "cwd": server.path().join("foo"),
156             "label": "cargo check -p foo",
157             "range": {
158               "end": {
159                 "character": 0,
160                 "line": 0
161               },
162               "start": {
163                 "character": 0,
164                 "line": 0
165               }
166             }
167           }
168         ])
169     );
170 }
171
172 #[test]
173 fn test_format_document() {
174     let server = project(
175         r#"
176 [package]
177 name = "foo"
178 version = "0.0.0"
179
180 //- src/lib.rs
181 mod bar;
182
183 fn main() {
184 }
185
186 pub use std::collections::HashMap;
187 "#,
188     );
189     server.wait_until_workspace_is_loaded();
190
191     server.request::<Formatting>(
192         DocumentFormattingParams {
193             text_document: server.doc_id("src/lib.rs"),
194             options: FormattingOptions {
195                 tab_size: 4,
196                 insert_spaces: false,
197                 properties: HashMap::new(),
198             },
199         },
200         json!([
201             {
202                 "newText": r#"mod bar;
203
204 fn main() {}
205
206 pub use std::collections::HashMap;
207 "#,
208                 "range": {
209                     "end": {
210                         "character": 0,
211                         "line": 7
212                     },
213                     "start": {
214                         "character": 0,
215                         "line": 0
216                     }
217                 }
218             }
219         ]),
220     );
221 }
222
223 #[test]
224 fn test_missing_module_code_action() {
225     let server = project(
226         r#"
227 //- Cargo.toml
228 [package]
229 name = "foo"
230 version = "0.0.0"
231
232 //- src/lib.rs
233 mod bar;
234
235 fn main() {}
236 "#,
237     );
238     server.wait_until_workspace_is_loaded();
239     let empty_context = || CodeActionContext { diagnostics: Vec::new(), only: None };
240     server.request::<CodeActionRequest>(
241         CodeActionParams {
242             text_document: server.doc_id("src/lib.rs"),
243             range: Range::new(Position::new(0, 4), Position::new(0, 7)),
244             context: empty_context(),
245         },
246         json!([
247           {
248             "command": {
249               "arguments": [
250                 {
251                   "cursorPosition": null,
252                   "label": "create module",
253                   "workspaceEdit": {
254                     "documentChanges": [
255                       {
256                         "kind": "create",
257                         "uri": "file:///[..]/src/bar.rs"
258                       }
259                     ]
260                   }
261                 }
262               ],
263               "command": "rust-analyzer.applySourceChange",
264               "title": "create module"
265             },
266             "title": "create module"
267           }
268         ]),
269     );
270
271     server.request::<CodeActionRequest>(
272         CodeActionParams {
273             text_document: server.doc_id("src/lib.rs"),
274             range: Range::new(Position::new(2, 4), Position::new(2, 7)),
275             context: empty_context(),
276         },
277         json!([]),
278     );
279 }
280
281 #[test]
282 fn test_missing_module_code_action_in_json_project() {
283     let tmp_dir = TempDir::new().unwrap();
284
285     let path = tmp_dir.path();
286
287     let project = json!({
288         "roots": [path],
289         "crates": [ { "root_module": path.join("src/lib.rs"), "deps": [], "edition": "2015" } ]
290     });
291
292     let code = format!(
293         r#"
294 //- rust-project.json
295 {PROJECT}
296
297 //- src/lib.rs
298 mod bar;
299
300 fn main() {{}}
301 "#,
302         PROJECT = project.to_string(),
303     );
304
305     let server = Project::with_fixture(&code).tmp_dir(tmp_dir).server();
306
307     server.wait_until_workspace_is_loaded();
308     let empty_context = || CodeActionContext { diagnostics: Vec::new(), only: None };
309     server.request::<CodeActionRequest>(
310         CodeActionParams {
311             text_document: server.doc_id("src/lib.rs"),
312             range: Range::new(Position::new(0, 4), Position::new(0, 7)),
313             context: empty_context(),
314         },
315         json!([
316           {
317             "command": {
318               "arguments": [
319                 {
320                   "cursorPosition": null,
321                   "label": "create module",
322                   "workspaceEdit": {
323                     "documentChanges": [
324                       {
325                         "kind": "create",
326                         "uri": "file:///[..]/src/bar.rs"
327                       }
328                     ]
329                   }
330                 }
331               ],
332               "command": "rust-analyzer.applySourceChange",
333               "title": "create module"
334             },
335             "title": "create module"
336           }
337         ]),
338     );
339
340     server.request::<CodeActionRequest>(
341         CodeActionParams {
342             text_document: server.doc_id("src/lib.rs"),
343             range: Range::new(Position::new(2, 4), Position::new(2, 7)),
344             context: empty_context(),
345         },
346         json!([]),
347     );
348 }
349
350 #[test]
351 fn diagnostics_dont_block_typing() {
352     let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect();
353     let libs: String = (0..10).map(|i| format!("//- src/m{}.rs\nfn foo() {{}}\n\n", i)).collect();
354     let server = Project::with_fixture(&format!(
355         r#"
356 //- Cargo.toml
357 [package]
358 name = "foo"
359 version = "0.0.0"
360
361 //- src/lib.rs
362 {}
363
364 {}
365
366 fn main() {{}}
367 "#,
368         librs, libs
369     ))
370     .with_sysroot(true)
371     .server();
372
373     server.wait_until_workspace_is_loaded();
374     for i in 0..10 {
375         server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
376             text_document: TextDocumentItem {
377                 uri: server.doc_id(&format!("src/m{}.rs", i)).uri,
378                 language_id: "rust".to_string(),
379                 version: 0,
380                 text: "/// Docs\nfn foo() {}".to_string(),
381             },
382         });
383     }
384     let start = std::time::Instant::now();
385     server.request::<OnEnter>(
386         TextDocumentPositionParams {
387             text_document: server.doc_id("src/m0.rs"),
388             position: Position { line: 0, character: 5 },
389         },
390         json!({
391           "cursorPosition": {
392             "position": { "character": 4, "line": 1 },
393             "textDocument": { "uri": "file:///[..]src/m0.rs" }
394           },
395           "label": "on enter",
396           "workspaceEdit": {
397             "documentChanges": [
398               {
399                 "edits": [
400                   {
401                     "newText": "\n/// ",
402                     "range": {
403                       "end": { "character": 5, "line": 0 },
404                       "start": { "character": 5, "line": 0 }
405                     }
406                   }
407                 ],
408                 "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null }
409               }
410             ]
411           }
412         }),
413     );
414     let elapsed = start.elapsed();
415     assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed);
416 }
417
418 #[test]
419 fn preserves_dos_line_endings() {
420     let server = Project::with_fixture(
421         &"
422 //- Cargo.toml
423 [package]
424 name = \"foo\"
425 version = \"0.0.0\"
426
427 //- src/main.rs
428 /// Some Docs\r\nfn main() {}
429 ",
430     )
431     .server();
432
433     server.request::<OnEnter>(
434         TextDocumentPositionParams {
435             text_document: server.doc_id("src/main.rs"),
436             position: Position { line: 0, character: 8 },
437         },
438         json!({
439           "cursorPosition": {
440             "position": { "line": 1, "character": 4 },
441             "textDocument": { "uri": "file:///[..]src/main.rs" }
442           },
443           "label": "on enter",
444           "workspaceEdit": {
445             "documentChanges": [
446               {
447                 "edits": [
448                   {
449                     "newText": "\r\n/// ",
450                     "range": {
451                       "end": { "line": 0, "character": 8 },
452                       "start": { "line": 0, "character": 8 }
453                     }
454                   }
455                 ],
456                 "textDocument": { "uri": "file:///[..]src/main.rs", "version": null }
457               }
458             ]
459           }
460         }),
461     );
462 }