Move LSP bits from flycheck to rust-analyzer

There should be only one place that knows about LSP, and that place is
right before we spit JSON on stdout.
This commit is contained in:
Aleksey Kladov 2020-05-15 01:51:48 +02:00
parent 12d82687cd
commit 220813dcb0
18 changed files with 1505 additions and 1506 deletions

View file

@ -29,6 +29,7 @@ rustc-hash = "1.1.0"
serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0.48"
threadpool = "1.7.1"
cargo_metadata = "0.10.0"
stdx = { path = "../stdx" }
@ -53,6 +54,7 @@ winapi = "0.3.8"
[dev-dependencies]
tempfile = "3.1.0"
insta = "0.16.0"
test_utils = { path = "../test_utils" }
[features]

View file

@ -1,4 +1,5 @@
//! Book keeping for keeping diagnostics easily in sync with the client.
pub(crate) mod to_proto;
use std::{collections::HashMap, sync::Arc};

View file

@ -0,0 +1,83 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/mir/tagset.rs",
range: Range {
start: Position {
line: 41,
character: 23,
},
end: Position {
line: 41,
character: 28,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 41,
character: 23,
},
end: Position {
line: 41,
character: 28,
},
},
severity: Some(
Warning,
),
code: Some(
String(
"trivially_copy_pass_by_ref",
),
),
source: Some(
"clippy",
),
message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
related_information: Some(
[
DiagnosticRelatedInformation {
location: Location {
uri: "file:///test/compiler/lib.rs",
range: Range {
start: Position {
line: 0,
character: 8,
},
end: Position {
line: 0,
character: 19,
},
},
},
message: "lint level defined here",
},
DiagnosticRelatedInformation {
location: Location {
uri: "file:///test/compiler/mir/tagset.rs",
range: Range {
start: Position {
line: 41,
character: 23,
},
end: Position {
line: 41,
character: 28,
},
},
},
message: "consider passing by value instead",
},
],
),
tags: None,
},
fixes: [],
},
]

View file

@ -0,0 +1,48 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/src/main.rs",
range: Range {
start: Position {
line: 1,
character: 4,
},
end: Position {
line: 1,
character: 26,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 1,
character: 4,
},
end: Position {
line: 1,
character: 26,
},
},
severity: Some(
Error,
),
code: Some(
String(
"E0277",
),
),
source: Some(
"rustc",
),
message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
related_information: None,
tags: None,
},
fixes: [],
},
]

View file

@ -0,0 +1,63 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/crates/ra_hir_def/src/data.rs",
range: Range {
start: Position {
line: 79,
character: 15,
},
end: Position {
line: 79,
character: 41,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 79,
character: 15,
},
end: Position {
line: 79,
character: 41,
},
},
severity: Some(
Error,
),
code: None,
source: Some(
"rustc",
),
message: "Please register your known path in the path module",
related_information: Some(
[
DiagnosticRelatedInformation {
location: Location {
uri: "file:///test/crates/ra_hir_def/src/path.rs",
range: Range {
start: Position {
line: 264,
character: 8,
},
end: Position {
line: 264,
character: 76,
},
},
},
message: "Error originated from macro here",
},
],
),
tags: None,
},
fixes: [],
},
]

View file

@ -0,0 +1,114 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/src/main.rs",
range: Range {
start: Position {
line: 3,
character: 4,
},
end: Position {
line: 3,
character: 5,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 3,
character: 4,
},
end: Position {
line: 3,
character: 5,
},
},
severity: Some(
Warning,
),
code: Some(
String(
"let_and_return",
),
),
source: Some(
"clippy",
),
message: "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return",
related_information: Some(
[
DiagnosticRelatedInformation {
location: Location {
uri: "file:///test/src/main.rs",
range: Range {
start: Position {
line: 2,
character: 4,
},
end: Position {
line: 2,
character: 30,
},
},
},
message: "unnecessary let binding",
},
],
),
tags: None,
},
fixes: [
CodeAction {
title: "return the expression directly",
kind: Some(
"quickfix",
),
diagnostics: None,
edit: Some(
WorkspaceEdit {
changes: Some(
{
"file:///test/src/main.rs": [
TextEdit {
range: Range {
start: Position {
line: 2,
character: 4,
},
end: Position {
line: 2,
character: 30,
},
},
new_text: "",
},
TextEdit {
range: Range {
start: Position {
line: 3,
character: 4,
},
end: Position {
line: 3,
character: 5,
},
},
new_text: "(0..10).collect()",
},
],
},
),
document_changes: None,
},
),
command: None,
is_preferred: None,
},
],
},
]

View file

@ -0,0 +1,48 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/ty/list_iter.rs",
range: Range {
start: Position {
line: 51,
character: 4,
},
end: Position {
line: 51,
character: 47,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 51,
character: 4,
},
end: Position {
line: 51,
character: 47,
},
},
severity: Some(
Error,
),
code: Some(
String(
"E0053",
),
),
source: Some(
"rustc",
),
message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&\'list ty::Ref<M>>`",
related_information: None,
tags: None,
},
fixes: [],
},
]

View file

@ -0,0 +1,48 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/runtime/compiler_support.rs",
range: Range {
start: Position {
line: 47,
character: 64,
},
end: Position {
line: 47,
character: 69,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 47,
character: 64,
},
end: Position {
line: 47,
character: 69,
},
},
severity: Some(
Error,
),
code: Some(
String(
"E0308",
),
),
source: Some(
"rustc",
),
message: "mismatched types\nexpected usize, found u32",
related_information: None,
tags: None,
},
fixes: [],
},
]

