diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/build.rs | 15 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 20 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/config.rs | 5 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 7 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 25 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 19 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 18 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/pending_requests.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/subscriptions.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/markdown.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 29 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/world.rs | 75 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/main.rs | 118 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/support.rs | 3 |
15 files changed, 277 insertions, 67 deletions
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 21aef842c..60cbc38a9 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -13,9 +13,8 @@ relative-path = "1.0.0" | |||
13 | serde_json = "1.0.34" | 13 | serde_json = "1.0.34" |
14 | serde = { version = "1.0.83", features = ["derive"] } | 14 | serde = { version = "1.0.83", features = ["derive"] } |
15 | crossbeam-channel = "0.4" | 15 | crossbeam-channel = "0.4" |
16 | flexi_logger = "0.14.0" | ||
17 | log = "0.4.3" | 16 | log = "0.4.3" |
18 | lsp-types = { version = "0.61.0", features = ["proposed"] } | 17 | lsp-types = { version = "0.66.0", features = ["proposed"] } |
19 | rustc-hash = "1.0" | 18 | rustc-hash = "1.0" |
20 | parking_lot = "0.10.0" | 19 | parking_lot = "0.10.0" |
21 | jod-thread = "0.1.0" | 20 | jod-thread = "0.1.0" |
@@ -27,6 +26,7 @@ lsp-server = "0.3.0" | |||
27 | ra_project_model = { path = "../ra_project_model" } | 26 | ra_project_model = { path = "../ra_project_model" } |
28 | ra_prof = { path = "../ra_prof" } | 27 | ra_prof = { path = "../ra_prof" } |
29 | ra_vfs_glob = { path = "../ra_vfs_glob" } | 28 | ra_vfs_glob = { path = "../ra_vfs_glob" } |
29 | env_logger = { version = "0.7.1", default-features = false, features = ["humantime"] } | ||
30 | 30 | ||
31 | [dev-dependencies] | 31 | [dev-dependencies] |
32 | tempfile = "3" | 32 | tempfile = "3" |
diff --git a/crates/ra_lsp_server/build.rs b/crates/ra_lsp_server/build.rs new file mode 100644 index 000000000..05f9772c0 --- /dev/null +++ b/crates/ra_lsp_server/build.rs | |||
@@ -0,0 +1,15 @@ | |||
1 | //! Just embed git-hash to `--version` | ||
2 | |||
3 | use std::process::Command; | ||
4 | |||
5 | fn main() { | ||
6 | let rev = rev().unwrap_or_else(|| "???????".to_string()); | ||
7 | println!("cargo:rustc-env=REV={}", rev) | ||
8 | } | ||
9 | |||
10 | fn rev() -> Option<String> { | ||
11 | let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().ok()?; | ||
12 | let stdout = String::from_utf8(output.stdout).ok()?; | ||
13 | let short_hash = stdout.get(0..7)?; | ||
14 | Some(short_hash.to_owned()) | ||
15 | } | ||
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index eea0965ed..eeca67ee1 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -1,11 +1,12 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Advertizes the capabilities of the LSP Server. |
2 | 2 | ||
3 | use lsp_types::{ | 3 | use lsp_types::{ |
4 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, | 4 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, |
5 | DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, | 5 | DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, |
6 | ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, | 6 | ImplementationProviderCapability, RenameOptions, RenameProviderCapability, |
7 | SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, | 7 | SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions, |
8 | TextDocumentSyncOptions, TypeDefinitionProviderCapability, | 8 | TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, |
9 | TypeDefinitionProviderCapability, WorkDoneProgressOptions, | ||
9 | }; | 10 | }; |
10 | 11 | ||
11 | pub fn server_capabilities() -> ServerCapabilities { | 12 | pub fn server_capabilities() -> ServerCapabilities { |
@@ -21,10 +22,14 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
21 | completion_provider: Some(CompletionOptions { | 22 | completion_provider: Some(CompletionOptions { |
22 | resolve_provider: None, | 23 | resolve_provider: None, |
23 | trigger_characters: Some(vec![":".to_string(), ".".to_string()]), | 24 | trigger_characters: Some(vec![":".to_string(), ".".to_string()]), |
25 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | ||
24 | }), | 26 | }), |
25 | signature_help_provider: Some(SignatureHelpOptions { | 27 | signature_help_provider: Some(SignatureHelpOptions { |
26 | trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), | 28 | trigger_characters: Some(vec!["(".to_string(), ",".to_string()]), |
29 | retrigger_characters: None, | ||
30 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | ||
27 | }), | 31 | }), |
32 | declaration_provider: None, | ||
28 | definition_provider: Some(true), | 33 | definition_provider: Some(true), |
29 | type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), | 34 | type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), |
30 | implementation_provider: Some(ImplementationProviderCapability::Simple(true)), | 35 | implementation_provider: Some(ImplementationProviderCapability::Simple(true)), |
@@ -40,10 +45,11 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
40 | first_trigger_character: "=".to_string(), | 45 | first_trigger_character: "=".to_string(), |
41 | more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), | 46 | more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), |
42 | }), | 47 | }), |
43 | selection_range_provider: Some(GenericCapability::default()), | 48 | selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), |
44 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | 49 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), |
45 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions { | 50 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions { |
46 | prepare_provider: Some(true), | 51 | prepare_provider: Some(true), |
52 | work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, | ||
47 | })), | 53 | })), |
48 | document_link_provider: None, | 54 | document_link_provider: None, |
49 | color_provider: None, | 55 | color_provider: None, |
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 8045f3d60..67942aa41 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
11 | 11 | ||
12 | use ra_project_model::CargoFeatures; | ||
12 | use serde::{Deserialize, Deserializer}; | 13 | use serde::{Deserialize, Deserializer}; |
13 | 14 | ||
14 | /// Client provided initialization options | 15 | /// Client provided initialization options |
@@ -37,6 +38,9 @@ pub struct ServerConfig { | |||
37 | 38 | ||
38 | /// Fine grained feature flags to disable specific features. | 39 | /// Fine grained feature flags to disable specific features. |
39 | pub feature_flags: FxHashMap<String, bool>, | 40 | pub feature_flags: FxHashMap<String, bool>, |
41 | |||
42 | /// Cargo feature configurations. | ||
43 | pub cargo_features: CargoFeatures, | ||
40 | } | 44 | } |
41 | 45 | ||
42 | impl Default for ServerConfig { | 46 | impl Default for ServerConfig { |
@@ -49,6 +53,7 @@ impl Default for ServerConfig { | |||
49 | max_inlay_hint_length: None, | 53 | max_inlay_hint_length: None, |
50 | with_sysroot: true, | 54 | with_sysroot: true, |
51 | feature_flags: FxHashMap::default(), | 55 | feature_flags: FxHashMap::default(), |
56 | cargo_features: Default::default(), | ||
52 | } | 57 | } |
53 | } | 58 | } |
54 | } | 59 | } |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index b13093cfe..e93d4ea33 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Convenience module responsible for translating between rust-analyzer's types and LSP types. |
2 | 2 | ||
3 | use lsp_types::{ | 3 | use lsp_types::{ |
4 | self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation, | 4 | self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation, |
@@ -130,6 +130,11 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { | |||
130 | deprecated: Some(self.deprecated()), | 130 | deprecated: Some(self.deprecated()), |
131 | ..Default::default() | 131 | ..Default::default() |
132 | }; | 132 | }; |
133 | |||
134 | if self.deprecated() { | ||
135 | res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated]) | ||
136 | } | ||
137 | |||
133 | res.insert_text_format = Some(match self.insert_text_format() { | 138 | res.insert_text_format = Some(match self.insert_text_format() { |
134 | InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet, | 139 | InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet, |
135 | InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText, | 140 | InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText, |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index e13c8ca14..cdd925c9f 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -1,24 +1,22 @@ | |||
1 | //! `ra_lsp_server` binary | 1 | //! `ra_lsp_server` binary |
2 | 2 | ||
3 | use flexi_logger::{Duplicate, Logger}; | ||
4 | use lsp_server::Connection; | 3 | use lsp_server::Connection; |
5 | use ra_lsp_server::{show_message, Result, ServerConfig}; | 4 | use ra_lsp_server::{show_message, Result, ServerConfig}; |
6 | use ra_prof; | 5 | use ra_prof; |
7 | 6 | ||
8 | fn main() -> Result<()> { | 7 | fn main() -> Result<()> { |
9 | setup_logging()?; | 8 | setup_logging()?; |
10 | run_server()?; | 9 | match Args::parse()? { |
10 | Args::Version => println!("rust-analyzer {}", env!("REV")), | ||
11 | Args::Run => run_server()?, | ||
12 | } | ||
11 | Ok(()) | 13 | Ok(()) |
12 | } | 14 | } |
13 | 15 | ||
14 | fn setup_logging() -> Result<()> { | 16 | fn setup_logging() -> Result<()> { |
15 | std::env::set_var("RUST_BACKTRACE", "short"); | 17 | std::env::set_var("RUST_BACKTRACE", "short"); |
16 | 18 | ||
17 | let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); | 19 | env_logger::try_init()?; |
18 | match std::env::var("RA_LOG_DIR") { | ||
19 | Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, | ||
20 | _ => logger.start()?, | ||
21 | }; | ||
22 | 20 | ||
23 | ra_prof::set_filter(match std::env::var("RA_PROFILE") { | 21 | ra_prof::set_filter(match std::env::var("RA_PROFILE") { |
24 | Ok(spec) => ra_prof::Filter::from_spec(&spec), | 22 | Ok(spec) => ra_prof::Filter::from_spec(&spec), |
@@ -27,6 +25,19 @@ fn setup_logging() -> Result<()> { | |||
27 | Ok(()) | 25 | Ok(()) |
28 | } | 26 | } |
29 | 27 | ||
28 | enum Args { | ||
29 | Version, | ||
30 | Run, | ||
31 | } | ||
32 | |||
33 | impl Args { | ||
34 | fn parse() -> Result<Args> { | ||
35 | let res = | ||
36 | if std::env::args().any(|it| it == "--version") { Args::Version } else { Args::Run }; | ||
37 | Ok(res) | ||
38 | } | ||
39 | } | ||
40 | |||
30 | fn run_server() -> Result<()> { | 41 | fn run_server() -> Result<()> { |
31 | log::info!("lifecycle: server started"); | 42 | log::info!("lifecycle: server started"); |
32 | 43 | ||
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 83845f1e0..dda318e43 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! The main loop of `ra_lsp_server` responsible for dispatching LSP requests/replies and |
2 | //! notifications back to the client. | ||
2 | 3 | ||
3 | mod handlers; | 4 | mod handlers; |
4 | mod subscriptions; | 5 | mod subscriptions; |
@@ -67,6 +68,7 @@ pub fn main_loop( | |||
67 | let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( | 68 | let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( |
68 | ws_root.as_path(), | 69 | ws_root.as_path(), |
69 | config.with_sysroot, | 70 | config.with_sysroot, |
71 | &config.cargo_features, | ||
70 | ); | 72 | ); |
71 | match workspace { | 73 | match workspace { |
72 | Ok(workspace) => loaded_workspaces.push(workspace), | 74 | Ok(workspace) => loaded_workspaces.push(workspace), |
@@ -130,7 +132,7 @@ pub fn main_loop( | |||
130 | let feature_flags = { | 132 | let feature_flags = { |
131 | let mut ff = FeatureFlags::default(); | 133 | let mut ff = FeatureFlags::default(); |
132 | for (flag, value) in config.feature_flags { | 134 | for (flag, value) in config.feature_flags { |
133 | if let Err(_) = ff.set(flag.as_str(), value) { | 135 | if ff.set(flag.as_str(), value).is_err() { |
134 | log::error!("unknown feature flag: {:?}", flag); | 136 | log::error!("unknown feature flag: {:?}", flag); |
135 | show_message( | 137 | show_message( |
136 | req::MessageType::Error, | 138 | req::MessageType::Error, |
@@ -303,7 +305,6 @@ fn loop_turn( | |||
303 | log::info!("queued count = {}", queue_count); | 305 | log::info!("queued count = {}", queue_count); |
304 | } | 306 | } |
305 | 307 | ||
306 | let mut state_changed = false; | ||
307 | match event { | 308 | match event { |
308 | Event::Task(task) => { | 309 | Event::Task(task) => { |
309 | on_task(task, &connection.sender, &mut loop_state.pending_requests, world_state); | 310 | on_task(task, &connection.sender, &mut loop_state.pending_requests, world_state); |
@@ -311,7 +312,6 @@ fn loop_turn( | |||
311 | } | 312 | } |
312 | Event::Vfs(task) => { | 313 | Event::Vfs(task) => { |
313 | world_state.vfs.write().handle_task(task); | 314 | world_state.vfs.write().handle_task(task); |
314 | state_changed = true; | ||
315 | } | 315 | } |
316 | Event::Lib(lib) => { | 316 | Event::Lib(lib) => { |
317 | world_state.add_lib(lib); | 317 | world_state.add_lib(lib); |
@@ -336,7 +336,6 @@ fn loop_turn( | |||
336 | &mut loop_state.subscriptions, | 336 | &mut loop_state.subscriptions, |
337 | not, | 337 | not, |
338 | )?; | 338 | )?; |
339 | state_changed = true; | ||
340 | } | 339 | } |
341 | Message::Response(resp) => { | 340 | Message::Response(resp) => { |
342 | let removed = loop_state.pending_responses.remove(&resp.id); | 341 | let removed = loop_state.pending_responses.remove(&resp.id); |
@@ -347,7 +346,12 @@ fn loop_turn( | |||
347 | }, | 346 | }, |
348 | }; | 347 | }; |
349 | 348 | ||
350 | loop_state.pending_libraries.extend(world_state.process_changes()); | 349 | let mut state_changed = false; |
350 | if let Some(changes) = world_state.process_changes() { | ||
351 | state_changed = true; | ||
352 | loop_state.pending_libraries.extend(changes); | ||
353 | } | ||
354 | |||
351 | while loop_state.in_flight_libraries < MAX_IN_FLIGHT_LIBS | 355 | while loop_state.in_flight_libraries < MAX_IN_FLIGHT_LIBS |
352 | && !loop_state.pending_libraries.is_empty() | 356 | && !loop_state.pending_libraries.is_empty() |
353 | { | 357 | { |
@@ -520,7 +524,8 @@ fn on_notification( | |||
520 | if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { | 524 | if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { |
521 | subs.remove_sub(FileId(file_id.0)); | 525 | subs.remove_sub(FileId(file_id.0)); |
522 | } | 526 | } |
523 | let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; | 527 | let params = |
528 | req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; | ||
524 | let not = notification_new::<req::PublishDiagnostics>(params); | 529 | let not = notification_new::<req::PublishDiagnostics>(params); |
525 | msg_sender.send(not.into()).unwrap(); | 530 | msg_sender.send(not.into()).unwrap(); |
526 | return Ok(()); | 531 | return Ok(()); |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index c81fa7f67..39eb3df3e 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! This module is responsible for implementing handlers for Lanuage Server Protocol. |
2 | //! The majority of requests are fulfilled by calling into the `ra_ide` crate. | ||
2 | 3 | ||
3 | use std::{fmt::Write as _, io::Write as _}; | 4 | use std::{fmt::Write as _, io::Write as _}; |
4 | 5 | ||
@@ -164,7 +165,7 @@ pub fn handle_on_type_formatting( | |||
164 | 165 | ||
165 | // in `ra_ide`, the `on_type` invariant is that | 166 | // in `ra_ide`, the `on_type` invariant is that |
166 | // `text.char_at(position) == typed_char`. | 167 | // `text.char_at(position) == typed_char`. |
167 | position.offset = position.offset - TextUnit::of_char('.'); | 168 | position.offset -= TextUnit::of_char('.'); |
168 | let char_typed = params.ch.chars().next().unwrap_or('\0'); | 169 | let char_typed = params.ch.chars().next().unwrap_or('\0'); |
169 | 170 | ||
170 | // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, | 171 | // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, |
@@ -480,8 +481,6 @@ pub fn handle_prepare_rename( | |||
480 | let _p = profile("handle_prepare_rename"); | 481 | let _p = profile("handle_prepare_rename"); |
481 | let position = params.try_conv_with(&world)?; | 482 | let position = params.try_conv_with(&world)?; |
482 | 483 | ||
483 | // We support renaming references like handle_rename does. | ||
484 | // In the future we may want to reject the renaming of things like keywords here too. | ||
485 | let optional_change = world.analysis().rename(position, "dummy")?; | 484 | let optional_change = world.analysis().rename(position, "dummy")?; |
486 | let range = match optional_change { | 485 | let range = match optional_change { |
487 | None => return Ok(None), | 486 | None => return Ok(None), |
@@ -557,12 +556,18 @@ pub fn handle_formatting( | |||
557 | let _p = profile("handle_formatting"); | 556 | let _p = profile("handle_formatting"); |
558 | let file_id = params.text_document.try_conv_with(&world)?; | 557 | let file_id = params.text_document.try_conv_with(&world)?; |
559 | let file = world.analysis().file_text(file_id)?; | 558 | let file = world.analysis().file_text(file_id)?; |
559 | let crate_ids = world.analysis().crate_for(file_id)?; | ||
560 | 560 | ||
561 | let file_line_index = world.analysis().file_line_index(file_id)?; | 561 | let file_line_index = world.analysis().file_line_index(file_id)?; |
562 | let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); | 562 | let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); |
563 | 563 | ||
564 | use std::process; | 564 | use std::process; |
565 | let mut rustfmt = process::Command::new("rustfmt"); | 565 | let mut rustfmt = process::Command::new("rustfmt"); |
566 | if let Some(&crate_id) = crate_ids.first() { | ||
567 | // Assume all crates are in the same edition | ||
568 | let edition = world.analysis().crate_edition(crate_id)?; | ||
569 | rustfmt.args(&["--edition", &edition.to_string()]); | ||
570 | } | ||
566 | rustfmt.stdin(process::Stdio::piped()).stdout(process::Stdio::piped()); | 571 | rustfmt.stdin(process::Stdio::piped()).stdout(process::Stdio::piped()); |
567 | 572 | ||
568 | if let Ok(path) = params.text_document.uri.to_file_path() { | 573 | if let Ok(path) = params.text_document.uri.to_file_path() { |
@@ -644,6 +649,7 @@ pub fn handle_code_action( | |||
644 | diagnostics: None, | 649 | diagnostics: None, |
645 | edit: None, | 650 | edit: None, |
646 | command: Some(command), | 651 | command: Some(command), |
652 | is_preferred: None, | ||
647 | }; | 653 | }; |
648 | res.push(action.into()); | 654 | res.push(action.into()); |
649 | } | 655 | } |
@@ -666,6 +672,7 @@ pub fn handle_code_action( | |||
666 | diagnostics: None, | 672 | diagnostics: None, |
667 | edit: None, | 673 | edit: None, |
668 | command: Some(command), | 674 | command: Some(command), |
675 | is_preferred: None, | ||
669 | }; | 676 | }; |
670 | res.push(action.into()); | 677 | res.push(action.into()); |
671 | } | 678 | } |
@@ -824,9 +831,10 @@ pub fn publish_diagnostics( | |||
824 | source: Some("rust-analyzer".to_string()), | 831 | source: Some("rust-analyzer".to_string()), |
825 | message: d.message, | 832 | message: d.message, |
826 | related_information: None, | 833 | related_information: None, |
834 | tags: None, | ||
827 | }) | 835 | }) |
828 | .collect(); | 836 | .collect(); |
829 | Ok(req::PublishDiagnosticsParams { uri, diagnostics }) | 837 | Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) |
830 | } | 838 | } |
831 | 839 | ||
832 | pub fn publish_decorations( | 840 | pub fn publish_decorations( |
diff --git a/crates/ra_lsp_server/src/main_loop/pending_requests.rs b/crates/ra_lsp_server/src/main_loop/pending_requests.rs index e7ea7aa5b..2d2213464 100644 --- a/crates/ra_lsp_server/src/main_loop/pending_requests.rs +++ b/crates/ra_lsp_server/src/main_loop/pending_requests.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Datastructures that keep track of inflight requests. |
2 | 2 | ||
3 | use std::time::{Duration, Instant}; | 3 | use std::time::{Duration, Instant}; |
4 | 4 | ||
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs index 609b2adcc..b0bae90f5 100644 --- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs +++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Keeps track of file subscriptions. |
2 | 2 | ||
3 | use ra_ide::FileId; | 3 | use ra_ide::FileId; |
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs index f51fc4ade..76bef45cc 100644 --- a/crates/ra_lsp_server/src/markdown.rs +++ b/crates/ra_lsp_server/src/markdown.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Transforms markdown |
2 | 2 | ||
3 | pub(crate) fn format_docs(src: &str) -> String { | 3 | pub(crate) fn format_docs(src: &str) -> String { |
4 | let mut processed_lines = Vec::new(); | 4 | let mut processed_lines = Vec::new(); |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 39361b7e8..b34e6f9b8 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Defines `rust-analyzer` specific custom messages. |
2 | 2 | ||
3 | use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; | 3 | use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; |
4 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
@@ -10,8 +10,9 @@ pub use lsp_types::{ | |||
10 | DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, | 10 | DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, |
11 | DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, | 11 | DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, |
12 | FileSystemWatcher, Hover, InitializeResult, MessageType, PublishDiagnosticsParams, | 12 | FileSystemWatcher, Hover, InitializeResult, MessageType, PublishDiagnosticsParams, |
13 | ReferenceParams, Registration, RegistrationParams, ShowMessageParams, SignatureHelp, | 13 | ReferenceParams, Registration, RegistrationParams, SelectionRange, SelectionRangeParams, |
14 | TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, | 14 | ShowMessageParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, TextEdit, |
15 | WorkspaceEdit, WorkspaceSymbolParams, | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | pub enum AnalyzerStatus {} | 18 | pub enum AnalyzerStatus {} |
@@ -67,28 +68,6 @@ pub struct ExpandMacroParams { | |||
67 | pub position: Option<Position>, | 68 | pub position: Option<Position>, |
68 | } | 69 | } |
69 | 70 | ||
70 | pub enum SelectionRangeRequest {} | ||
71 | |||
72 | impl Request for SelectionRangeRequest { | ||
73 | type Params = SelectionRangeParams; | ||
74 | type Result = Vec<SelectionRange>; | ||
75 | const METHOD: &'static str = "textDocument/selectionRange"; | ||
76 | } | ||
77 | |||
78 | #[derive(Deserialize, Debug)] | ||
79 | #[serde(rename_all = "camelCase")] | ||
80 | pub struct SelectionRangeParams { | ||
81 | pub text_document: TextDocumentIdentifier, | ||
82 | pub positions: Vec<Position>, | ||
83 | } | ||
84 | |||
85 | #[derive(Serialize, Debug)] | ||
86 | #[serde(rename_all = "camelCase")] | ||
87 | pub struct SelectionRange { | ||
88 | pub range: Range, | ||
89 | pub parent: Option<Box<SelectionRange>>, | ||
90 | } | ||
91 | |||
92 | pub enum FindMatchingBrace {} | 71 | pub enum FindMatchingBrace {} |
93 | 72 | ||
94 | impl Request for FindMatchingBrace { | 73 | impl Request for FindMatchingBrace { |
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 927449b45..79431e7e6 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! The context or environment in which the language server functions. |
2 | //! In our server implementation this is know as the `WorldState`. | ||
3 | //! | ||
4 | //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. | ||
2 | 5 | ||
3 | use std::{ | 6 | use std::{ |
4 | path::{Path, PathBuf}, | 7 | path::{Path, PathBuf}, |
@@ -17,11 +20,13 @@ use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; | |||
17 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; | 20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; |
18 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; | 21 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; |
19 | use relative_path::RelativePathBuf; | 22 | use relative_path::RelativePathBuf; |
23 | use std::path::{Component, Prefix}; | ||
20 | 24 | ||
21 | use crate::{ | 25 | use crate::{ |
22 | main_loop::pending_requests::{CompletedRequest, LatestRequests}, | 26 | main_loop::pending_requests::{CompletedRequest, LatestRequests}, |
23 | LspError, Result, | 27 | LspError, Result, |
24 | }; | 28 | }; |
29 | use std::str::FromStr; | ||
25 | 30 | ||
26 | #[derive(Debug, Clone)] | 31 | #[derive(Debug, Clone)] |
27 | pub struct Options { | 32 | pub struct Options { |
@@ -140,10 +145,10 @@ impl WorldState { | |||
140 | /// FIXME: better API here | 145 | /// FIXME: better API here |
141 | pub fn process_changes( | 146 | pub fn process_changes( |
142 | &mut self, | 147 | &mut self, |
143 | ) -> Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)> { | 148 | ) -> Option<Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>> { |
144 | let changes = self.vfs.write().commit_changes(); | 149 | let changes = self.vfs.write().commit_changes(); |
145 | if changes.is_empty() { | 150 | if changes.is_empty() { |
146 | return Vec::new(); | 151 | return None; |
147 | } | 152 | } |
148 | let mut libs = Vec::new(); | 153 | let mut libs = Vec::new(); |
149 | let mut change = AnalysisChange::new(); | 154 | let mut change = AnalysisChange::new(); |
@@ -177,7 +182,7 @@ impl WorldState { | |||
177 | } | 182 | } |
178 | } | 183 | } |
179 | self.analysis_host.apply_change(change); | 184 | self.analysis_host.apply_change(change); |
180 | libs | 185 | Some(libs) |
181 | } | 186 | } |
182 | 187 | ||
183 | pub fn add_lib(&mut self, data: LibraryData) { | 188 | pub fn add_lib(&mut self, data: LibraryData) { |
@@ -233,8 +238,8 @@ impl WorldSnapshot { | |||
233 | 238 | ||
234 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { | 239 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { |
235 | let path = self.vfs.read().file2path(VfsFile(id.0)); | 240 | let path = self.vfs.read().file2path(VfsFile(id.0)); |
236 | let url = Url::from_file_path(&path) | 241 | let url = url_from_path_with_drive_lowercasing(path)?; |
237 | .map_err(|_| format!("can't convert path to url: {}", path.display()))?; | 242 | |
238 | Ok(url) | 243 | Ok(url) |
239 | } | 244 | } |
240 | 245 | ||
@@ -279,3 +284,61 @@ impl WorldSnapshot { | |||
279 | self.analysis.feature_flags() | 284 | self.analysis.feature_flags() |
280 | } | 285 | } |
281 | } | 286 | } |
287 | |||
288 | /// Returns a `Url` object from a given path, will lowercase drive letters if present. | ||
289 | /// This will only happen when processing windows paths. | ||
290 | /// | ||
291 | /// When processing non-windows path, this is essentially the same as `Url::from_file_path`. | ||
292 | fn url_from_path_with_drive_lowercasing(path: impl AsRef<Path>) -> Result<Url> { | ||
293 | let component_has_windows_drive = path.as_ref().components().any(|comp| { | ||
294 | if let Component::Prefix(c) = comp { | ||
295 | match c.kind() { | ||
296 | Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true, | ||
297 | _ => return false, | ||
298 | } | ||
299 | } | ||
300 | false | ||
301 | }); | ||
302 | |||
303 | // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters. | ||
304 | if component_has_windows_drive { | ||
305 | let url_original = Url::from_file_path(&path) | ||
306 | .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?; | ||
307 | |||
308 | let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect(); | ||
309 | |||
310 | // There is a drive partition, but we never found a colon. | ||
311 | // This should not happen, but in this case we just pass it through. | ||
312 | if drive_partition.len() == 1 { | ||
313 | return Ok(url_original); | ||
314 | } | ||
315 | |||
316 | let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; | ||
317 | let url = Url::from_str(&joined).expect("This came from a valid `Url`"); | ||
318 | |||
319 | Ok(url) | ||
320 | } else { | ||
321 | Ok(Url::from_file_path(&path) | ||
322 | .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?) | ||
323 | } | ||
324 | } | ||
325 | |||
326 | // `Url` is not able to parse windows paths on unix machines. | ||
327 | #[cfg(target_os = "windows")] | ||
328 | #[cfg(test)] | ||
329 | mod path_conversion_windows_tests { | ||
330 | use super::url_from_path_with_drive_lowercasing; | ||
331 | #[test] | ||
332 | fn test_lowercase_drive_letter_with_drive() { | ||
333 | let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); | ||
334 | |||
335 | assert_eq!(url.to_string(), "file:///c:/Test"); | ||
336 | } | ||
337 | |||
338 | #[test] | ||
339 | fn test_drive_without_colon_passthrough() { | ||
340 | let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); | ||
341 | |||
342 | assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); | ||
343 | } | ||
344 | } | ||
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index 2ba82ab05..dff63a12d 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs | |||
@@ -4,7 +4,8 @@ use std::{collections::HashMap, time::Instant}; | |||
4 | 4 | ||
5 | use lsp_types::{ | 5 | use lsp_types::{ |
6 | CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, | 6 | CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, |
7 | Position, Range, TextDocumentItem, TextDocumentPositionParams, | 7 | PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, |
8 | WorkDoneProgressParams, | ||
8 | }; | 9 | }; |
9 | use ra_lsp_server::req::{ | 10 | use ra_lsp_server::req::{ |
10 | CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, | 11 | CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, |
@@ -12,15 +13,19 @@ use ra_lsp_server::req::{ | |||
12 | }; | 13 | }; |
13 | use serde_json::json; | 14 | use serde_json::json; |
14 | use tempfile::TempDir; | 15 | use tempfile::TempDir; |
16 | use test_utils::skip_slow_tests; | ||
15 | 17 | ||
16 | use crate::support::{project, Project}; | 18 | use crate::support::{project, Project}; |
17 | 19 | ||
18 | const LOG: &'static str = ""; | ||
19 | const PROFILE: &'static str = ""; | 20 | const PROFILE: &'static str = ""; |
20 | // const PROFILE: &'static str = "*@3>100"; | 21 | // const PROFILE: &'static str = "*@3>100"; |
21 | 22 | ||
22 | #[test] | 23 | #[test] |
23 | fn completes_items_from_standard_library() { | 24 | fn completes_items_from_standard_library() { |
25 | if skip_slow_tests() { | ||
26 | return; | ||
27 | } | ||
28 | |||
24 | let project_start = Instant::now(); | 29 | let project_start = Instant::now(); |
25 | let server = Project::with_fixture( | 30 | let server = Project::with_fixture( |
26 | r#" | 31 | r#" |
@@ -44,6 +49,8 @@ use std::collections::Spam; | |||
44 | Position::new(0, 23), | 49 | Position::new(0, 23), |
45 | ), | 50 | ), |
46 | context: None, | 51 | context: None, |
52 | partial_result_params: PartialResultParams::default(), | ||
53 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
47 | }); | 54 | }); |
48 | assert!(format!("{}", res).contains("HashMap")); | 55 | assert!(format!("{}", res).contains("HashMap")); |
49 | eprintln!("completion took {:?}", completion_start.elapsed()); | 56 | eprintln!("completion took {:?}", completion_start.elapsed()); |
@@ -51,6 +58,10 @@ use std::collections::Spam; | |||
51 | 58 | ||
52 | #[test] | 59 | #[test] |
53 | fn test_runnables_no_project() { | 60 | fn test_runnables_no_project() { |
61 | if skip_slow_tests() { | ||
62 | return; | ||
63 | } | ||
64 | |||
54 | let server = project( | 65 | let server = project( |
55 | r" | 66 | r" |
56 | //- lib.rs | 67 | //- lib.rs |
@@ -100,6 +111,10 @@ fn foo() { | |||
100 | 111 | ||
101 | #[test] | 112 | #[test] |
102 | fn test_runnables_project() { | 113 | fn test_runnables_project() { |
114 | if skip_slow_tests() { | ||
115 | return; | ||
116 | } | ||
117 | |||
103 | let code = r#" | 118 | let code = r#" |
104 | //- foo/Cargo.toml | 119 | //- foo/Cargo.toml |
105 | [package] | 120 | [package] |
@@ -171,8 +186,13 @@ fn main() {} | |||
171 | 186 | ||
172 | #[test] | 187 | #[test] |
173 | fn test_format_document() { | 188 | fn test_format_document() { |
189 | if skip_slow_tests() { | ||
190 | return; | ||
191 | } | ||
192 | |||
174 | let server = project( | 193 | let server = project( |
175 | r#" | 194 | r#" |
195 | //- Cargo.toml | ||
176 | [package] | 196 | [package] |
177 | name = "foo" | 197 | name = "foo" |
178 | version = "0.0.0" | 198 | version = "0.0.0" |
@@ -194,8 +214,12 @@ pub use std::collections::HashMap; | |||
194 | options: FormattingOptions { | 214 | options: FormattingOptions { |
195 | tab_size: 4, | 215 | tab_size: 4, |
196 | insert_spaces: false, | 216 | insert_spaces: false, |
217 | insert_final_newline: None, | ||
218 | trim_final_newlines: None, | ||
219 | trim_trailing_whitespace: None, | ||
197 | properties: HashMap::new(), | 220 | properties: HashMap::new(), |
198 | }, | 221 | }, |
222 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
199 | }, | 223 | }, |
200 | json!([ | 224 | json!([ |
201 | { | 225 | { |
@@ -221,7 +245,77 @@ pub use std::collections::HashMap; | |||
221 | } | 245 | } |
222 | 246 | ||
223 | #[test] | 247 | #[test] |
248 | fn test_format_document_2018() { | ||
249 | if skip_slow_tests() { | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | let server = project( | ||
254 | r#" | ||
255 | //- Cargo.toml | ||
256 | [package] | ||
257 | name = "foo" | ||
258 | version = "0.0.0" | ||
259 | edition = "2018" | ||
260 | |||
261 | //- src/lib.rs | ||
262 | mod bar; | ||
263 | |||
264 | async fn test() { | ||
265 | } | ||
266 | |||
267 | fn main() { | ||
268 | } | ||
269 | |||
270 | pub use std::collections::HashMap; | ||
271 | "#, | ||
272 | ); | ||
273 | server.wait_until_workspace_is_loaded(); | ||
274 | |||
275 | server.request::<Formatting>( | ||
276 | DocumentFormattingParams { | ||
277 | text_document: server.doc_id("src/lib.rs"), | ||
278 | options: FormattingOptions { | ||
279 | tab_size: 4, | ||
280 | insert_spaces: false, | ||
281 | properties: HashMap::new(), | ||
282 | insert_final_newline: None, | ||
283 | trim_final_newlines: None, | ||
284 | trim_trailing_whitespace: None, | ||
285 | }, | ||
286 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
287 | }, | ||
288 | json!([ | ||
289 | { | ||
290 | "newText": r#"mod bar; | ||
291 | |||
292 | async fn test() {} | ||
293 | |||
294 | fn main() {} | ||
295 | |||
296 | pub use std::collections::HashMap; | ||
297 | "#, | ||
298 | "range": { | ||
299 | "end": { | ||
300 | "character": 0, | ||
301 | "line": 10 | ||
302 | }, | ||
303 | "start": { | ||
304 | "character": 0, | ||
305 | "line": 0 | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | ]), | ||
310 | ); | ||
311 | } | ||
312 | |||
313 | #[test] | ||
224 | fn test_missing_module_code_action() { | 314 | fn test_missing_module_code_action() { |
315 | if skip_slow_tests() { | ||
316 | return; | ||
317 | } | ||
318 | |||
225 | let server = project( | 319 | let server = project( |
226 | r#" | 320 | r#" |
227 | //- Cargo.toml | 321 | //- Cargo.toml |
@@ -242,6 +336,8 @@ fn main() {} | |||
242 | text_document: server.doc_id("src/lib.rs"), | 336 | text_document: server.doc_id("src/lib.rs"), |
243 | range: Range::new(Position::new(0, 4), Position::new(0, 7)), | 337 | range: Range::new(Position::new(0, 4), Position::new(0, 7)), |
244 | context: empty_context(), | 338 | context: empty_context(), |
339 | partial_result_params: PartialResultParams::default(), | ||
340 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
245 | }, | 341 | }, |
246 | json!([ | 342 | json!([ |
247 | { | 343 | { |
@@ -273,6 +369,8 @@ fn main() {} | |||
273 | text_document: server.doc_id("src/lib.rs"), | 369 | text_document: server.doc_id("src/lib.rs"), |
274 | range: Range::new(Position::new(2, 4), Position::new(2, 7)), | 370 | range: Range::new(Position::new(2, 4), Position::new(2, 7)), |
275 | context: empty_context(), | 371 | context: empty_context(), |
372 | partial_result_params: PartialResultParams::default(), | ||
373 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
276 | }, | 374 | }, |
277 | json!([]), | 375 | json!([]), |
278 | ); | 376 | ); |
@@ -280,6 +378,10 @@ fn main() {} | |||
280 | 378 | ||
281 | #[test] | 379 | #[test] |
282 | fn test_missing_module_code_action_in_json_project() { | 380 | fn test_missing_module_code_action_in_json_project() { |
381 | if skip_slow_tests() { | ||
382 | return; | ||
383 | } | ||
384 | |||
283 | let tmp_dir = TempDir::new().unwrap(); | 385 | let tmp_dir = TempDir::new().unwrap(); |
284 | 386 | ||
285 | let path = tmp_dir.path(); | 387 | let path = tmp_dir.path(); |
@@ -317,6 +419,8 @@ fn main() {{}} | |||
317 | text_document: server.doc_id("src/lib.rs"), | 419 | text_document: server.doc_id("src/lib.rs"), |
318 | range: Range::new(Position::new(0, 4), Position::new(0, 7)), | 420 | range: Range::new(Position::new(0, 4), Position::new(0, 7)), |
319 | context: empty_context(), | 421 | context: empty_context(), |
422 | partial_result_params: PartialResultParams::default(), | ||
423 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
320 | }, | 424 | }, |
321 | json!([ | 425 | json!([ |
322 | { | 426 | { |
@@ -348,6 +452,8 @@ fn main() {{}} | |||
348 | text_document: server.doc_id("src/lib.rs"), | 452 | text_document: server.doc_id("src/lib.rs"), |
349 | range: Range::new(Position::new(2, 4), Position::new(2, 7)), | 453 | range: Range::new(Position::new(2, 4), Position::new(2, 7)), |
350 | context: empty_context(), | 454 | context: empty_context(), |
455 | partial_result_params: PartialResultParams::default(), | ||
456 | work_done_progress_params: WorkDoneProgressParams::default(), | ||
351 | }, | 457 | }, |
352 | json!([]), | 458 | json!([]), |
353 | ); | 459 | ); |
@@ -355,6 +461,10 @@ fn main() {{}} | |||
355 | 461 | ||
356 | #[test] | 462 | #[test] |
357 | fn diagnostics_dont_block_typing() { | 463 | fn diagnostics_dont_block_typing() { |
464 | if skip_slow_tests() { | ||
465 | return; | ||
466 | } | ||
467 | |||
358 | let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect(); | 468 | let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect(); |
359 | let libs: String = (0..10).map(|i| format!("//- src/m{}.rs\nfn foo() {{}}\n\n", i)).collect(); | 469 | let libs: String = (0..10).map(|i| format!("//- src/m{}.rs\nfn foo() {{}}\n\n", i)).collect(); |
360 | let server = Project::with_fixture(&format!( | 470 | let server = Project::with_fixture(&format!( |
@@ -423,6 +533,10 @@ fn main() {{}} | |||
423 | 533 | ||
424 | #[test] | 534 | #[test] |
425 | fn preserves_dos_line_endings() { | 535 | fn preserves_dos_line_endings() { |
536 | if skip_slow_tests() { | ||
537 | return; | ||
538 | } | ||
539 | |||
426 | let server = Project::with_fixture( | 540 | let server = Project::with_fixture( |
427 | &" | 541 | &" |
428 | //- Cargo.toml | 542 | //- Cargo.toml |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index 86073b57d..d5ea52fa9 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs | |||
@@ -7,7 +7,6 @@ use std::{ | |||
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crossbeam_channel::{after, select, Receiver}; | 9 | use crossbeam_channel::{after, select, Receiver}; |
10 | use flexi_logger::Logger; | ||
11 | use lsp_server::{Connection, Message, Notification, Request}; | 10 | use lsp_server::{Connection, Message, Notification, Request}; |
12 | use lsp_types::{ | 11 | use lsp_types::{ |
13 | notification::{DidOpenTextDocument, Exit}, | 12 | notification::{DidOpenTextDocument, Exit}, |
@@ -53,7 +52,7 @@ impl<'a> Project<'a> { | |||
53 | let tmp_dir = self.tmp_dir.unwrap_or_else(|| TempDir::new().unwrap()); | 52 | let tmp_dir = self.tmp_dir.unwrap_or_else(|| TempDir::new().unwrap()); |
54 | static INIT: Once = Once::new(); | 53 | static INIT: Once = Once::new(); |
55 | INIT.call_once(|| { | 54 | INIT.call_once(|| { |
56 | let _ = Logger::with_env_or_str(crate::LOG).start().unwrap(); | 55 | let _ = env_logger::builder().is_test(true).try_init().unwrap(); |
57 | ra_prof::set_filter(if crate::PROFILE.is_empty() { | 56 | ra_prof::set_filter(if crate::PROFILE.is_empty() { |
58 | ra_prof::Filter::disabled() | 57 | ra_prof::Filter::disabled() |
59 | } else { | 58 | } else { |