View file

@ -0,0 +1,86 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/driver/subcommand/repl.rs",
range: Range {
start: Position {
line: 290,
character: 8,
},
end: Position {
line: 290,
character: 11,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 290,
character: 8,
},
end: Position {
line: 290,
character: 11,
},
},
severity: Some(
Warning,
),
code: Some(
String(
"unused_variables",
),
),
source: Some(
"rustc",
),
message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
related_information: None,
tags: Some(
[
Unnecessary,
],
),
},
fixes: [
CodeAction {
title: "consider prefixing with an underscore",
kind: Some(
"quickfix",
),
diagnostics: None,
edit: Some(
WorkspaceEdit {
changes: Some(
{
"file:///test/driver/subcommand/repl.rs": [
TextEdit {
range: Range {
start: Position {
line: 290,
character: 8,
},
end: Position {
line: 290,
character: 11,
},
},
new_text: "_foo",
},
],
},
),
document_changes: None,
},
),
command: None,
is_preferred: None,
},
],
},
]

View file

@ -0,0 +1,67 @@
---
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/ty/select.rs",
range: Range {
start: Position {
line: 103,
character: 17,
},
end: Position {
line: 103,
character: 29,
},
},
},
diagnostic: Diagnostic {
range: Range {
start: Position {
line: 103,
character: 17,
},
end: Position {
line: 103,
character: 29,
},
},
severity: Some(
Error,
),
code: Some(
String(
"E0061",
),
),
source: Some(
"rustc",
),
message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters",
related_information: Some(
[
DiagnosticRelatedInformation {
location: Location {
uri: "file:///test/compiler/ty/select.rs",
range: Range {
start: Position {
line: 218,
character: 4,
},
end: Position {
line: 230,
character: 5,
},
},
},
message: "defined here",
},
],
),
tags: None,
},
fixes: [],
},
]

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ use lsp_types::{
WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd,
WorkDoneProgressReport,
};
use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask};
use ra_flycheck::{CheckTask, Status};
use ra_ide::{Canceled, FileId, LibraryData, LineIndex, SourceRootId};
use ra_prof::profile;
use ra_project_model::{PackageRoot, ProjectWorkspace};
@ -37,7 +37,7 @@ use threadpool::ThreadPool;
use crate::{
config::{Config, FilesWatcher},
diagnostics::DiagnosticTask,
diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask},
from_proto, lsp_ext,
main_loop::{
pending_requests::{PendingRequest, PendingRequests},
@ -736,22 +736,61 @@ fn on_check_task(
task_sender.send(Task::Diagnostic(DiagnosticTask::ClearCheck))?;
}
CheckTask::AddDiagnostic { url, diagnostic, fixes } => {
let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?;
let file_id = match world_state.vfs.read().path2file(&path) {
Some(file) => FileId(file.0),
None => {
log::error!("File with cargo diagnostic not found in VFS: {}", path.display());
return Ok(());
}
};
CheckTask::AddDiagnostic { workspace_root, diagnostic } => {
let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
&diagnostic,
&workspace_root,
);
for diag in diagnostics {
let path = diag
.location
.uri
.to_file_path()
.map_err(|()| format!("invalid uri: {}", diag.location.uri))?;
let file_id = match world_state.vfs.read().path2file(&path) {
Some(file) => FileId(file.0),
None => {
log::error!(
"File with cargo diagnostic not found in VFS: {}",
path.display()
);
return Ok(());
}
};
task_sender
.send(Task::Diagnostic(DiagnosticTask::AddCheck(file_id, diagnostic, fixes)))?;
task_sender.send(Task::Diagnostic(DiagnosticTask::AddCheck(
file_id,
diag.diagnostic,
diag.fixes.into_iter().map(|it| it.into()).collect(),
)))?;
}
}
CheckTask::Status(progress) => {
CheckTask::Status(status) => {
if world_state.config.client_caps.work_done_progress {
let progress = match status {
Status::Being => {
lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
title: "Running `cargo check`".to_string(),
cancellable: Some(false),
message: None,
percentage: None,
})
}
Status::Progress(target) => {
lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport {
cancellable: Some(false),
message: Some(target),
percentage: None,
})
}
Status::End => {
lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd {
message: None,
})
}
};
let params = lsp_types::ProgressParams {
token: lsp_types::ProgressToken::String(
"rustAnalyzer/cargoWatcher".to_string(),

View file

@ -11,7 +11,7 @@ use std::{
use crossbeam_channel::{unbounded, Receiver};
use lsp_types::Url;
use parking_lot::RwLock;
use ra_flycheck::{url_from_path_with_drive_lowercasing, Flycheck, FlycheckConfig};
use ra_flycheck::{Flycheck, FlycheckConfig};
use ra_ide::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
};
@ -22,7 +22,9 @@ use stdx::format_to;
use crate::{
config::Config,
diagnostics::{CheckFixes, DiagnosticCollection},
diagnostics::{
to_proto::url_from_path_with_drive_lowercasing, CheckFixes, DiagnosticCollection,
},
main_loop::pending_requests::{CompletedRequest, LatestRequests},
vfs_glob::{Glob, RustPackageFilterBuilder},
LspError, Result,