From 259c16314330821a71a3fc6719b8dfa5d4e18101 Mon Sep 17 00:00:00 2001 From: BenjaminBrienen Date: Wed, 22 Apr 2026 01:25:12 +0200 Subject: [PATCH 1/4] switch out lsp-types for gen-lsp-types --- Cargo.lock | 128 ++-- crates/rust-analyzer/Cargo.toml | 4 +- crates/rust-analyzer/src/bin/main.rs | 52 +- crates/rust-analyzer/src/cli/lsif.rs | 19 +- crates/rust-analyzer/src/cli/lsif/vendored.rs | 338 +++++++++++ crates/rust-analyzer/src/config.rs | 4 +- crates/rust-analyzer/src/diagnostics.rs | 8 +- .../src/diagnostics/flycheck_to_proto.rs | 53 +- .../test_data/clippy_pass_by_ref.txt | 257 ++++---- .../test_data/handles_macro_location.txt | 59 +- .../test_data/macro_compiler_error.txt | 140 ++--- ...easonable_line_numbers_from_empty_file.txt | 59 +- .../rustc_incompatible_type_for_trait.txt | 59 +- .../test_data/rustc_mismatched_type.txt | 59 +- .../rustc_range_map_lsp_position.txt | 158 ++--- .../test_data/rustc_unused_variable.txt | 92 ++- .../rustc_unused_variable_as_hint.txt | 92 ++- .../rustc_unused_variable_as_info.txt | 92 ++- .../rustc_wrong_number_of_parameters.txt | 158 ++--- .../test_data/snap_multi_line_fix.txt | 269 ++++----- crates/rust-analyzer/src/global_state.rs | 33 +- crates/rust-analyzer/src/handlers/dispatch.rs | 36 +- .../src/handlers/notification.rs | 21 +- crates/rust-analyzer/src/handlers/request.rs | 453 +++++++------- crates/rust-analyzer/src/lib.rs | 4 +- crates/rust-analyzer/src/lsp/capabilities.rs | 153 ++--- crates/rust-analyzer/src/lsp/ext.rs | 363 ++++++----- crates/rust-analyzer/src/lsp/from_proto.rs | 40 +- .../rust-analyzer/src/lsp/semantic_tokens.rs | 396 +++++++----- crates/rust-analyzer/src/lsp/to_proto.rs | 566 ++++++++++-------- crates/rust-analyzer/src/lsp/utils.rs | 169 +++--- crates/rust-analyzer/src/main_loop.rs | 250 ++++---- crates/rust-analyzer/src/reload.rs | 96 +-- crates/rust-analyzer/tests/slow-tests/main.rs | 92 ++- .../rust-analyzer/tests/slow-tests/ratoml.rs | 87 +-- .../rust-analyzer/tests/slow-tests/support.rs | 26 +- docs/book/src/contributing/lsp-extensions.md | 26 +- lib/lsp-server/Cargo.toml | 2 +- lib/lsp-server/examples/minimal_lsp.rs | 107 ++-- lib/lsp-server/src/lib.rs | 17 +- 40 files changed, 2841 insertions(+), 2196 deletions(-) create mode 100644 crates/rust-analyzer/src/cli/lsif/vendored.rs diff --git a/Cargo.lock b/Cargo.lock index 768c3a9aa616..76a23d45732e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -456,6 +456,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive-where" version = "1.6.1" @@ -478,6 +489,27 @@ dependencies = [ "syn", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + [[package]] name = "dhat" version = "0.3.3" @@ -671,6 +703,18 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" +[[package]] +name = "gen-lsp-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4998232b36d5aca53d27b42c7a6c9b65e8a5166ce3c7c24a510c0eece5b5d6ac" +dependencies = [ + "derive-new", + "derive_more", + "serde", + "serde_json", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -766,6 +810,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1423,8 +1473,8 @@ dependencies = [ "anyhow", "crossbeam-channel", "ctrlc", + "gen-lsp-types", "log", - "lsp-types", "rustc-hash 2.1.1", "serde", "serde_derive", @@ -1445,19 +1495,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "lsp-types" -version = "0.95.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984" -dependencies = [ - "bitflags 1.3.2", - "serde", - "serde_json", - "serde_repr", - "url", -] - [[package]] name = "macros" version = "0.0.0" @@ -2306,6 +2343,7 @@ dependencies = [ "dirs", "dissimilar", "expect-test", + "gen-lsp-types", "hir", "hir-def", "hir-ty", @@ -2318,7 +2356,6 @@ dependencies = [ "itertools 0.14.0", "load-cargo", "lsp-server 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types", "memchr", "mimalloc", "num_cpus", @@ -2340,6 +2377,8 @@ dependencies = [ "serde_json", "smallvec", "stdx", + "strum", + "strum_macros", "syntax", "syntax-bridge", "tenthash", @@ -2446,12 +2485,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "salsa" version = "0.26.0" @@ -2531,9 +2564,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -2541,18 +2574,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -2561,27 +2594,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "indexmap", "itoa", "memchr", - "ryu", "serde", "serde_core", -] - -[[package]] -name = "serde_repr" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "zmij", ] [[package]] @@ -2697,6 +2719,24 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syn" version = "2.0.106" @@ -3750,3 +3790,9 @@ dependencies = [ "memchr", "time", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 27d9576e29d0..c3795a555e2c 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -29,7 +29,7 @@ ide-completion.workspace = true indexmap.workspace = true itertools.workspace = true scip = "0.7.1" -lsp-types = { version = "=0.95.0", features = ["proposed"] } +lsp-types = { version = "0.3.0", package = "gen-lsp-types" } parking_lot = "0.12.4" xflags = "0.3.2" oorandom = "11.1.5" @@ -53,6 +53,8 @@ semver.workspace = true memchr = "2.7.5" cargo_metadata.workspace = true process-wrap.workspace = true +strum = "0.28.0" +strum_macros = "0.28.0" dhat = { version = "0.3.3", optional = true } cfg.workspace = true diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 44c442ffd81d..bb40b7d477f9 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -14,7 +14,7 @@ use std::{env, fs, path::PathBuf, process::ExitCode, sync::Arc}; use anyhow::Context; use lsp_server::Connection; -use paths::Utf8PathBuf; +use paths::{Utf8Component, Utf8PathBuf, Utf8Prefix}; use rust_analyzer::{ cli::flags, config::{Config, ConfigChange, ConfigErrors}, @@ -207,29 +207,18 @@ fn run_server() -> anyhow::Result<()> { tracing::info!("InitializeParams: {}", initialize_params); let lsp_types::InitializeParams { + #[expect(deprecated, reason = "migration TODO")] root_uri, - mut capabilities, - workspace_folders, + capabilities, + workspace_folders_initialize_params, initialization_options, client_info, .. } = from_json::("InitializeParams", &initialize_params)?; - // lsp-types has a typo in the `/capabilities/workspace/diagnostics` field, its typoed as `diagnostic` - if let Some(val) = initialize_params.pointer("/capabilities/workspace/diagnostics") - && let Ok(diag_caps) = from_json::( - "DiagnosticWorkspaceClientCapabilities", - val, - ) - { - tracing::info!("Patching lsp-types workspace diagnostics capabilities: {diag_caps:#?}"); - capabilities.workspace.get_or_insert_default().diagnostic.get_or_insert(diag_caps); - } - let root_path = match root_uri - .and_then(|it| it.to_file_path().ok()) + .map(|it| Utf8PathBuf::from(it.to_string().to_owned())) .map(patch_path_prefix) - .and_then(|it| Utf8PathBuf::from_path_buf(it).ok()) .and_then(|it| AbsPathBuf::try_from(it).ok()) { Some(it) => it, @@ -247,13 +236,19 @@ fn run_server() -> anyhow::Result<()> { ); } - let workspace_roots = workspace_folders + let workspace_roots = workspace_folders_initialize_params + .workspace_folders + .and_then(|workspaces| match workspaces { + lsp_types::WorkspaceFolders::WorkspaceFolderList(workspace_folders) => { + Some(workspace_folders) + } + lsp_types::WorkspaceFolders::Null => None, + }) .map(|workspaces| { workspaces .into_iter() - .filter_map(|it| it.uri.to_file_path().ok()) + .map(|it| Utf8PathBuf::from(it.uri.to_string())) .map(patch_path_prefix) - .filter_map(|it| Utf8PathBuf::from_path_buf(it).ok()) .filter_map(|it| AbsPathBuf::try_from(it).ok()) .collect::>() }) @@ -269,12 +264,11 @@ fn run_server() -> anyhow::Result<()> { if !error_sink.is_empty() { use lsp_types::{ - MessageType, ShowMessageParams, - notification::{Notification, ShowMessage}, + MessageType, Notification as _, ShowMessageNotification, ShowMessageParams, }; let not = lsp_server::Notification::new( - ShowMessage::METHOD.to_owned(), - ShowMessageParams { typ: MessageType::WARNING, message: error_sink.to_string() }, + ShowMessageNotification::METHOD.to_string(), + ShowMessageParams { kind: MessageType::Warning, message: error_sink.to_string() }, ); connection.sender.send(lsp_server::Message::Notification(not)).unwrap(); } @@ -288,7 +282,6 @@ fn run_server() -> anyhow::Result<()> { name: String::from("rust-analyzer"), version: Some(rust_analyzer::version().to_string()), }), - offset_encoding: None, }; let initialize_result = serde_json::to_value(initialize_result).unwrap(); @@ -325,8 +318,7 @@ fn run_server() -> anyhow::Result<()> { Ok(()) } -fn patch_path_prefix(path: PathBuf) -> PathBuf { - use std::path::{Component, Prefix}; +fn patch_path_prefix(path: Utf8PathBuf) -> Utf8PathBuf { if cfg!(windows) { // VSCode might report paths with the file drive in lowercase, but this can mess // with env vars set by tools and build scripts executed by r-a such that it invalidates @@ -335,17 +327,17 @@ fn patch_path_prefix(path: PathBuf) -> PathBuf { // (doing it conditionally is a pain because std::path::Prefix always reports uppercase letters on windows) let mut comps = path.components(); match comps.next() { - Some(Component::Prefix(prefix)) => { + Some(Utf8Component::Prefix(prefix)) => { let prefix = match prefix.kind() { - Prefix::Disk(d) => { + Utf8Prefix::Disk(d) => { format!("{}:", d.to_ascii_uppercase() as char) } - Prefix::VerbatimDisk(d) => { + Utf8Prefix::VerbatimDisk(d) => { format!(r"\\?\{}:", d.to_ascii_uppercase() as char) } _ => return path, }; - let mut path = PathBuf::new(); + let mut path = Utf8PathBuf::new(); path.push(prefix); path.extend(comps); path diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs index 4f6de6850abb..8cfad1f3eaa4 100644 --- a/crates/rust-analyzer/src/cli/lsif.rs +++ b/crates/rust-analyzer/src/cli/lsif.rs @@ -1,5 +1,4 @@ //! LSIF (language server index format) generator - use std::env; use std::time::Instant; @@ -10,12 +9,14 @@ use ide::{ }; use ide_db::{line_index, line_index::WideEncoding}; use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace}; -use lsp_types::lsif; use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; use rustc_hash::FxHashMap; use stdx::format_to; +use vendored as lsif; use vfs::{AbsPathBuf, Vfs}; +mod vendored; + use crate::{ cli::flags, line_index::{LineEndings, LineIndex, PositionEncoding}, @@ -38,9 +39,9 @@ struct LsifManager<'a, 'w> { #[derive(Clone, Copy)] struct Id(i32); -impl From for lsp_types::NumberOrString { +impl From for lsp_types::Code { fn from(Id(it): Id) -> Self { - lsp_types::NumberOrString::Number(it) + lsp_types::Code::Int(it) } } @@ -145,7 +146,7 @@ impl LsifManager<'_, '_> { let path = path.as_path().unwrap(); let doc_id = self.add_vertex(lsif::Vertex::Document(lsif::Document { language_id: "rust".to_owned(), - uri: lsp_types::Url::from_file_path(path).unwrap(), + uri: lsp_types::Uri(path.to_string()), })); self.file_map.insert(id, doc_id); doc_id @@ -156,7 +157,7 @@ impl LsifManager<'_, '_> { if let Some(hover) = token.hover { let hover_id = self.add_vertex(lsif::Vertex::HoverResult { result: lsp_types::Hover { - contents: lsp_types::HoverContents::Markup(to_proto::markup_content( + contents: lsp_types::Contents::MarkupContent(to_proto::markup_content( hover.markup, ide::HoverDocFormat::Markdown, )), @@ -211,7 +212,7 @@ impl LsifManager<'_, '_> { out_v: result_set_id.into(), })); let mut edges = token.references.iter().fold( - FxHashMap::<_, Vec>::default(), + FxHashMap::<_, Vec>::default(), |mut edges, it| { let entry = edges.entry((it.range.file_id, it.is_definition)).or_default(); entry.push((*self.range_map.get(&it.range).unwrap()).into()); @@ -321,9 +322,9 @@ impl flags::Lsif { let mut lsif = LsifManager::new(&analysis, db, &vfs, out); lsif.add_vertex(lsif::Vertex::MetaData(lsif::MetaData { version: String::from("0.5.0"), - project_root: lsp_types::Url::from_file_path(path).unwrap(), + project_root: lsp_types::Uri(path.to_string()), position_encoding: lsif::Encoding::Utf16, - tool_info: Some(lsp_types::lsif::ToolInfo { + tool_info: Some(lsif::ToolInfo { name: "rust-analyzer".to_owned(), args: vec![], version: Some(version().to_string()), diff --git a/crates/rust-analyzer/src/cli/lsif/vendored.rs b/crates/rust-analyzer/src/cli/lsif/vendored.rs new file mode 100644 index 000000000000..cad2514bec5a --- /dev/null +++ b/crates/rust-analyzer/src/cli/lsif/vendored.rs @@ -0,0 +1,338 @@ +//! Types of Language Server Index Format (LSIF). LSIF is a standard format +//! for language servers or other programming tools to dump their knowledge +//! about a workspace. +//! +//! Based on + +#![allow(unused, unreachable_pub, reason = "implementing the full spec is fine")] + +use lsp_types::{Range, Uri}; +use serde::{Deserialize, Serialize}; + +pub type Id = lsp_types::Code; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum LocationOrRangeId { + Location(lsp_types::Location), + RangeId(Id), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Entry { + pub id: Id, + #[serde(flatten)] + pub data: Element, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "type")] +pub enum Element { + Vertex(Vertex), + Edge(Edge), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct ToolInfo { + pub name: String, + #[serde(default = "Default::default")] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub args: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)] +pub enum Encoding { + /// Currently only 'utf-16' is supported due to the limitations in LSP. + #[serde(rename = "utf-16")] + Utf16, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct RangeBasedDocumentSymbol { + pub id: Id, + #[serde(default = "Default::default")] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub children: Vec, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(untagged)] +pub enum DocumentSymbolOrRangeBasedVec { + DocumentSymbol(Vec), + RangeBased(Vec), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DefinitionTag { + /// The text covered by the range + text: String, + /// The symbol kind. + kind: lsp_types::SymbolKind, + /// Indicates if this symbol is deprecated. + #[serde(default)] + #[serde(skip_serializing_if = "std::ops::Not::not")] + deprecated: bool, + /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code. + /// The range must be included in fullRange. + full_range: Range, + /// Optional detail information for the definition. + #[serde(skip_serializing_if = "Option::is_none")] + detail: Option, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DeclarationTag { + /// The text covered by the range + text: String, + /// The symbol kind. + kind: lsp_types::SymbolKind, + /// Indicates if this symbol is deprecated. + #[serde(default)] + deprecated: bool, + /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code. + /// The range must be included in fullRange. + full_range: Range, + /// Optional detail information for the definition. + #[serde(skip_serializing_if = "Option::is_none")] + detail: Option, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReferenceTag { + text: String, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UnknownTag { + text: String, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "type")] +pub enum RangeTag { + Definition(DefinitionTag), + Declaration(DeclarationTag), + Reference(ReferenceTag), + Unknown(UnknownTag), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "label")] +pub enum Vertex { + MetaData(MetaData), + /// + Project(Project), + Document(Document), + /// + Range { + #[serde(flatten)] + range: Range, + #[serde(skip_serializing_if = "Option::is_none")] + tag: Option, + }, + /// + ResultSet(ResultSet), + Moniker(lsp_types::Moniker), + PackageInformation(PackageInformation), + + #[serde(rename = "$event")] + Event(Event), + + DefinitionResult, + DeclarationResult, + TypeDefinitionResult, + ReferenceResult, + ImplementationResult, + FoldingRangeResult { + result: Vec, + }, + HoverResult { + result: lsp_types::Hover, + }, + DocumentSymbolResult { + result: DocumentSymbolOrRangeBasedVec, + }, + DocumentLinkResult { + result: Vec, + }, + DiagnosticResult { + result: Vec, + }, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum EventKind { + Begin, + End, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum EventScope { + Document, + Project, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Event { + pub kind: EventKind, + pub scope: EventScope, + pub data: Id, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "label")] +pub enum Edge { + Contains(EdgeDataMultiIn), + Moniker(EdgeData), + NextMoniker(EdgeData), + Next(EdgeData), + PackageInformation(EdgeData), + Item(Item), + + // Methods + #[serde(rename = "textDocument/definition")] + Definition(EdgeData), + #[serde(rename = "textDocument/declaration")] + Declaration(EdgeData), + #[serde(rename = "textDocument/hover")] + Hover(EdgeData), + #[serde(rename = "textDocument/references")] + References(EdgeData), + #[serde(rename = "textDocument/implementation")] + Implementation(EdgeData), + #[serde(rename = "textDocument/typeDefinition")] + TypeDefinition(EdgeData), + #[serde(rename = "textDocument/foldingRange")] + FoldingRange(EdgeData), + #[serde(rename = "textDocument/documentLink")] + DocumentLink(EdgeData), + #[serde(rename = "textDocument/documentSymbol")] + DocumentSymbol(EdgeData), + #[serde(rename = "textDocument/diagnostic")] + Diagnostic(EdgeData), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EdgeData { + pub in_v: Id, + pub out_v: Id, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EdgeDataMultiIn { + pub in_vs: Vec, + pub out_v: Id, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DefinitionResultType { + Scalar(LocationOrRangeId), + Array(LocationOrRangeId), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum ItemKind { + Declarations, + Definitions, + References, + ReferenceResults, + ImplementationResults, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Item { + pub document: Id, + #[serde(skip_serializing_if = "Option::is_none")] + pub property: Option, + #[serde(flatten)] + pub edge_data: EdgeDataMultiIn, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Document { + pub uri: Uri, + pub language_id: String, +} + +/// +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ResultSet { + #[serde(skip_serializing_if = "Option::is_none")] + pub key: Option, +} + +/// +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Project { + #[serde(skip_serializing_if = "Option::is_none")] + pub resource: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub content: Option, + pub kind: String, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetaData { + /// The version of the LSIF format using semver notation. See . Please note + /// the version numbers starting with 0 don't adhere to semver and adopters have to assume + /// that each new version is breaking. + pub version: String, + + /// The project root (in form of an URI) used to compute this dump. + pub project_root: Uri, + + /// The string encoding used to compute line and character values in + /// positions and ranges. + pub position_encoding: Encoding, + + /// Information about the tool that created the dump + #[serde(skip_serializing_if = "Option::is_none")] + pub tool_info: Option, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Repository { + pub r#type: String, + pub url: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub commit_id: Option, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PackageInformation { + pub name: String, + pub manager: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub uri: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub content: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3a88a8fe8480..022ea2247578 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1116,7 +1116,7 @@ pub struct Config { default_config: &'static DefaultConfigData, /// Config node that obtains its initial value during the server initialization and - /// by receiving a `lsp_types::notification::DidChangeConfiguration`. + /// by receiving a [`lsp_types::DidChangeConfigurationNotification`]. client_config: (FullConfigInput, ConfigErrors), /// Config node whose values apply to **every** Rust project. @@ -2657,8 +2657,6 @@ impl Config { } pub fn snippet_cap(&self) -> Option { - // FIXME: Also detect the proposed lsp version at caps.workspace.workspaceEdit.snippetEditSupport - // once lsp-types has it. SnippetCap::new(self.snippet_text_edit()) } diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 8d0f52433e02..03971f825b4e 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -357,14 +357,12 @@ pub(crate) fn convert_diagnostic( lsp_types::Diagnostic { range: lsp::to_proto::range(line_index, d.range.range), severity: Some(lsp::to_proto::diagnostic_severity(d.severity)), - code: Some(lsp_types::NumberOrString::String(d.code.as_str().to_owned())), - code_description: Some(lsp_types::CodeDescription { - href: lsp_types::Url::parse(&d.code.url()).unwrap(), - }), + code: Some(lsp_types::Code::String(d.code.as_str().to_owned())), + code_description: Some(lsp_types::CodeDescription { href: lsp_types::Uri(d.code.url()) }), source: Some("rust-analyzer".to_owned()), message: d.message, related_information: None, - tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::UNNECESSARY]), + tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::Unnecessary]), data: None, } } diff --git a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs index a6d7bcb9c70e..d786613871d4 100644 --- a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs @@ -3,6 +3,7 @@ use crate::flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan}; use itertools::Itertools; +use lsp_types::Uri; use rustc_hash::FxHashMap; use smallvec::SmallVec; use stdx::format_to; @@ -22,8 +23,8 @@ fn diagnostic_severity( code: Option<&crate::flycheck::DiagnosticCode>, ) -> Option { let res = match level { - DiagnosticLevel::Ice => lsp_types::DiagnosticSeverity::ERROR, - DiagnosticLevel::Error => lsp_types::DiagnosticSeverity::ERROR, + DiagnosticLevel::Ice => lsp_types::DiagnosticSeverity::Error, + DiagnosticLevel::Error => lsp_types::DiagnosticSeverity::Error, DiagnosticLevel::Warning => match code { // HACK: special case for `warnings` rustc lint. Some(code) @@ -31,7 +32,7 @@ fn diagnostic_severity( lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint) }) => { - lsp_types::DiagnosticSeverity::HINT + lsp_types::DiagnosticSeverity::Hint } // HACK: special case for `warnings` rustc lint. Some(code) @@ -39,12 +40,12 @@ fn diagnostic_severity( lint == "warnings" || ide_db::helpers::lint_eq_or_in_group(&code.code, lint) }) => { - lsp_types::DiagnosticSeverity::INFORMATION + lsp_types::DiagnosticSeverity::Information } - _ => lsp_types::DiagnosticSeverity::WARNING, + _ => lsp_types::DiagnosticSeverity::Warning, }, - DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::INFORMATION, - DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::HINT, + DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::Information, + DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::Hint, _ => return None, }; Some(res) @@ -192,7 +193,7 @@ fn map_rust_child_diagnostic( return MappedRustChildDiagnostic::MessageLine(rd.message.clone()); } - let mut edit_map: FxHashMap> = FxHashMap::default(); + let mut edit_map: FxHashMap> = FxHashMap::default(); let mut suggested_replacements = Vec::new(); let mut is_preferred = true; for &span in &spans { @@ -239,7 +240,7 @@ fn map_rust_child_diagnostic( action: lsp_ext::CodeAction { title: message.clone(), group: None, - kind: Some(lsp_types::CodeActionKind::QUICKFIX), + kind: Some(lsp_types::CodeActionKind::QuickFix), edit: Some(lsp_ext::SnippetWorkspaceEdit { // FIXME: there's no good reason to use edit_map here.... changes: Some(edit_map), @@ -263,7 +264,7 @@ fn map_rust_child_diagnostic( #[derive(Debug)] pub(crate) struct MappedRustDiagnostic { - pub(crate) url: lsp_types::Url, + pub(crate) url: lsp_types::Uri, pub(crate) diagnostic: lsp_types::Diagnostic, pub(crate) fix: Option>, } @@ -351,10 +352,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp( match &*code.code { "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes" | "unused_imports" | "unused_macros" | "unused_variables" => { - tag = Some(lsp_types::DiagnosticTag::UNNECESSARY); + tag = Some(lsp_types::DiagnosticTag::Unnecessary); } "deprecated" => { - tag = Some(lsp_types::DiagnosticTag::DEPRECATED); + tag = Some(lsp_types::DiagnosticTag::Deprecated); } _ => {} } @@ -418,13 +419,13 @@ pub(crate) fn map_rust_diagnostic_to_lsp( let diagnostic = lsp_types::Diagnostic { range: secondary_location.range, // downgrade to hint if we're pointing at the macro - severity: Some(lsp_types::DiagnosticSeverity::HINT), - code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), + severity: Some(lsp_types::DiagnosticSeverity::Hint), + code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), code_description: code_description.clone(), source: Some(source.to_owned()), message: message.clone(), related_information: Some(information_for_additional_diagnostic), - tags: tag.clone().map(|tag| vec![tag]), + tags: tag.map(|tag| vec![tag]), data: Some(serde_json::json!({ "rendered": rendered })), }; diagnostics.push(MappedRustDiagnostic { @@ -440,7 +441,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( diagnostic: lsp_types::Diagnostic { range: primary_location.range, severity, - code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), + code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), code_description: code_description.clone(), source: Some(source.to_owned()), message, @@ -452,7 +453,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( .collect::>(); if info.is_empty() { None } else { Some(info) } }, - tags: tag.clone().map(|tag| vec![tag]), + tags: tag.map(|tag| vec![tag]), data: Some(serde_json::json!({ "rendered": rendered })), }, fix: None, @@ -471,8 +472,8 @@ pub(crate) fn map_rust_diagnostic_to_lsp( fix: sub.suggested_fix.clone(), diagnostic: lsp_types::Diagnostic { range: sub.related.location.range, - severity: Some(lsp_types::DiagnosticSeverity::HINT), - code: code.map(ToOwned::to_owned).map(lsp_types::NumberOrString::String), + severity: Some(lsp_types::DiagnosticSeverity::Hint), + code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), code_description: code_description.clone(), source: Some(source.to_owned()), message: sub.related.message.clone(), @@ -493,20 +494,16 @@ fn rustc_code_description(code: Option<&str>) -> Option) -> Option { - code.and_then(|code| { - lsp_types::Url::parse(&format!( + code.map(|code| lsp_types::CodeDescription { + href: lsp_types::Uri(format!( "https://rust-lang.github.io/rust-clippy/master/index.html#{code}" - )) - .ok() - .map(|href| lsp_types::CodeDescription { href }) + )), }) } diff --git a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt index c3b540e31f77..319b2cefaf15 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "trivially_copy_pass_by_ref", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "trivially_copy_pass_by_ref", + ), + }, + ), }, ), source: Some( @@ -59,17 +64,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/lib.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/lib.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 0, @@ -85,17 +88,15 @@ }, DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 41, @@ -117,17 +118,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/lib.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/lib.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -149,23 +148,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "trivially_copy_pass_by_ref", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "trivially_copy_pass_by_ref", + ), + }, + ), }, ), source: Some( @@ -176,17 +182,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 41, @@ -208,17 +212,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -240,23 +242,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "trivially_copy_pass_by_ref", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "trivially_copy_pass_by_ref", + ), + }, + ), }, ), source: Some( @@ -267,17 +276,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 41, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt index 989e5cf66d86..49c5e4b1a4e4 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", + ), + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0277", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0277", - ), - }, + }, + ), }, ), source: Some( diff --git a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt index b44569b4931d..9c7c83423fa9 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/path.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/path.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -35,17 +33,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/path.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/path.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 264, @@ -67,17 +63,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/data.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/data.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -102,17 +96,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/path.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/path.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 264, @@ -134,17 +126,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/path.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/path.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -169,17 +159,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/path.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/path.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 271, @@ -195,17 +183,15 @@ }, DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/hir_def/src/data.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/hir_def/src/data.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 79, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt index df00b330b6e9..ab0a52757bae 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/bin/current.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/bin/current.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", + ), + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0601", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0601", - ), - }, + }, + ), }, ), source: Some( diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt index dc36aa761c06..482a193fd8b3 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/ty/list_iter.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/ty/list_iter.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", + ), + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0053", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0053", - ), - }, + }, + ), }, ), source: Some( diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt index d557196c2bd2..0ea8f1d345e0 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/runtime/compiler_support.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/runtime/compiler_support.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", + ), + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0308", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0308", - ), - }, + }, + ), }, ), source: Some( diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt index a100fa07ffdd..c174ad591296 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/test_diagnostics/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/test_diagnostics/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0308", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0308", + ), + }, + ), }, ), source: Some( @@ -59,17 +64,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/test_diagnostics/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/test_diagnostics/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 3, @@ -91,17 +94,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/test_diagnostics/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/test_diagnostics/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -123,23 +124,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0308", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0308", + ), + }, + ), }, ), source: Some( @@ -150,17 +158,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/crates/test_diagnostics/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/crates/test_diagnostics/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 3, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt index 1c5c33622349..d423d0fee74d 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -39,17 +37,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -75,17 +71,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -114,17 +108,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -170,17 +162,7 @@ SnippetWorkspaceEdit { changes: Some( { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ + "/test/driver/subcommand/repl.rs": [ TextEdit { range: Range { start: Position { diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt index 3ab3412d971b..cfe1eefafe8d 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -39,17 +37,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -75,17 +71,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -114,17 +108,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -170,17 +162,7 @@ SnippetWorkspaceEdit { changes: Some( { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ + "/test/driver/subcommand/repl.rs": [ TextEdit { range: Range { start: Position { diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt index 0702420aa5f9..6de7eb028dac 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -39,17 +37,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -75,17 +71,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -114,17 +108,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 290, @@ -170,17 +162,7 @@ SnippetWorkspaceEdit { changes: Some( { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ + "/test/driver/subcommand/repl.rs": [ TextEdit { range: Range { start: Position { diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt index 8ec92888ce11..316d335dbc08 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/ty/select.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/ty/select.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0061", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0061", + ), + }, + ), }, ), source: Some( @@ -59,17 +64,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/ty/select.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/ty/select.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 218, @@ -91,17 +94,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/ty/select.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/ty/select.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -123,23 +124,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "doc.rust-lang.org", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/error-index.html", - query: None, - fragment: Some( - "E0061", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "doc.rust-lang.org", + data: RegName( + "doc.rust-lang.org", + ), + }, + port: None, + }, + ), + path: "/error-index.html", + query: None, + fragment: Some( + "E0061", + ), + }, + ), }, ), source: Some( @@ -150,17 +158,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/ty/select.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/compiler/ty/select.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 103, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt index 4365e450df1f..3a3b6cc0e644 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt @@ -1,16 +1,14 @@ [ MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -32,23 +30,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "let_and_return", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "let_and_return", + ), + }, + ), }, ), source: Some( @@ -59,17 +64,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 2, @@ -85,17 +88,15 @@ }, DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 2, @@ -117,17 +118,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -149,23 +148,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "let_and_return", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "let_and_return", + ), + }, + ), }, ), source: Some( @@ -176,17 +182,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 3, @@ -208,17 +212,15 @@ fix: None, }, MappedRustDiagnostic { - url: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + url: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), diagnostic: Diagnostic { range: Range { start: Position { @@ -240,23 +242,30 @@ ), code_description: Some( CodeDescription { - href: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "rust-lang.github.io", + href: Uri( + Uri { + scheme: Some( + "https", ), - ), - port: None, - path: "/rust-clippy/master/index.html", - query: None, - fragment: Some( - "let_and_return", - ), - }, + authority: Some( + Authority { + userinfo: None, + host: Host { + text: "rust-lang.github.io", + data: RegName( + "rust-lang.github.io", + ), + }, + port: None, + }, + ), + path: "/rust-clippy/master/index.html", + query: None, + fragment: Some( + "let_and_return", + ), + }, + ), }, ), source: Some( @@ -267,17 +276,15 @@ [ DiagnosticRelatedInformation { location: Location { - uri: Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }, + uri: Uri( + Uri { + scheme: None, + authority: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }, + ), range: Range { start: Position { line: 3, @@ -333,17 +340,7 @@ SnippetWorkspaceEdit { changes: Some( { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }: [ + "/test/src/main.rs": [ TextEdit { range: Range { start: Position { diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index afd4162de622..86c0d653465f 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -18,7 +18,7 @@ use ide_db::{ }; use itertools::Itertools; use load_cargo::SourceRootConfig; -use lsp_types::{SemanticTokens, Url}; +use lsp_types::{Notification, SemanticTokens, Uri}; use parking_lot::{ MappedRwLockReadGuard, Mutex, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard, @@ -97,7 +97,7 @@ pub(crate) struct GlobalState { pub(crate) source_root_config: SourceRootConfig, /// A mapping that maps a local source root's `SourceRootId` to it parent's `SourceRootId`, if it has one. pub(crate) local_roots_parent_map: Arc>, - pub(crate) semantic_tokens_cache: Arc>>, + pub(crate) semantic_tokens_cache: Arc>>, // status pub(crate) shutdown_requested: bool, @@ -209,7 +209,7 @@ pub(crate) struct GlobalStateSnapshot { pub(crate) analysis: Analysis, pub(crate) check_fixes: CheckFixes, mem_docs: MemDocs, - pub(crate) semantic_tokens_cache: Arc>>, + pub(crate) semantic_tokens_cache: Arc>>, vfs: Arc)>>, pub(crate) workspaces: Arc>, // used to signal semantic highlighting to fall back to syntax based highlighting until @@ -580,12 +580,12 @@ impl GlobalState { } } - pub(crate) fn send_request( + pub(crate) fn send_request( &mut self, params: R::Params, handler: ReqHandler, ) { - let request = self.req_queue.outgoing.register(R::METHOD.to_owned(), params, handler); + let request = self.req_queue.outgoing.register(R::METHOD.to_string(), params, handler); self.send(request.into()); } @@ -598,11 +598,8 @@ impl GlobalState { handler(self, response) } - pub(crate) fn send_notification( - &self, - params: N::Params, - ) { - let not = lsp_server::Notification::new(N::METHOD.to_owned(), params); + pub(crate) fn send_notification(&self, params: N::Params) { + let not = lsp_server::Notification::new(N::METHOD.into(), params); self.send(not.into()); } @@ -647,7 +644,7 @@ impl GlobalState { pub(crate) fn publish_diagnostics( &mut self, - uri: Url, + uri: Uri, version: Option, mut diagnostics: Vec, ) { @@ -680,7 +677,7 @@ impl GlobalState { } let not = lsp_server::Notification::new( - ::METHOD.to_owned(), + lsp_types::PublishDiagnosticsNotification::METHOD.into(), lsp_types::PublishDiagnosticsParams { uri, diagnostics, version }, ); _ = sender.send(not.into()); @@ -744,11 +741,11 @@ impl GlobalStateSnapshot { } /// Returns `None` if the file was excluded. - pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result> { + pub(crate) fn url_to_file_id(&self, url: &Uri) -> anyhow::Result> { url_to_file_id(&self.vfs_read(), url) } - pub(crate) fn file_id_to_url(&self, id: FileId) -> Url { + pub(crate) fn file_id_to_url(&self, id: FileId) -> Uri { file_id_to_url(&self.vfs_read(), id) } @@ -768,12 +765,12 @@ impl GlobalStateSnapshot { Some(self.mem_docs.get(self.vfs_read().file_path(file_id))?.version) } - pub(crate) fn url_file_version(&self, url: &Url) -> Option { + pub(crate) fn url_file_version(&self, url: &Uri) -> Option { let path = from_proto::vfs_path(url).ok()?; Some(self.mem_docs.get(&path)?.version) } - pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url { + pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Uri { let mut base = self.vfs_read().file_path(path.anchor).clone(); base.pop(); let path = base.join(&path.path).unwrap(); @@ -898,14 +895,14 @@ impl GlobalStateSnapshot { } } -pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url { +pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Uri { let path = vfs.file_path(id); let path = path.as_path().unwrap(); url_from_abs_path(path) } /// Returns `None` if the file was excluded. -pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result> { +pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Uri) -> anyhow::Result> { let path = from_proto::vfs_path(url)?; vfs_path_to_file_id(vfs, &path) } diff --git a/crates/rust-analyzer/src/handlers/dispatch.rs b/crates/rust-analyzer/src/handlers/dispatch.rs index 67bd643fcef1..be816fe552bc 100644 --- a/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/crates/rust-analyzer/src/handlers/dispatch.rs @@ -47,7 +47,7 @@ impl RequestDispatcher<'_> { f: fn(&mut GlobalState, R::Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug, R::Result: Serialize, { @@ -75,7 +75,7 @@ impl RequestDispatcher<'_> { f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug, R::Result: Serialize, { @@ -107,14 +107,14 @@ impl RequestDispatcher<'_> { f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request< + R: lsp_types::Request< Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, Result: Serialize + Default, > + 'static, { if !self.global_state.vfs_done { if let Some(lsp_server::Request { id, .. }) = - self.req.take_if(|it| it.method == R::METHOD) + self.req.take_if(|it| it.method == R::METHOD.to_string()) { self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default())); } @@ -136,14 +136,14 @@ impl RequestDispatcher<'_> { on_cancelled: fn() -> ResponseError, ) -> &mut Self where - R: lsp_types::request::Request< + R: lsp_types::Request< Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, Result: Serialize, > + 'static, { if !self.global_state.vfs_done || self.global_state.incomplete_crate_graph { if let Some(lsp_server::Request { id, .. }) = - self.req.take_if(|it| it.method == R::METHOD) + self.req.take_if(|it| it.method == R::METHOD.to_string()) { self.global_state.respond(lsp_server::Response::new_ok(id, default())); } @@ -159,7 +159,7 @@ impl RequestDispatcher<'_> { f: fn(GlobalStateSnapshot, Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request + 'static, + R: lsp_types::Request + 'static, Params: Serialize + DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, { if !self.global_state.vfs_done { @@ -182,14 +182,14 @@ impl RequestDispatcher<'_> { f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request< + R: lsp_types::Request< Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, Result: Serialize + Default, > + 'static, { if !self.global_state.vfs_done { if let Some(lsp_server::Request { id, .. }) = - self.req.take_if(|it| it.method == R::METHOD) + self.req.take_if(|it| it.method == R::METHOD.to_string()) { self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default())); } @@ -210,7 +210,7 @@ impl RequestDispatcher<'_> { f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result, ) -> &mut Self where - R: lsp_types::request::Request + 'static, + R: lsp_types::Request + 'static, R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, R::Result: Serialize, { @@ -240,7 +240,7 @@ impl RequestDispatcher<'_> { on_cancelled: fn() -> ResponseError, ) -> &mut Self where - R: lsp_types::request::Request + 'static, + R: lsp_types::Request + 'static, R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug, R::Result: Serialize, { @@ -278,11 +278,11 @@ impl RequestDispatcher<'_> { fn parse(&mut self) -> Option<(lsp_server::Request, R::Params, String)> where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: DeserializeOwned + fmt::Debug, { - let req = self.req.take_if(|it| it.method == R::METHOD)?; - let res = crate::from_json(R::METHOD, &req.params); + let req = self.req.take_if(|it| it.method == R::METHOD.to_string())?; + let res = crate::from_json(R::METHOD.to_string(), &req.params); match res { Ok(params) => { let panic_context = @@ -334,7 +334,7 @@ fn thread_result_to_response( result: thread::Result>, ) -> Result where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: DeserializeOwned, R::Result: Serialize, { @@ -369,7 +369,7 @@ fn result_to_response( result: anyhow::Result, ) -> Result where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: DeserializeOwned, R::Result: Serialize, { @@ -401,7 +401,7 @@ impl NotificationDispatcher<'_> { f: fn(&mut GlobalState, N::Params) -> anyhow::Result<()>, ) -> &mut Self where - N: lsp_types::notification::Notification, + N: lsp_types::Notification, N::Params: DeserializeOwned + Send + Debug, { let not = match self.not.take() { @@ -411,7 +411,7 @@ impl NotificationDispatcher<'_> { let _guard = tracing::info_span!("notification", method = ?not.method).entered(); - let params = match not.extract::(N::METHOD) { + let params = match not.extract::(&N::METHOD.to_string()) { Ok(it) => it, Err(ExtractError::JsonError { method, error }) => { tracing::error!(method = %method, error = %error, "invalid notification"); diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index 09b6794e4f43..558fc2806f21 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -4,6 +4,7 @@ use std::{ ops::{Deref, Not as _}, panic::UnwindSafe, + str::FromStr, }; use itertools::Itertools; @@ -30,8 +31,8 @@ use crate::{ pub(crate) fn handle_cancel(state: &mut GlobalState, params: CancelParams) -> anyhow::Result<()> { let id: lsp_server::RequestId = match params.id { - lsp_types::NumberOrString::Number(id) => id.into(), - lsp_types::NumberOrString::String(id) => id.into(), + lsp_types::Id::Int(id) => id.into(), + lsp_types::Id::String(id) => id.into(), }; state.cancel(id); Ok(()) @@ -41,7 +42,7 @@ pub(crate) fn handle_work_done_progress_cancel( state: &mut GlobalState, params: WorkDoneProgressCancelParams, ) -> anyhow::Result<()> { - if let lsp_types::NumberOrString::String(s) = ¶ms.token + if let lsp_types::ProgressToken::String(s) = ¶ms.token && let Some(id) = s.strip_prefix("rust-analyzer/flycheck/") && let Ok(id) = id.parse::() && let Some(flycheck) = state.flycheck.get(id as usize) @@ -103,7 +104,7 @@ pub(crate) fn handle_did_change_text_document( ) -> anyhow::Result<()> { let _p = tracing::info_span!("handle_did_change_text_document").entered(); - if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { + if let Ok(path) = from_proto::vfs_path(¶ms.text_document.text_document_identifier.uri) { let Some(DocumentData { version, data }) = state.mem_docs.get_mut(&path) else { tracing::error!(?path, "unexpected DidChangeTextDocument"); return Ok(()); @@ -215,7 +216,7 @@ pub(crate) fn handle_did_change_configuration( ) -> anyhow::Result<()> { // As stated in https://github.com/microsoft/language-server-protocol/issues/676, // this notification's parameters should be ignored and the actual config queried separately. - state.send_request::( + state.send_request::( lsp_types::ConfigurationParams { items: vec![lsp_types::ConfigurationItem { scope_uri: None, @@ -260,8 +261,8 @@ pub(crate) fn handle_did_change_workspace_folders( let config = Arc::make_mut(&mut state.config); for workspace in params.event.removed { - let Ok(path) = workspace.uri.to_file_path() else { continue }; - let Ok(path) = Utf8PathBuf::from_path_buf(path) else { continue }; + let path = workspace.uri.to_string(); + let Ok(path) = Utf8PathBuf::from_str(&path); let Ok(path) = AbsPathBuf::try_from(path) else { continue }; config.remove_workspace(&path); } @@ -270,8 +271,8 @@ pub(crate) fn handle_did_change_workspace_folders( .event .added .into_iter() - .filter_map(|it| it.uri.to_file_path().ok()) - .filter_map(|it| Utf8PathBuf::from_path_buf(it).ok()) + .map(|it| it.uri.to_string()) + .filter_map(|it| Utf8PathBuf::from_str(&it).ok()) .filter_map(|it| AbsPathBuf::try_from(it).ok()); config.add_workspaces(added); @@ -553,7 +554,7 @@ pub(crate) fn handle_run_flycheck( pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { if state.test_run_session.take().is_some() { - state.send_notification::(()); + state.send_notification::(()); } Ok(()) } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 0c1c067ffa91..8c847d396c04 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1,7 +1,7 @@ //! This module is responsible for implementing handlers for Language Server //! Protocol. This module specifically handles requests. -use std::{fs, io::Write as _, ops::Not, process::Stdio}; +use std::{fs, io::Write as _, ops::Not, process::Stdio, str::FromStr}; use anyhow::Context; @@ -18,11 +18,11 @@ use lsp_server::ErrorCode; use lsp_types::{ CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, - CodeLens, CompletionItem, FoldingRange, FoldingRangeParams, HoverContents, InlayHint, - InlayHintParams, Location, LocationLink, Position, PrepareRenameResponse, Range, RenameParams, - ResourceOp, ResourceOperationKind, SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, - SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult, - SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit, + CodeLens, CompletionItem, Contents, DocumentChange, FoldingRange, FoldingRangeParams, + InlayHint, InlayHintParams, Location, LocationLink, Position, PrepareRenameResult, Range, + RenameParams, ResourceOperationKind, SemanticTokens, SemanticTokensDeltaParams, + SemanticTokensDeltaRequestResponse, SemanticTokensParams, SemanticTokensRangeParams, + SymbolInformation, SymbolTag, TextDocumentIdentifier, Uri, WorkspaceEdit, }; use paths::Utf8PathBuf; use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind}; @@ -87,7 +87,7 @@ pub(crate) fn handle_analyzer_status( match from_proto::file_id(&snap, &tdi.uri) { Ok(Some(it)) => file_id = Some(it), Ok(None) => {} - Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri), + Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri.to_string()), } } @@ -172,7 +172,7 @@ pub(crate) fn handle_view_hir( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_hir").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let res = snap.analysis.view_hir(position)?; Ok(res) } @@ -182,7 +182,7 @@ pub(crate) fn handle_view_mir( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_mir").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let res = snap.analysis.view_mir(position)?; Ok(res) } @@ -192,7 +192,7 @@ pub(crate) fn handle_interpret_function( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_interpret_function").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let res = snap.analysis.interpret_function(position)?; Ok(res) } @@ -252,7 +252,7 @@ pub(crate) fn handle_run_test( params: lsp_ext::RunTestParams, ) -> anyhow::Result<()> { if let Some(_session) = state.test_run_session.take() { - state.send_notification::(()); + state.send_notification::(()); } let mut handles = vec![]; @@ -343,7 +343,7 @@ pub(crate) fn handle_expand_macro( let _p = tracing::info_span!("handle_expand_macro").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; - let offset = from_proto::offset(&line_index, params.position)?; + let offset = from_proto::offset(&line_index, ¶ms.position)?; let res = snap.analysis.expand_macro(FilePosition { file_id, offset })?; Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion })) @@ -358,7 +358,7 @@ pub(crate) fn handle_selection_range( let line_index = snap.file_line_index(file_id)?; let res: anyhow::Result> = params .positions - .into_iter() + .iter() .map(|position| { let offset = from_proto::offset(&line_index, position)?; let mut ranges = Vec::new(); @@ -401,7 +401,7 @@ pub(crate) fn handle_matching_brace( let line_index = snap.file_line_index(file_id)?; params .positions - .into_iter() + .iter() .map(|position| { let offset = from_proto::offset(&line_index, position); offset.map(|offset| { @@ -445,7 +445,7 @@ pub(crate) fn handle_on_enter( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_on_enter").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let edit = match snap.analysis.on_enter(position)? { None => return Ok(None), Some(it) => it, @@ -469,9 +469,11 @@ pub(crate) fn handle_on_type_formatting( if !snap.config.typing_trigger_chars().contains(char_typed) { return Ok(None); } - - let mut position = - try_default!(from_proto::file_position(&snap, params.text_document_position)?); + let tdpp = lsp_types::TextDocumentPositionParams { + text_document: params.text_document, + position: params.position, + }; + let mut position = try_default!(from_proto::file_position(&snap, &tdpp)?); let line_index = snap.file_line_index(position.file_id)?; // in `ide`, the `on_type` invariant is that @@ -502,8 +504,8 @@ pub(crate) fn handle_on_type_formatting( Ok(Some(change)) } -pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportResult { - lsp_types::DocumentDiagnosticReportResult::Report(lsp_types::DocumentDiagnosticReport::Full( +pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReport { + lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport( lsp_types::RelatedFullDocumentDiagnosticReport { related_documents: None, full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { @@ -511,13 +513,13 @@ pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportRe items: vec![], }, }, - )) + ) } pub(crate) fn handle_document_diagnostics( snap: GlobalStateSnapshot, params: lsp_types::DocumentDiagnosticParams, -) -> anyhow::Result { +) -> anyhow::Result { let file_id = match from_proto::file_id(&snap, ¶ms.text_document.uri)? { Some(it) => it, None => return Ok(empty_diagnostic_report()), @@ -554,8 +556,8 @@ pub(crate) fn handle_document_diagnostics( } None }); - Ok(lsp_types::DocumentDiagnosticReportResult::Report( - lsp_types::DocumentDiagnosticReport::Full(lsp_types::RelatedFullDocumentDiagnosticReport { + Ok(lsp_types::DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport( + lsp_types::RelatedFullDocumentDiagnosticReport { full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { result_id: Some("rust-analyzer".to_owned()), items: diagnostics.collect(), @@ -564,26 +566,24 @@ pub(crate) fn handle_document_diagnostics( related_documents .into_iter() .map(|(id, (items, _))| { - ( - to_proto::url(&snap, id), - lsp_types::DocumentDiagnosticReportKind::Full( - lsp_types::FullDocumentDiagnosticReport { - result_id: Some("rust-analyzer".to_owned()), - items, - }, - ), - ) + let full = lsp_types::RelatedDocument::FullDocumentDiagnosticReport( + lsp_types::FullDocumentDiagnosticReport { + result_id: Some("rust-analyzer".to_owned()), + items, + }, + ); + (to_proto::url(&snap, id), full) }) .collect() }), - }), + }, )) } pub(crate) fn handle_document_symbol( snap: GlobalStateSnapshot, params: lsp_types::DocumentSymbolParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_document_symbol").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; @@ -600,7 +600,7 @@ pub(crate) fn handle_document_symbol( for node in structure_nodes { let mut tags = Vec::new(); if node.deprecated { - tags.push(SymbolTag::DEPRECATED) + tags.push(SymbolTag::Deprecated) }; #[allow(deprecated)] @@ -649,17 +649,19 @@ pub(crate) fn handle_document_symbol( fn flatten_document_symbol( symbol: &lsp_types::DocumentSymbol, container_name: Option, - url: &Url, + url: &Uri, res: &mut Vec, ) { #[allow(deprecated)] res.push(SymbolInformation { - name: symbol.name.clone(), - kind: symbol.kind, - tags: symbol.tags.clone(), deprecated: symbol.deprecated, location: Location::new(url.clone(), symbol.range), - container_name, + base_symbol_information: lsp_types::BaseSymbolInformation { + name: symbol.name.clone(), + kind: symbol.kind, + tags: symbol.tags.clone(), + container_name, + }, }); for child in symbol.children.iter().flatten() { @@ -671,7 +673,7 @@ pub(crate) fn handle_document_symbol( pub(crate) fn handle_workspace_symbol( snap: GlobalStateSnapshot, params: WorkspaceSymbolParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_workspace_symbol").entered(); let config = snap.config.workspace_symbol(None); @@ -696,7 +698,7 @@ pub(crate) fn handle_workspace_symbol( res = exec_query(&snap, Query::new(params.query), config.search_limit)?; } - return Ok(Some(lsp_types::WorkspaceSymbolResponse::Nested(res))); + return Ok(Some(lsp_types::WorkspaceSymbolRequestResponse::WorkspaceSymbolList(res))); fn decide_search_kind_and_scope( params: &WorkspaceSymbolParams, @@ -743,19 +745,23 @@ pub(crate) fn handle_workspace_symbol( let container_name = nav.container_name.as_ref().map(|v| v.to_string()); let info = lsp_types::WorkspaceSymbol { - name: match &nav.alias { - Some(alias) => format!("{} (alias for {})", alias, nav.name), - None => format!("{}", nav.name), - }, - kind: nav - .kind - .map(to_proto::symbol_kind) - .unwrap_or(lsp_types::SymbolKind::VARIABLE), - // FIXME: Set deprecation - tags: None, - container_name, - location: lsp_types::OneOf::Left(to_proto::location_from_nav(snap, nav)?), + location: lsp_types::WorkspaceSymbolLocation::Location( + to_proto::location_from_nav(snap, &nav)?, + ), data: None, + base_symbol_information: lsp_types::BaseSymbolInformation { + name: match &nav.alias { + Some(alias) => format!("{} (alias for {})", alias, nav.name), + None => format!("{}", nav.name), + }, + kind: nav + .kind + .map(to_proto::symbol_kind) + .unwrap_or(lsp_types::SymbolKind::Variable), + // FIXME: Set deprecation + tags: None, + container_name, + }, }; res.push(info); } @@ -771,42 +777,42 @@ pub(crate) fn handle_will_rename_files( let source_changes: Vec = params .files - .into_iter() - .filter_map(|file_rename| { - let from = Url::parse(&file_rename.old_uri).ok()?; - let to = Url::parse(&file_rename.new_uri).ok()?; - - let from_path = from.to_file_path().ok()?; - let to_path = to.to_file_path().ok()?; - - // Limit to single-level moves for now. - match (from_path.parent(), to_path.parent()) { - (Some(p1), Some(p2)) if p1 == p2 => { - if from_path.is_dir() { - // add '/' to end of url -- from `file://path/to/folder` to `file://path/to/folder/` - let mut old_folder_name = from_path.file_stem()?.to_str()?.to_owned(); - old_folder_name.push('/'); - let from_with_trailing_slash = from.join(&old_folder_name).ok()?; - - let imitate_from_url = from_with_trailing_slash.join("mod.rs").ok()?; - let new_file_name = to_path.file_name()?.to_str()?; - Some(( - snap.url_to_file_id(&imitate_from_url).ok()?, - new_file_name.to_owned(), - )) - } else { - let old_name = from_path.file_stem()?.to_str()?; - let new_name = to_path.file_stem()?.to_str()?; - match (old_name, new_name) { - ("mod", _) => None, - (_, "mod") => None, - _ => Some((snap.url_to_file_id(&from).ok()?, new_name.to_owned())), + .iter() + .filter_map( + |file_rename| -> Option<(std::option::Option, std::string::String)> { + let from = Uri(file_rename.old_uri.clone()); + + let Ok(from_path) = Utf8PathBuf::from_str(&file_rename.old_uri); + let Ok(to_path) = Utf8PathBuf::from_str(&file_rename.new_uri); + + // Limit to single-level moves for now. + match (from_path.parent(), to_path.parent()) { + (Some(p1), Some(p2)) if p1 == p2 => { + if from_path.is_dir() { + // add '/' to end of url -- from `file://path/to/folder` to `file://path/to/folder/` + let mut old_folder_name = from_path.file_stem()?.to_owned(); + old_folder_name.push('/'); + let from_with_trailing_slash = from_path.join(&old_folder_name); + + let imitate_from_url = from_with_trailing_slash.join("mod.rs"); + let new_file_name = to_path.file_name()?.to_owned(); + let uri = Uri(imitate_from_url.to_string()); + let vfs_path = from_proto::vfs_path(&uri).ok()?; + Some((snap.vfs_path_to_file_id(&vfs_path).ok()?, new_file_name)) + } else { + let old_name = from_path.file_stem()?; + let new_name = to_path.file_stem()?; + match (old_name, new_name) { + ("mod", _) => None, + (_, "mod") => None, + _ => Some((snap.url_to_file_id(&from).ok()?, new_name.to_owned())), + } } } + _ => None, } - _ => None, - } - }) + }, + ) .filter_map(|(file_id, new_name)| { let file_id = file_id?; let source_root = snap.analysis.source_root_id(file_id).ok(); @@ -831,11 +837,11 @@ pub(crate) fn handle_will_rename_files( pub(crate) fn handle_goto_definition( snap: GlobalStateSnapshot, - params: lsp_types::GotoDefinitionParams, -) -> anyhow::Result> { + params: lsp_types::DefinitionParams, +) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_definition").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let config = snap.config.goto_definition(snap.minicore()); let nav_info = match snap.analysis.goto_definition(position, &config)? { None => return Ok(None), @@ -848,69 +854,92 @@ pub(crate) fn handle_goto_definition( pub(crate) fn handle_goto_declaration( snap: GlobalStateSnapshot, - params: lsp_types::request::GotoDeclarationParams, -) -> anyhow::Result> { + params: lsp_types::DeclarationParams, +) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_declaration").entered(); - let position = try_default!(from_proto::file_position( - &snap, - params.text_document_position_params.clone() - )?); + let position = + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let config = snap.config.goto_definition(snap.minicore()); let nav_info = match snap.analysis.goto_declaration(position, &config)? { - None => return handle_goto_definition(snap, params), + None => { + // fallback to goto definition + let params = lsp_types::DefinitionParams { + work_done_progress_params: params.work_done_progress_params, + partial_result_params: params.partial_result_params, + text_document_position_params: params.text_document_position_params, + }; + return match handle_goto_definition(snap, params) { + Ok(Some(x)) => match x { + lsp_types::DefinitionRequestResponse::Definition(definition) => Ok(Some( + lsp_types::DeclarationRequestResponse::Declaration(match definition { + lsp_types::Definition::Location(location) => { + lsp_types::Declaration::Location(location) + } + lsp_types::Definition::LocationList(locations) => { + lsp_types::Declaration::LocationList(locations) + } + }), + )), + lsp_types::DefinitionRequestResponse::DefinitionLinkList(location_links) => { + Ok(Some(lsp_types::DeclarationRequestResponse::DeclarationLinkList( + location_links, + ))) + } + }, + Ok(None) => Ok(None), + Err(error) => Err(error), + }; + } Some(it) => it, }; let src = FileRange { file_id: position.file_id, range: nav_info.range }; - let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; + let res = to_proto::goto_declaration_response(&snap, Some(src), nav_info.info)?; Ok(Some(res)) } pub(crate) fn handle_goto_implementation( snap: GlobalStateSnapshot, - params: lsp_types::request::GotoImplementationParams, -) -> anyhow::Result> { + params: lsp_types::ImplementationParams, +) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_implementation").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let nav_info = match snap.analysis.goto_implementation(&snap.config.goto_implementation(), position)? { None => return Ok(None), Some(it) => it, }; let src = FileRange { file_id: position.file_id, range: nav_info.range }; - let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; + let res = to_proto::goto_implementation_response(&snap, Some(src), nav_info.info)?; Ok(Some(res)) } pub(crate) fn handle_goto_type_definition( snap: GlobalStateSnapshot, - params: lsp_types::request::GotoTypeDefinitionParams, -) -> anyhow::Result> { + params: lsp_types::TypeDefinitionParams, +) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_type_definition").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let nav_info = match snap.analysis.goto_type_definition(position)? { None => return Ok(None), Some(it) => it, }; let src = FileRange { file_id: position.file_id, range: nav_info.range }; - let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?; + let res = to_proto::goto_type_definition_response(&snap, Some(src), nav_info.info)?; Ok(Some(res)) } pub(crate) fn handle_parent_module( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_parent_module").entered(); - if let Ok(file_path) = ¶ms.text_document.uri.to_file_path() { + if let Ok(file_path) = &Utf8PathBuf::from_str(¶ms.text_document.uri.0) { if file_path.file_name().unwrap_or_default() == "Cargo.toml" { // search workspaces for parent packages or fallback to workspace root - let abs_path_buf = match Utf8PathBuf::from_path_buf(file_path.to_path_buf()) - .ok() - .map(AbsPathBuf::try_from) - { - Some(Ok(abs_path_buf)) => abs_path_buf, + let abs_path_buf = match AbsPathBuf::try_from(file_path.to_owned()) { + Ok(abs_path_buf) => abs_path_buf, _ => return Ok(None), }; @@ -965,7 +994,7 @@ pub(crate) fn handle_parent_module( } // locate parent module by semantics - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let navs = snap.analysis.parent_module(position)?; let res = to_proto::goto_definition_response(&snap, None, navs)?; Ok(Some(res)) @@ -974,10 +1003,10 @@ pub(crate) fn handle_parent_module( pub(crate) fn handle_child_modules( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_child_modules").entered(); // locate child module by semantics - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let navs = snap.analysis.child_modules(position)?; let res = to_proto::goto_definition_response(&snap, None, navs)?; Ok(Some(res)) @@ -991,7 +1020,7 @@ pub(crate) fn handle_runnables( let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let source_root = snap.analysis.source_root_id(file_id).ok(); let line_index = snap.file_line_index(file_id)?; - let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok()); + let offset = params.position.and_then(|it| from_proto::offset(&line_index, &it).ok()); let target_spec = TargetSpec::for_file(&snap, file_id)?; let mut res = Vec::new(); @@ -1105,7 +1134,7 @@ pub(crate) fn handle_related_tests( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_related_tests").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let tests = snap.analysis.related_tests(position, None)?; let mut res = Vec::new(); @@ -1121,14 +1150,14 @@ pub(crate) fn handle_related_tests( pub(crate) fn handle_completion( snap: GlobalStateSnapshot, lsp_types::CompletionParams { - text_document_position, + text_document_position_params, context, .. }: lsp_types::CompletionParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_completion").entered(); let mut position = - try_default!(from_proto::file_position(&snap, text_document_position.clone())?); + try_default!(from_proto::file_position(&snap, &text_document_position_params)?); let line_index = snap.file_line_index(position.file_id)?; let completion_trigger_character = context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next()); @@ -1151,12 +1180,17 @@ pub(crate) fn handle_completion( &completion_config.fields_to_resolve, &line_index, snap.file_version(position.file_id), - text_document_position, + &text_document_position_params, completion_trigger_character, items, ); - let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; + let completion_list = lsp_types::CompletionList { + is_incomplete: true, + items, + item_defaults: None, + apply_kind: None, + }; Ok(Some(completion_list.into())) } @@ -1183,7 +1217,7 @@ pub(crate) fn handle_completion_resolve( .expect("we never provide completions for excluded files"); let line_index = snap.file_line_index(file_id)?; // FIXME: We should fix up the position when retrying the cancelled request instead - let Ok(offset) = from_proto::offset(&line_index, resolve_data.position.position) else { + let Ok(offset) = from_proto::offset(&line_index, &resolve_data.position.position) else { return Ok(original_completion); }; let source_root = snap.analysis.source_root_id(file_id)?; @@ -1219,7 +1253,7 @@ pub(crate) fn handle_completion_resolve( &forced_resolve_completions_config.fields_to_resolve, &line_index, snap.file_version(position.file_id), - resolve_data.position, + &resolve_data.position, resolve_data.trigger_character, vec![corresponding_completion], ); @@ -1289,7 +1323,7 @@ pub(crate) fn handle_signature_help( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_signature_help").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let help = match snap.analysis.signature_help(position)? { Some(it) => it, None => return Ok(None), @@ -1321,7 +1355,7 @@ pub(crate) fn handle_hover( let markup_kind = hover.format; let hover = lsp_ext::Hover { hover: lsp_types::Hover { - contents: HoverContents::Markup(to_proto::markup_content( + contents: Contents::MarkupContent(to_proto::markup_content( info.info.markup, markup_kind, )), @@ -1339,16 +1373,17 @@ pub(crate) fn handle_hover( pub(crate) fn handle_prepare_rename( snap: GlobalStateSnapshot, - params: lsp_types::TextDocumentPositionParams, -) -> anyhow::Result> { + params: lsp_types::PrepareRenameParams, +) -> anyhow::Result> { let _p = tracing::info_span!("handle_prepare_rename").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; let line_index = snap.file_line_index(position.file_id)?; let range = to_proto::range(&line_index, change.range); - Ok(Some(PrepareRenameResponse::Range(range))) + Ok(Some(PrepareRenameResult::Range(range))) } pub(crate) fn handle_rename( @@ -1356,7 +1391,8 @@ pub(crate) fn handle_rename( params: RenameParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_rename").entered(); - let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); + let position = + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let source_root = snap.analysis.source_root_id(position.file_id).ok(); let config = snap.config.rename(source_root); @@ -1377,13 +1413,9 @@ pub(crate) fn handle_rename( let workspace_edit = to_proto::workspace_edit(&snap, change)?; - if let Some(lsp_types::DocumentChanges::Operations(ops)) = - workspace_edit.document_changes.as_ref() - { - for op in ops { - if let lsp_types::DocumentChangeOperation::Op(doc_change_op) = op { - resource_ops_supported(&snap.config, resolve_resource_op(doc_change_op))? - } + if let Some(changes) = workspace_edit.document_changes.as_ref() { + for change in changes { + resource_ops_supported(&snap.config, change)?; } } @@ -1395,7 +1427,8 @@ pub(crate) fn handle_references( params: lsp_types::ReferenceParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_references").entered(); - let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); + let position = + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let exclude_imports = snap.config.find_all_refs_exclude_imports(); let exclude_tests = snap.config.find_all_refs_exclude_tests(); @@ -1444,7 +1477,7 @@ pub(crate) fn handle_formatting( ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_formatting").entered(); - run_rustfmt(&snap, params.text_document, None) + run_rustfmt(&snap, ¶ms.text_document, None) } pub(crate) fn handle_range_formatting( @@ -1453,7 +1486,7 @@ pub(crate) fn handle_range_formatting( ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_range_formatting").entered(); - run_rustfmt(&snap, params.text_document, Some(params.range)) + run_rustfmt(&snap, ¶ms.text_document, Some(params.range)) } pub(crate) fn handle_code_action( @@ -1508,8 +1541,8 @@ pub(crate) fn handle_code_action( let changes = code_action.edit.as_ref().and_then(|it| it.document_changes.as_ref()); if let Some(changes) = changes { for change in changes { - if let lsp_ext::SnippetDocumentChangeOperation::Op(res_op) = change { - resource_ops_supported(&snap.config, resolve_resource_op(res_op))? + if let lsp_ext::SnippetDocumentChangeOperation::Change(change) = change { + resource_ops_supported(&snap.config, change)? } } } @@ -1611,8 +1644,8 @@ pub(crate) fn handle_code_action_resolve( && let Some(changes) = edit.document_changes.as_ref() { for change in changes { - if let lsp_ext::SnippetDocumentChangeOperation::Op(res_op) = change { - resource_ops_supported(&snap.config, resolve_resource_op(res_op))? + if let lsp_ext::SnippetDocumentChangeOperation::Change(change) = change { + resource_ops_supported(&snap.config, change)? } } } @@ -1716,7 +1749,7 @@ pub(crate) fn handle_document_highlight( ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_document_highlight").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let line_index = snap.file_line_index(position.file_id)?; let source_root = snap.analysis.source_root_id(position.file_id)?; @@ -1749,7 +1782,7 @@ pub(crate) fn handle_ssr( .map(|range| from_proto::file_range(&snap, ¶ms.position.text_document, *range)) .collect::>, _>>()? ); - let position = try_default!(from_proto::file_position(&snap, params.position)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms.position)?); let source_change = snap.analysis.structural_search_replace( ¶ms.query, params.parse_only, @@ -1854,7 +1887,7 @@ pub(crate) fn handle_call_hierarchy_prepare( ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_call_hierarchy_prepare").entered(); let position = - try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); + try_default!(from_proto::file_position(&snap, ¶ms.text_document_position_params)?); let config = snap.config.call_hierarchy(snap.minicore()); let nav_info = match snap.analysis.call_hierarchy(position, &config)? { @@ -1889,25 +1922,26 @@ pub(crate) fn handle_call_hierarchy_incoming( Some(it) => it, }; - let mut res = vec![]; - - for call_item in call_items.into_iter() { - let file_id = call_item.target.file_id; - let line_index = snap.file_line_index(file_id)?; - let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; - res.push(CallHierarchyIncomingCall { - from: item, - from_ranges: call_item - .ranges - .into_iter() - // This is the range relative to the item - .filter(|it| it.file_id == file_id) - .map(|it| to_proto::range(&line_index, it.range)) - .collect(), - }); - } - - Ok(Some(res)) + Ok(Some( + call_items + .into_iter() + .map(|call_item| { + let file_id = call_item.target.file_id; + let line_index = snap.file_line_index(file_id)?; + let item = to_proto::call_hierarchy_item(&snap, call_item.target)?; + Ok(CallHierarchyIncomingCall { + from: item, + from_ranges: call_item + .ranges + .iter() + // This is the range relative to the item + .filter(|it| it.file_id == file_id) + .map(|it| to_proto::range(&line_index, it.range)) + .collect(), + }) + }) + .collect::>()?, + )) } pub(crate) fn handle_call_hierarchy_outgoing( @@ -1950,7 +1984,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( pub(crate) fn handle_semantic_tokens_full( snap: GlobalStateSnapshot, params: SemanticTokensParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_full").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); @@ -1974,13 +2008,13 @@ pub(crate) fn handle_semantic_tokens_full( // Unconditionally cache the tokens snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone()); - Ok(Some(semantic_tokens.into())) + Ok(Some(semantic_tokens)) } pub(crate) fn handle_semantic_tokens_full_delta( snap: GlobalStateSnapshot, params: SemanticTokensDeltaParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_full_delta").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); @@ -2022,7 +2056,7 @@ pub(crate) fn handle_semantic_tokens_full_delta( pub(crate) fn handle_semantic_tokens_range( snap: GlobalStateSnapshot, params: SemanticTokensRangeParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_range").entered(); let frange = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?); @@ -2042,7 +2076,7 @@ pub(crate) fn handle_semantic_tokens_range( snap.config.semantics_tokens_augments_syntax_tokens(), snap.config.highlighting_non_standard_tokens(), ); - Ok(Some(semantic_tokens.into())) + Ok(Some(semantic_tokens)) } pub(crate) fn handle_open_docs( @@ -2050,7 +2084,7 @@ pub(crate) fn handle_open_docs( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_open_docs").entered(); - let position = try_default!(from_proto::file_position(&snap, params)?); + let position = try_default!(from_proto::file_position(&snap, ¶ms)?); let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind { ProjectWorkspaceKind::Cargo { cargo, .. } @@ -2077,8 +2111,8 @@ pub(crate) fn handle_open_docs( }; }; - let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok()); - let local = remote_urls.local_url.and_then(|it| Url::parse(&it).ok()); + let web = remote_urls.web_url.map(Uri); + let local = remote_urls.local_url.map(Uri); if snap.config.local_docs() { Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local })) @@ -2090,7 +2124,7 @@ pub(crate) fn handle_open_docs( pub(crate) fn handle_open_cargo_toml( snap: GlobalStateSnapshot, params: lsp_ext::OpenCargoTomlParams, -) -> anyhow::Result> { +) -> anyhow::Result> { let _p = tracing::info_span!("handle_open_cargo_toml").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); @@ -2100,8 +2134,9 @@ pub(crate) fn handle_open_cargo_toml( }; let cargo_toml_url = to_proto::url_from_abs_path(&cargo_spec.cargo_toml); - let res: lsp_types::GotoDefinitionResponse = - Location::new(cargo_toml_url, Range::default()).into(); + let res = lsp_types::DefinitionRequestResponse::Definition(lsp_types::Definition::Location( + Location::new(cargo_toml_url, Range::default()), + )); Ok(Some(res)) } @@ -2139,7 +2174,7 @@ pub(crate) fn handle_view_recursive_memory_layout( let _p = tracing::info_span!("handle_view_recursive_memory_layout").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; - let offset = from_proto::offset(&line_index, params.position)?; + let offset = from_proto::offset(&line_index, ¶ms.position)?; let res = snap.analysis.get_recursive_memory_layout(FilePosition { file_id, offset })?; Ok(res.map(|it| lsp_ext::RecursiveMemoryLayout { @@ -2183,7 +2218,7 @@ fn show_impl_command_link( let locations: Vec<_> = nav_data .info .into_iter() - .filter_map(|nav| to_proto::location_from_nav(snap, nav).ok()) + .filter_map(|nav| to_proto::location_from_nav(snap, &nav).ok()) .collect(); let title = to_proto::implementation_title(locations.len()); let command = to_proto::command::show_references(title, &uri, position, locations); @@ -2358,7 +2393,7 @@ fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&TargetSpec>) -> b fn run_rustfmt( snap: &GlobalStateSnapshot, - text_document: TextDocumentIdentifier, + text_document: &TextDocumentIdentifier, range: Option, ) -> anyhow::Result>> { let file_id = try_default!(from_proto::file_id(snap, &text_document.uri)?); @@ -2371,17 +2406,21 @@ fn run_rustfmt( // try to chdir to the file so we can respect `rustfmt.toml` // FIXME: use `rustfmt --config-path` once // https://github.com/rust-lang/rustfmt/issues/4660 gets fixed - let current_dir = match text_document.uri.to_file_path() { + let current_dir = match Utf8PathBuf::from_str(&text_document.uri.0) { Ok(mut path) => { // pop off file name - if path.pop() && path.is_dir() { path } else { std::env::current_dir()? } + if path.pop() && path.is_dir() { + path + } else { + Utf8PathBuf::from_path_buf(std::env::current_dir()?).unwrap() + } } Err(_) => { tracing::error!( text_document = ?text_document.uri, "Unable to get path, rustfmt.toml might be ignored" ); - std::env::current_dir()? + Utf8PathBuf::from_path_buf(std::env::current_dir()?).unwrap() } }; @@ -2424,7 +2463,7 @@ fn run_rustfmt( .into()); } - let frange = try_default!(from_proto::file_range(snap, &text_document, range)?); + let frange = try_default!(from_proto::file_range(snap, text_document, range)?); let start_line = line_index.index.line_col(frange.range.start()).line; let end_line = line_index.index.line_col(frange.range.end()).line; @@ -2454,9 +2493,7 @@ fn run_rustfmt( let cmd_path = if command.contains(std::path::MAIN_SEPARATOR) || (cfg!(windows) && command.contains('/')) { - let project_root = Utf8PathBuf::from_path_buf(current_dir.clone()) - .ok() - .and_then(|p| AbsPathBuf::try_from(p).ok()); + let project_root = AbsPathBuf::try_from(current_dir.clone()); let project_root = project_root .as_ref() .map(|dir| snap.config.workspace_root_for(dir)) @@ -2560,11 +2597,9 @@ pub(crate) fn fetch_dependency_list( .into_iter() .filter_map(|it| { let root_file_path = state.file_id_to_file_path(it.root_file_id); - crate_path(&root_file_path).and_then(to_url).map(|path| CrateInfoResult { - name: it.name, - version: it.version, - path, - }) + crate_path(&root_file_path) + .map(|path| Uri(path.to_string())) + .map(|path| CrateInfoResult { name: it.name, version: it.version, path }) }) .collect(); Ok(FetchDependencyListResult { crates: crate_infos }) @@ -2604,7 +2639,7 @@ pub(crate) fn get_failed_obligations( let _p = tracing::info_span!("get_failed_obligations").entered(); let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; - let offset = from_proto::offset(&line_index, params.position)?; + let offset = from_proto::offset(&line_index, ¶ms.position)?; Ok(snap.analysis.get_failed_obligations(offset, file_id)?) } @@ -2633,20 +2668,20 @@ fn crate_path(root_file_path: &VfsPath) -> Option { None } -fn to_url(path: VfsPath) -> Option { - let path = path.as_path()?; - let str_path = path.as_os_str().to_str()?; - Url::from_file_path(str_path).ok() -} - -fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyhow::Result<()> { - if !matches!(config.workspace_edit_resource_operations(), Some(resops) if resops.contains(&kind)) +fn resource_ops_supported(config: &Config, kind: &DocumentChange) -> anyhow::Result<()> { + let op = match kind { + lsp_types::DocumentChange::CreateFile(_) => ResourceOperationKind::Create, + lsp_types::DocumentChange::RenameFile(_) => ResourceOperationKind::Rename, + lsp_types::DocumentChange::DeleteFile(_) => ResourceOperationKind::Delete, + lsp_types::DocumentChange::TextDocumentEdit(_) => return Ok(()), + }; + if !matches!(config.workspace_edit_resource_operations(), Some(resops) if resops.contains(&op)) { return Err(LspError::new( ErrorCode::RequestFailed as i32, format!( "Client does not support {} capability.", - match kind { + match op { ResourceOperationKind::Create => "create", ResourceOperationKind::Rename => "rename", ResourceOperationKind::Delete => "delete", @@ -2659,14 +2694,6 @@ fn resource_ops_supported(config: &Config, kind: ResourceOperationKind) -> anyho Ok(()) } -fn resolve_resource_op(op: &ResourceOp) -> ResourceOperationKind { - match op { - ResourceOp::Create(_) => ResourceOperationKind::Create, - ResourceOp::Rename(_) => ResourceOperationKind::Rename, - ResourceOp::Delete(_) => ResourceOperationKind::Delete, - } -} - pub(crate) fn diff(left: &str, right: &str) -> TextEdit { use dissimilar::Chunk; diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 4a37bb34aba3..9eb243f91b38 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -60,6 +60,8 @@ pub mod tracing { pub mod config; mod global_state; pub mod lsp; +use std::fmt; + use self::lsp::ext as lsp_ext; #[cfg(test)] @@ -73,7 +75,7 @@ pub use crate::{ }; pub fn from_json( - what: &'static str, + what: impl fmt::Display, json: &serde_json::Value, ) -> anyhow::Result { serde_json::from_value(json.clone()) diff --git a/crates/rust-analyzer/src/lsp/capabilities.rs b/crates/rust-analyzer/src/lsp/capabilities.rs index 3ad4cb70b419..f2465d37497c 100644 --- a/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/crates/rust-analyzer/src/lsp/capabilities.rs @@ -2,19 +2,21 @@ use ide::{CompletionFieldsToResolve, InlayFieldsToResolve}; use ide_db::{FxHashSet, line_index::WideEncoding}; use lsp_types::{ - CallHierarchyServerCapability, CodeActionKind, CodeActionOptions, CodeActionProviderCapability, - CodeLensOptions, CompletionOptions, CompletionOptionsCompletionItem, DeclarationCapability, - DocumentOnTypeFormattingOptions, FileOperationFilter, FileOperationPattern, - FileOperationPatternKind, FileOperationRegistrationOptions, FoldingRangeProviderCapability, - HoverProviderCapability, ImplementationProviderCapability, InlayHintOptions, - InlayHintServerCapabilities, OneOf, PositionEncodingKind, RenameOptions, SaveOptions, - SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend, - SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, - TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, - WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities, - WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, + CallHierarchyProvider, ChangeNotifications, CodeActionKind, CodeActionOptions, + CodeActionProvider, CodeLensOptions, CompletionOptions, DeclarationProvider, + DefinitionProvider, DocumentFormattingProvider, DocumentHighlightProvider, + DocumentOnTypeFormattingOptions, DocumentRangeFormattingProvider, DocumentSymbolProvider, + FileOperationFilter, FileOperationOptions, FileOperationPattern, FileOperationPatternKind, + FileOperationRegistrationOptions, FoldingRangeProvider, Full, HoverProvider, + ImplementationProvider, InlayHintOptions, InlayHintProvider, PositionEncodingKind, + ReferencesProvider, RenameOptions, RenameProvider, SaveOptions, SelectionRangeProvider, + SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities, ServerCompletionItemOptions, + SignatureHelpOptions, TextDocumentSync, TextDocumentSyncKind, TextDocumentSyncOptions, + TypeDefinitionProvider, WorkDoneProgressOptions, WorkspaceFoldersServerCapabilities, + WorkspaceOptions, WorkspaceSymbolProvider, }; use serde_json::json; +use strum::IntoEnumIterator; use crate::{ config::{Config, RustfmtConfig}, @@ -32,9 +34,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { _ => None, }, }, - text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { + text_document_sync: Some(TextDocumentSync::Options(TextDocumentSyncOptions { open_close: Some(true), - change: Some(TextDocumentSyncKind::INCREMENTAL), + change: Some(TextDocumentSyncKind::Incremental), will_save: None, will_save_wait_until: None, save: if config.caps().did_save_text_document_dynamic_registration() { @@ -43,7 +45,9 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { Some(SaveOptions::default().into()) }, })), - hover_provider: Some(HoverProviderCapability::Simple(true)), + notebook_document_sync: None, + selection_range_provider: Some(SelectionRangeProvider::Bool(true)), + hover_provider: Some(HoverProvider::Bool(true)), completion_provider: Some(CompletionOptions { resolve_provider: if config.client_is_neovim() { config.has_completion_item_resolve_additionalTextEdits().then_some(true) @@ -65,20 +69,24 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { retrigger_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), - declaration_provider: Some(DeclarationCapability::Simple(true)), - definition_provider: Some(OneOf::Left(true)), - type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), - implementation_provider: Some(ImplementationProviderCapability::Simple(true)), - references_provider: Some(OneOf::Left(true)), - document_highlight_provider: Some(OneOf::Left(true)), - document_symbol_provider: Some(OneOf::Left(true)), - workspace_symbol_provider: Some(OneOf::Left(true)), + definition_provider: Some(DefinitionProvider::Bool(true)), + type_definition_provider: Some(TypeDefinitionProvider::Bool(true)), + implementation_provider: Some(ImplementationProvider::Bool(true)), + references_provider: Some(ReferencesProvider::Bool(true)), + document_highlight_provider: Some(DocumentHighlightProvider::Bool(true)), + document_symbol_provider: Some(DocumentSymbolProvider::Bool(true)), + workspace_symbol_provider: Some(WorkspaceSymbolProvider::Bool(true)), code_action_provider: Some(config.caps().code_action_capabilities()), - code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), - document_formatting_provider: Some(OneOf::Left(true)), + code_lens_provider: Some(CodeLensOptions { + resolve_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, + }), + document_formatting_provider: Some(DocumentFormattingProvider::Bool(true)), document_range_formatting_provider: match config.rustfmt(None) { - RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)), - _ => Some(OneOf::Left(false)), + RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => { + Some(DocumentRangeFormattingProvider::Bool(true)) + } + _ => Some(DocumentRangeFormattingProvider::Bool(false)), }, document_on_type_formatting_provider: Some({ let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.iter(); @@ -87,22 +95,21 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { more_trigger_character: Some(chars.map(|c| c.to_string()).collect()), } }), - selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), - folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), - rename_provider: Some(OneOf::Right(RenameOptions { + rename_provider: Some(RenameProvider::RenameOptions(RenameOptions { prepare_provider: Some(true), work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), - linked_editing_range_provider: None, document_link_provider: None, color_provider: None, + folding_range_provider: Some(FoldingRangeProvider::Bool(true)), + declaration_provider: Some(DeclarationProvider::Bool(true)), execute_command_provider: None, - workspace: Some(WorkspaceServerCapabilities { + workspace: Some(WorkspaceOptions { workspace_folders: Some(WorkspaceFoldersServerCapabilities { supported: Some(true), - change_notifications: Some(OneOf::Left(true)), + change_notifications: Some(ChangeNotifications::Bool(true)), }), - file_operations: Some(WorkspaceFileOperationsServerCapabilities { + file_operations: Some(FileOperationOptions { did_create: None, will_create: None, did_rename: None, @@ -129,29 +136,45 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { did_delete: None, will_delete: None, }), + text_document_content: None, }), - call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), + call_hierarchy_provider: Some(CallHierarchyProvider::Bool(true)), semantic_tokens_provider: Some( SemanticTokensOptions { legend: SemanticTokensLegend { - token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(), - token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), + token_types: semantic_tokens::SupportedType::iter() + .map(|semantic_token_type| semantic_token_type.to_string()) + .collect(), + token_modifiers: semantic_tokens::SupportedModifiers::iter() + .map(|semantic_token_type| semantic_token_type.to_string()) + .collect(), }, - full: Some(SemanticTokensFullOptions::Delta { delta: Some(true) }), - range: Some(true), + full: Some(Full::SemanticTokensFullDelta(lsp_types::SemanticTokensFullDelta { + delta: Some(true), + })), + range: Some(lsp_types::SemanticTokensOptionsRange::Bool(true)), work_done_progress_options: Default::default(), } .into(), ), moniker_provider: None, - inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( - InlayHintOptions { - work_done_progress_options: Default::default(), - resolve_provider: Some(config.caps().inlay_hints_resolve_provider()), - }, - ))), + linked_editing_range_provider: None, inline_value_provider: None, + inlay_hint_provider: Some(InlayHintProvider::InlayHintOptions(InlayHintOptions { + work_done_progress_options: Default::default(), + resolve_provider: Some(config.caps().inlay_hints_resolve_provider()), + })), + diagnostic_provider: Some(lsp_types::DiagnosticProvider::DiagnosticOptions( + lsp_types::DiagnosticOptions { + identifier: Some("rust-analyzer".to_owned()), + inter_file_dependencies: true, + // FIXME + workspace_diagnostics: false, + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, + }, + )), + inline_completion_provider: None, experimental: Some(json!({ "externalDocs": true, "hoverRange": true, @@ -168,16 +191,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { "ssr": true, "workspaceSymbolScopeKindFiltering": true, })), - diagnostic_provider: Some(lsp_types::DiagnosticServerCapabilities::Options( - lsp_types::DiagnosticOptions { - identifier: Some("rust-analyzer".to_owned()), - inter_file_dependencies: true, - // FIXME - workspace_diagnostics: false, - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, - }, - )), - inline_completion_provider: None, + type_hierarchy_provider: None, } } @@ -244,33 +258,34 @@ impl ClientCapabilities { })() == Some(true) } - fn completion_item(&self) -> Option { - Some(CompletionOptionsCompletionItem { + fn completion_item(&self) -> Option { + Some(ServerCompletionItemOptions { label_details_support: Some(self.completion_label_details_support()), }) } - fn code_action_capabilities(&self) -> CodeActionProviderCapability { + fn code_action_capabilities(&self) -> CodeActionProvider { self.0 .text_document .as_ref() .and_then(|it| it.code_action.as_ref()) .and_then(|it| it.code_action_literal_support.as_ref()) - .map_or(CodeActionProviderCapability::Simple(true), |_| { - CodeActionProviderCapability::Options(CodeActionOptions { + .map_or(CodeActionProvider::Bool(true), |_| { + CodeActionProvider::CodeActionOptions(CodeActionOptions { // Advertise support for all built-in CodeActionKinds. // Ideally we would base this off of the client capabilities // but the client is supposed to fall back gracefully for unknown values. code_action_kinds: Some(vec![ - CodeActionKind::EMPTY, - CodeActionKind::QUICKFIX, - CodeActionKind::REFACTOR, - CodeActionKind::REFACTOR_EXTRACT, - CodeActionKind::REFACTOR_INLINE, - CodeActionKind::REFACTOR_REWRITE, + CodeActionKind::Empty, + CodeActionKind::QuickFix, + CodeActionKind::Refactor, + CodeActionKind::Refactor, + CodeActionKind::Refactor, + CodeActionKind::RefactorRewrite, ]), resolve_provider: Some(true), work_done_progress_options: Default::default(), + documentation: None, }) }) } @@ -307,8 +322,8 @@ impl ClientCapabilities { } pub fn did_save_text_document_dynamic_registration(&self) -> bool { - let caps = (|| -> _ { self.0.text_document.as_ref()?.synchronization.clone() })() - .unwrap_or_default(); + let caps = + (|| -> _ { self.0.text_document.as_ref()?.synchronization })().unwrap_or_default(); caps.did_save == Some(true) && caps.dynamic_registration == Some(true) } @@ -455,6 +470,8 @@ impl ClientCapabilities { } pub fn snippet_text_edit(&self) -> bool { + // FIXME: apply https://github.com/rust-lang/rust-analyzer/pull/22088 + // self.0.workspace.unwrap().workspace_edit.unwrap().snippet_edit_support self.experimental_bool("snippetTextEdit") } @@ -501,7 +518,7 @@ impl ClientCapabilities { } pub fn diagnostics_refresh(&self) -> bool { - (|| -> _ { self.0.workspace.as_ref()?.diagnostic.as_ref()?.refresh_support })() + (|| -> _ { self.0.workspace.as_ref()?.diagnostics.as_ref()?.refresh_support })() .unwrap_or_default() } diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index 5d0d9209de2f..53a79bae4922 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/crates/rust-analyzer/src/lsp/ext.rs @@ -6,19 +6,18 @@ #![allow(clippy::disallowed_types)] -use std::ops; +use std::{borrow::Cow, ops}; -use lsp_types::Url; -use lsp_types::request::Request; use lsp_types::{ - CodeActionKind, DocumentOnTypeFormattingParams, PartialResultParams, Position, Range, - TextDocumentIdentifier, WorkDoneProgressParams, notification::Notification, + CodeActionKind, DocumentOnTypeFormattingParams, LspNotificationMethods, LspRequestMethods, + MessageDirection, Notification, PartialResultParams, Position, Range, Request, + TextDocumentIdentifier, Uri, WorkDoneProgressParams, }; use paths::Utf8PathBuf; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; -pub enum InternalTestingFetchConfig {} +pub enum InternalTestingFetchConfigRequest {} #[derive(Deserialize, Serialize, Debug)] pub enum InternalTestingFetchConfigOption { @@ -32,11 +31,14 @@ pub enum InternalTestingFetchConfigResponse { CheckWorkspace(bool), } -impl Request for InternalTestingFetchConfig { +impl Request for InternalTestingFetchConfigRequest { type Params = InternalTestingFetchConfigParams; // Option is solely to circumvent Default bound. type Result = Option; - const METHOD: &'static str = "rust-analyzer-internal/internalTestingFetchConfig"; + const METHOD: LspRequestMethods = LspRequestMethods::Custom(Cow::Borrowed( + "rust-analyzer-internal/internalTestingFetchConfig", + )); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -45,12 +47,14 @@ pub struct InternalTestingFetchConfigParams { pub text_document: Option, pub config: InternalTestingFetchConfigOption, } -pub enum AnalyzerStatus {} +pub enum AnalyzerStatusRequest {} -impl Request for AnalyzerStatus { +impl Request for AnalyzerStatusRequest { type Params = AnalyzerStatusParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/analyzerStatus"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/analyzerStatus")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -64,14 +68,16 @@ pub struct AnalyzerStatusParams { pub struct CrateInfoResult { pub name: Option, pub version: Option, - pub path: Url, + pub path: Uri, } -pub enum FetchDependencyList {} +pub enum FetchDependencyListRequest {} -impl Request for FetchDependencyList { +impl Request for FetchDependencyListRequest { type Params = FetchDependencyListParams; type Result = FetchDependencyListResult; - const METHOD: &'static str = "rust-analyzer/fetchDependencyList"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/fetchDependencyList")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -84,36 +90,44 @@ pub struct FetchDependencyListResult { pub crates: Vec, } -pub enum MemoryUsage {} +pub enum MemoryUsageRequest {} -impl Request for MemoryUsage { +impl Request for MemoryUsageRequest { type Params = (); type Result = String; - const METHOD: &'static str = "rust-analyzer/memoryUsage"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/memoryUsage")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ReloadWorkspace {} +pub enum ReloadWorkspaceRequest {} -impl Request for ReloadWorkspace { +impl Request for ReloadWorkspaceRequest { type Params = (); type Result = (); - const METHOD: &'static str = "rust-analyzer/reloadWorkspace"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/reloadWorkspace")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum RebuildProcMacros {} +pub enum RebuildProcMacrosRequest {} -impl Request for RebuildProcMacros { +impl Request for RebuildProcMacrosRequest { type Params = (); type Result = (); - const METHOD: &'static str = "rust-analyzer/rebuildProcMacros"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/rebuildProcMacros")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ViewSyntaxTree {} +pub enum ViewSyntaxTreeRequest {} -impl Request for ViewSyntaxTree { +impl Request for ViewSyntaxTreeRequest { type Params = ViewSyntaxTreeParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewSyntaxTree"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewSyntaxTree")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -122,28 +136,34 @@ pub struct ViewSyntaxTreeParams { pub text_document: TextDocumentIdentifier, } -pub enum ViewHir {} +pub enum ViewHirRequest {} -impl Request for ViewHir { +impl Request for ViewHirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewHir"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewHir")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ViewMir {} +pub enum ViewMirRequest {} -impl Request for ViewMir { +impl Request for ViewMirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewMir"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewMir")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum InterpretFunction {} +pub enum InterpretFunctionRequest {} -impl Request for InterpretFunction { +impl Request for InterpretFunctionRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/interpretFunction"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/interpretFunction")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } pub enum ViewFileText {} @@ -151,7 +171,9 @@ pub enum ViewFileText {} impl Request for ViewFileText { type Params = lsp_types::TextDocumentIdentifier; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewFileText"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewFileText")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -161,12 +183,14 @@ pub struct ViewCrateGraphParams { pub full: bool, } -pub enum ViewCrateGraph {} +pub enum ViewCrateGraphRequest {} -impl Request for ViewCrateGraph { +impl Request for ViewCrateGraphRequest { type Params = ViewCrateGraphParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewCrateGraph"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewCrateGraph")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -175,12 +199,14 @@ pub struct ViewItemTreeParams { pub text_document: TextDocumentIdentifier, } -pub enum ViewItemTree {} +pub enum ViewItemTreeRequest {} -impl Request for ViewItemTree { +impl Request for ViewItemTreeRequest { type Params = ViewItemTreeParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/viewItemTree"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewItemTree")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -218,19 +244,23 @@ pub struct DiscoverTestResults { pub scope_file: Option>, } -pub enum DiscoverTest {} +pub enum DiscoverTestRequest {} -impl Request for DiscoverTest { +impl Request for DiscoverTestRequest { type Params = DiscoverTestParams; type Result = DiscoverTestResults; - const METHOD: &'static str = "experimental/discoverTest"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/discoverTest")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum DiscoveredTests {} +pub enum DiscoveredTestsNotification {} -impl Notification for DiscoveredTests { +impl Notification for DiscoveredTestsNotification { type Params = DiscoverTestResults; - const METHOD: &'static str = "experimental/discoveredTests"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/discoveredTests")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -240,33 +270,41 @@ pub struct RunTestParams { pub exclude: Option>, } -pub enum RunTest {} +pub enum RunTestRequest {} -impl Request for RunTest { +impl Request for RunTestRequest { type Params = RunTestParams; type Result = (); - const METHOD: &'static str = "experimental/runTest"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/runTest")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum EndRunTest {} +pub enum EndRunTestNotification {} -impl Notification for EndRunTest { +impl Notification for EndRunTestNotification { type Params = (); - const METHOD: &'static str = "experimental/endRunTest"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/endRunTest")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum AppendOutputToRunTest {} +pub enum AppendOutputToRunTestNotification {} -impl Notification for AppendOutputToRunTest { +impl Notification for AppendOutputToRunTestNotification { type Params = String; - const METHOD: &'static str = "experimental/appendOutputToRunTest"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/appendOutputToRunTest")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum AbortRunTest {} +pub enum AbortRunTestNotification {} -impl Notification for AbortRunTest { +impl Notification for AbortRunTestNotification { type Params = (); - const METHOD: &'static str = "experimental/abortRunTest"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/abortRunTest")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -286,19 +324,23 @@ pub struct ChangeTestStateParams { pub state: TestState, } -pub enum ChangeTestState {} +pub enum ChangeTestStateNotification {} -impl Notification for ChangeTestState { +impl Notification for ChangeTestStateNotification { type Params = ChangeTestStateParams; - const METHOD: &'static str = "experimental/changeTestState"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/changeTestState")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ExpandMacro {} +pub enum ExpandMacroRequest {} -impl Request for ExpandMacro { +impl Request for ExpandMacroRequest { type Params = ExpandMacroParams; type Result = Option; - const METHOD: &'static str = "rust-analyzer/expandMacro"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/expandMacro")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -315,12 +357,14 @@ pub struct ExpandedMacro { pub expansion: String, } -pub enum ViewRecursiveMemoryLayout {} +pub enum ViewRecursiveMemoryLayoutRequest {} -impl Request for ViewRecursiveMemoryLayout { +impl Request for ViewRecursiveMemoryLayoutRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: &'static str = "rust-analyzer/viewRecursiveMemoryLayout"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/viewRecursiveMemoryLayout")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -342,32 +386,40 @@ pub struct MemoryLayoutNode { pub children_len: u64, } -pub enum CancelFlycheck {} +pub enum CancelFlycheckNotification {} -impl Notification for CancelFlycheck { +impl Notification for CancelFlycheckNotification { type Params = (); - const METHOD: &'static str = "rust-analyzer/cancelFlycheck"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("rust-analyzer/cancelFlycheck")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum RunFlycheck {} +pub enum RunFlycheckNotification {} -impl Notification for RunFlycheck { +impl Notification for RunFlycheckNotification { type Params = RunFlycheckParams; - const METHOD: &'static str = "rust-analyzer/runFlycheck"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("rust-analyzer/runFlycheck")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ClearFlycheck {} +pub enum ClearFlycheckNotification {} -impl Notification for ClearFlycheck { +impl Notification for ClearFlycheckNotification { type Params = (); - const METHOD: &'static str = "rust-analyzer/clearFlycheck"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("rust-analyzer/clearFlycheck")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum OpenServerLogs {} +pub enum OpenServerLogsNotification {} -impl Notification for OpenServerLogs { +impl Notification for OpenServerLogsNotification { type Params = (); - const METHOD: &'static str = "rust-analyzer/openServerLogs"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("rust-analyzer/openServerLogs")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -376,12 +428,14 @@ pub struct RunFlycheckParams { pub text_document: Option, } -pub enum MatchingBrace {} +pub enum MatchingBraceRequest {} -impl Request for MatchingBrace { +impl Request for MatchingBraceRequest { type Params = MatchingBraceParams; type Result = Vec; - const METHOD: &'static str = "experimental/matchingBrace"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/matchingBrace")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -391,28 +445,34 @@ pub struct MatchingBraceParams { pub positions: Vec, } -pub enum ParentModule {} +pub enum ParentModuleRequest {} -impl Request for ParentModule { +impl Request for ParentModuleRequest { type Params = lsp_types::TextDocumentPositionParams; - type Result = Option; - const METHOD: &'static str = "experimental/parentModule"; + type Result = Option; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/parentModule")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum ChildModules {} +pub enum ChildModulesRequest {} -impl Request for ChildModules { +impl Request for ChildModulesRequest { type Params = lsp_types::TextDocumentPositionParams; - type Result = Option; - const METHOD: &'static str = "experimental/childModules"; + type Result = Option; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/childModules")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum JoinLines {} +pub enum JoinLinesRequest {} -impl Request for JoinLines { +impl Request for JoinLinesRequest { type Params = JoinLinesParams; type Result = Vec; - const METHOD: &'static str = "experimental/joinLines"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/joinLines")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, Debug)] @@ -422,20 +482,24 @@ pub struct JoinLinesParams { pub ranges: Vec, } -pub enum OnEnter {} +pub enum OnEnterRequest {} -impl Request for OnEnter { +impl Request for OnEnterRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option>; - const METHOD: &'static str = "experimental/onEnter"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/onEnter")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } -pub enum Runnables {} +pub enum RunnablesRequest {} -impl Request for Runnables { +impl Request for RunnablesRequest { type Params = RunnablesParams; type Result = Vec; - const METHOD: &'static str = "experimental/runnables"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/runnables")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -496,12 +560,14 @@ pub struct ShellRunnableArgs { pub args: Vec, } -pub enum RelatedTests {} +pub enum RelatedTestsRequest {} -impl Request for RelatedTests { +impl Request for RelatedTestsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Vec; - const METHOD: &'static str = "rust-analyzer/relatedTests"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/relatedTests")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, Deserialize, Serialize)] @@ -509,12 +575,13 @@ pub struct TestInfo { pub runnable: Runnable, } -pub enum Ssr {} +pub enum SsrRequest {} -impl Request for Ssr { +impl Request for SsrRequest { type Params = SsrParams; type Result = lsp_types::WorkspaceEdit; - const METHOD: &'static str = "experimental/ssr"; + const METHOD: LspRequestMethods = LspRequestMethods::Custom(Cow::Borrowed("experimental/ssr")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, Deserialize, Serialize)] @@ -536,7 +603,9 @@ pub enum ServerStatusNotification {} impl Notification for ServerStatusNotification { type Params = ServerStatusParams; - const METHOD: &'static str = "experimental/serverStatus"; + const METHOD: LspNotificationMethods = + LspNotificationMethods::Custom(Cow::Borrowed("experimental/serverStatus")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Deserialize, Serialize, PartialEq, Eq, Clone)] @@ -570,7 +639,9 @@ pub enum CodeActionRequest {} impl Request for CodeActionRequest { type Params = lsp_types::CodeActionParams; type Result = Option>; - const METHOD: &'static str = "textDocument/codeAction"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("textDocument/codeAction")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } pub enum CodeActionResolveRequest {} @@ -578,7 +649,9 @@ pub enum CodeActionResolveRequest {} impl Request for CodeActionResolveRequest { type Params = CodeAction; type Result = CodeAction; - const METHOD: &'static str = "codeAction/resolve"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("codeAction/resolve")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] @@ -612,7 +685,7 @@ pub struct CodeActionData { #[serde(rename_all = "camelCase")] pub struct SnippetWorkspaceEdit { #[serde(skip_serializing_if = "Option::is_none")] - pub changes: Option>>, + pub changes: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub document_changes: Option>, #[serde(skip_serializing_if = "Option::is_none")] @@ -627,7 +700,7 @@ pub struct SnippetWorkspaceEdit { #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(untagged, rename_all = "lowercase")] pub enum SnippetDocumentChangeOperation { - Op(lsp_types::ResourceOp), + Change(lsp_types::DocumentChange), Edit(SnippetTextDocumentEdit), } @@ -655,7 +728,8 @@ pub enum HoverRequest {} impl Request for HoverRequest { type Params = HoverParams; type Result = Option; - const METHOD: &'static str = lsp_types::request::HoverRequest::METHOD; + const METHOD: LspRequestMethods = lsp_types::HoverRequest::METHOD; + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] @@ -699,18 +773,20 @@ pub struct CommandLink { pub tooltip: Option, } -pub enum ExternalDocs {} +pub enum ExternalDocsRequest {} -impl Request for ExternalDocs { +impl Request for ExternalDocsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = ExternalDocsResponse; - const METHOD: &'static str = "experimental/externalDocs"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/externalDocs")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[serde(untagged)] pub enum ExternalDocsResponse { - Simple(Option), + Simple(Option), WithLocal(ExternalDocsPair), } @@ -723,16 +799,18 @@ impl Default for ExternalDocsResponse { #[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct ExternalDocsPair { - pub web: Option, - pub local: Option, + pub web: Option, + pub local: Option, } -pub enum OpenCargoToml {} +pub enum OpenCargoTomlRequest {} -impl Request for OpenCargoToml { +impl Request for OpenCargoTomlRequest { type Params = OpenCargoTomlParams; - type Result = Option; - const METHOD: &'static str = "experimental/openCargoToml"; + type Result = Option; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/openCargoToml")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Serialize, Deserialize, Debug)] @@ -752,16 +830,18 @@ pub struct CodeLensResolveData { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum CodeLensResolveDataKind { - Impls(lsp_types::request::GotoImplementationParams), + Impls(lsp_types::ImplementationParams), References(lsp_types::TextDocumentPositionParams), } -pub enum MoveItem {} +pub enum MoveItemRequest {} -impl Request for MoveItem { +impl Request for MoveItemRequest { type Params = MoveItemParams; type Result = Vec; - const METHOD: &'static str = "experimental/moveItem"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("experimental/moveItem")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Serialize, Deserialize, Debug)] @@ -779,12 +859,13 @@ pub enum MoveItemDirection { } #[derive(Debug)] -pub enum WorkspaceSymbol {} +pub enum WorkspaceSymbolRequest {} -impl Request for WorkspaceSymbol { +impl Request for WorkspaceSymbolRequest { type Params = WorkspaceSymbolParams; - type Result = Option; - const METHOD: &'static str = "workspace/symbol"; + type Result = Option; + const METHOD: LspRequestMethods = LspRequestMethods::Custom(Cow::Borrowed("workspace/symbol")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] @@ -820,15 +901,17 @@ pub enum WorkspaceSymbolSearchKind { /// The document on type formatting request is sent from the client to /// the server to format parts of the document during typing. This is -/// almost same as lsp_types::request::OnTypeFormatting, but the +/// almost same as [`lsp_types::DocumentOnTypeFormattingRequest`], but the /// result has SnippetTextEdit in it instead of TextEdit. #[derive(Debug)] -pub enum OnTypeFormatting {} +pub enum DocumentOnTypeFormattingRequest {} -impl Request for OnTypeFormatting { +impl Request for DocumentOnTypeFormattingRequest { type Params = DocumentOnTypeFormattingParams; type Result = Option>; - const METHOD: &'static str = "textDocument/onTypeFormatting"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("textDocument/onTypeFormatting")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } #[derive(Debug, Serialize, Deserialize)] @@ -866,7 +949,7 @@ pub struct ClientCommandOptions { pub commands: Vec, } -pub enum GetFailedObligations {} +pub enum GetFailedObligationsRequest {} #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] @@ -875,8 +958,10 @@ pub struct GetFailedObligationsParams { pub position: Position, } -impl Request for GetFailedObligations { +impl Request for GetFailedObligationsRequest { type Params = GetFailedObligationsParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/getFailedObligations"; + const METHOD: LspRequestMethods = + LspRequestMethods::Custom(Cow::Borrowed("rust-analyzer/getFailedObligations")); + const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } diff --git a/crates/rust-analyzer/src/lsp/from_proto.rs b/crates/rust-analyzer/src/lsp/from_proto.rs index 333826a1790e..a744c97c5602 100644 --- a/crates/rust-analyzer/src/lsp/from_proto.rs +++ b/crates/rust-analyzer/src/lsp/from_proto.rs @@ -1,4 +1,6 @@ //! Conversion lsp_types types to rust-analyzer specific ones. +use std::str::FromStr; + use anyhow::format_err; use ide::{Annotation, AnnotationKind, AssistKind, LineCol}; use ide_db::{FileId, FilePosition, FileRange, line_index::WideLineCol}; @@ -12,18 +14,18 @@ use crate::{ lsp_ext, try_default, }; -pub(crate) fn abs_path(url: &lsp_types::Url) -> anyhow::Result { - let path = url.to_file_path().map_err(|()| anyhow::format_err!("url is not a file"))?; - Ok(AbsPathBuf::try_from(Utf8PathBuf::from_path_buf(path).unwrap()).unwrap()) +pub(crate) fn abs_path(url: &lsp_types::Uri) -> anyhow::Result { + let path = url.to_string(); + Ok(AbsPathBuf::try_from(Utf8PathBuf::from_str(&path).unwrap()).unwrap()) } -pub(crate) fn vfs_path(url: &lsp_types::Url) -> anyhow::Result { +pub(crate) fn vfs_path(url: &lsp_types::Uri) -> anyhow::Result { abs_path(url).map(vfs::VfsPath::from) } pub(crate) fn offset( line_index: &LineIndex, - position: lsp_types::Position, + position: &lsp_types::Position, ) -> anyhow::Result { let line_col = match line_index.encoding { PositionEncoding::Utf8 => LineCol { line: position.line, col: position.character }, @@ -54,8 +56,8 @@ pub(crate) fn text_range( line_index: &LineIndex, range: lsp_types::Range, ) -> anyhow::Result { - let start = offset(line_index, range.start)?; - let end = offset(line_index, range.end)?; + let start = offset(line_index, &range.start)?; + let end = offset(line_index, &range.end)?; match end < start { true => Err(format_err!("Invalid Range")), false => Ok(TextRange::new(start, end)), @@ -65,7 +67,7 @@ pub(crate) fn text_range( /// Returns `None` if the file was excluded. pub(crate) fn file_id( snap: &GlobalStateSnapshot, - url: &lsp_types::Url, + url: &lsp_types::Uri, ) -> anyhow::Result> { snap.url_to_file_id(url) } @@ -73,11 +75,11 @@ pub(crate) fn file_id( /// Returns `None` if the file was excluded. pub(crate) fn file_position( snap: &GlobalStateSnapshot, - tdpp: lsp_types::TextDocumentPositionParams, + tdpp: &lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { let file_id = try_default!(file_id(snap, &tdpp.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; - let offset = offset(&line_index, tdpp.position)?; + let offset = offset(&line_index, &tdpp.position)?; Ok(Some(FilePosition { file_id, offset })) } @@ -93,7 +95,7 @@ pub(crate) fn file_range( /// Returns `None` if the file was excluded. pub(crate) fn file_range_uri( snap: &GlobalStateSnapshot, - document: &lsp_types::Url, + document: &lsp_types::Uri, range: lsp_types::Range, ) -> anyhow::Result> { let file_id = try_default!(file_id(snap, document)?); @@ -104,12 +106,12 @@ pub(crate) fn file_range_uri( pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option { let assist_kind = match &kind { - k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::Generate, - k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix, - k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor, - k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract, - k if k == &lsp_types::CodeActionKind::REFACTOR_INLINE => AssistKind::RefactorInline, - k if k == &lsp_types::CodeActionKind::REFACTOR_REWRITE => AssistKind::RefactorRewrite, + k if k == &lsp_types::CodeActionKind::Empty => AssistKind::Generate, + k if k == &lsp_types::CodeActionKind::QuickFix => AssistKind::QuickFix, + k if k == &lsp_types::CodeActionKind::Refactor => AssistKind::Refactor, + k if k == &lsp_types::CodeActionKind::RefactorExtract => AssistKind::RefactorExtract, + k if k == &lsp_types::CodeActionKind::RefactorInline => AssistKind::RefactorInline, + k if k == &lsp_types::CodeActionKind::RefactorRewrite => AssistKind::RefactorRewrite, _ => return None, }; @@ -130,7 +132,7 @@ pub(crate) fn annotation( return Ok(None); } let pos @ FilePosition { file_id, .. } = - try_default!(file_position(snap, params.text_document_position_params)?); + try_default!(file_position(snap, ¶ms.text_document_position_params)?); let line_index = snap.file_line_index(file_id)?; Ok(Annotation { @@ -142,7 +144,7 @@ pub(crate) fn annotation( if snap.url_file_version(¶ms.text_document.uri) != Some(data.version) { return Ok(None); } - let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, params)?); + let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, ¶ms)?); let line_index = snap.file_line_index(file_id)?; Ok(Annotation { diff --git a/crates/rust-analyzer/src/lsp/semantic_tokens.rs b/crates/rust-analyzer/src/lsp/semantic_tokens.rs index 9bfdea8a1683..e93ccb63aa74 100644 --- a/crates/rust-analyzer/src/lsp/semantic_tokens.rs +++ b/crates/rust-analyzer/src/lsp/semantic_tokens.rs @@ -1,170 +1,245 @@ //! Semantic Tokens helpers -use std::ops; - -use lsp_types::{ - Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, - SemanticTokensEdit, -}; - -macro_rules! define_semantic_token_types { - ( - standard { - $($standard:ident),*$(,)? - } - custom { - $(($custom:ident, $string:literal) $(=> $fallback:ident)?),*$(,)? - } - - ) => { - pub(crate) mod types { - use super::SemanticTokenType; - $(pub(crate) const $standard: SemanticTokenType = SemanticTokenType::$standard;)* - $(pub(crate) const $custom: SemanticTokenType = SemanticTokenType::new($string);)* - } - - pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[ - $(self::types::$standard,)* - $(self::types::$custom),* - ]; +use std::{fmt, ops}; + +use lsp_types::{Range, SemanticTokenModifiers, SemanticTokens, SemanticTokensEdit}; + +use strum::IntoEnumIterator; +use strum_macros::EnumIter; + +#[repr(u32)] +#[derive(EnumIter, Debug, PartialEq, Clone, Copy)] +pub(crate) enum SupportedType { + Comment, + Decorator, + EnumMember, + Enum, + Function, + Interface, + Keyword, + Macro, + Method, + Namespace, + Number, + Operator, + Parameter, + Property, + String, + Struct, + TypeParameter, + Variable, + Type, + Label, + Angle, + Arithmetic, + AttributeBracket, + Attribute, + Bitwise, + Boolean, + Brace, + Bracket, + BuiltinAttribute, + BuiltinType, + Char, + Colon, + Comma, + Comparison, + ConstParameter, + Const, + DeriveHelper, + Derive, + Dot, + EscapeSequence, + FormatSpecifier, + Generic, + InvalidEscapeSequence, + Lifetime, + Logical, + MacroBang, + Negation, + Parenthesis, + ProcMacro, + Punctuation, + SelfKeyword, + SelfTypeKeyword, + Semicolon, + Static, + ToolModule, + TypeAlias, + Union, + UnresolvedReference, +} - pub(crate) fn standard_fallback_type(token: SemanticTokenType) -> Option { - use self::types::*; - $( - if token == $custom { - None $(.or(Some(self::types::$fallback)))? - } else - )* - { Some(token )} +impl From<&SupportedType> for String { + fn from(e: &SupportedType) -> Self { + match *e { + SupportedType::Comment => ::lsp_types::SemanticTokenTypes::Comment.into(), + SupportedType::Decorator => ::lsp_types::SemanticTokenTypes::Decorator.into(), + SupportedType::EnumMember => ::lsp_types::SemanticTokenTypes::EnumMember.into(), + SupportedType::Enum => ::lsp_types::SemanticTokenTypes::Enum.into(), + SupportedType::Function => ::lsp_types::SemanticTokenTypes::Function.into(), + SupportedType::Interface => ::lsp_types::SemanticTokenTypes::Interface.into(), + SupportedType::Keyword => ::lsp_types::SemanticTokenTypes::Keyword.into(), + SupportedType::Macro => ::lsp_types::SemanticTokenTypes::Macro.into(), + SupportedType::Method => ::lsp_types::SemanticTokenTypes::Method.into(), + SupportedType::Namespace => ::lsp_types::SemanticTokenTypes::Namespace.into(), + SupportedType::Number => ::lsp_types::SemanticTokenTypes::Number.into(), + SupportedType::Operator => ::lsp_types::SemanticTokenTypes::Operator.into(), + SupportedType::Parameter => ::lsp_types::SemanticTokenTypes::Parameter.into(), + SupportedType::Property => ::lsp_types::SemanticTokenTypes::Property.into(), + SupportedType::String => ::lsp_types::SemanticTokenTypes::String.into(), + SupportedType::Struct => ::lsp_types::SemanticTokenTypes::Struct.into(), + SupportedType::TypeParameter => ::lsp_types::SemanticTokenTypes::TypeParameter.into(), + SupportedType::Variable => ::lsp_types::SemanticTokenTypes::Variable.into(), + SupportedType::Type => ::lsp_types::SemanticTokenTypes::Type.into(), + SupportedType::Label => ::lsp_types::SemanticTokenTypes::Label.into(), + SupportedType::Angle => "angle".to_owned(), + SupportedType::Arithmetic => "arithmetic".to_owned(), + SupportedType::AttributeBracket => "attributeBracket".to_owned(), + SupportedType::Attribute => "attribute".to_owned(), + SupportedType::Bitwise => "bitwise".to_owned(), + SupportedType::Boolean => "boolean".to_owned(), + SupportedType::Brace => "brace".to_owned(), + SupportedType::Bracket => "bracket".to_owned(), + SupportedType::BuiltinAttribute => "builtinAttribute".to_owned(), + SupportedType::BuiltinType => "builtinType".to_owned(), + SupportedType::Char => "character".to_owned(), + SupportedType::Colon => "colon".to_owned(), + SupportedType::Comma => "comma".to_owned(), + SupportedType::Comparison => "comparison".to_owned(), + SupportedType::ConstParameter => "constParameter".to_owned(), + SupportedType::Const => "const".to_owned(), + SupportedType::DeriveHelper => "deriveHelper".to_owned(), + SupportedType::Derive => "derive".to_owned(), + SupportedType::Dot => "dot".to_owned(), + SupportedType::EscapeSequence => "escapeSequence".to_owned(), + SupportedType::FormatSpecifier => "formatSpecifier".to_owned(), + SupportedType::Generic => "generic".to_owned(), + SupportedType::InvalidEscapeSequence => "invalidEscapeSequence".to_owned(), + SupportedType::Lifetime => "lifetime".to_owned(), + SupportedType::Logical => "logical".to_owned(), + SupportedType::MacroBang => "macroBang".to_owned(), + SupportedType::Negation => "negation".to_owned(), + SupportedType::Parenthesis => "parenthesis".to_owned(), + SupportedType::ProcMacro => "procMacro".to_owned(), + SupportedType::Punctuation => "punctuation".to_owned(), + SupportedType::SelfKeyword => "selfKeyword".to_owned(), + SupportedType::SelfTypeKeyword => "selfTypeKeyword".to_owned(), + SupportedType::Semicolon => "semicolon".to_owned(), + SupportedType::Static => "static".to_owned(), + SupportedType::ToolModule => "toolModule".to_owned(), + SupportedType::TypeAlias => "typeAlias".to_owned(), + SupportedType::Union => "union".to_owned(), + SupportedType::UnresolvedReference => "unresolvedReference".to_owned(), } - }; + } } -define_semantic_token_types![ - standard { - COMMENT, - DECORATOR, - ENUM_MEMBER, - ENUM, - FUNCTION, - INTERFACE, - KEYWORD, - MACRO, - METHOD, - NAMESPACE, - NUMBER, - OPERATOR, - PARAMETER, - PROPERTY, - STRING, - STRUCT, - TYPE_PARAMETER, - VARIABLE, - TYPE, +impl fmt::Display for SupportedType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let string: String = self.into(); + write!(f, "{string}") } +} - custom { - (ANGLE, "angle"), - (ARITHMETIC, "arithmetic") => OPERATOR, - (ATTRIBUTE_BRACKET, "attributeBracket") => DECORATOR, - (ATTRIBUTE, "attribute") => DECORATOR, - (BITWISE, "bitwise") => OPERATOR, - (BOOLEAN, "boolean"), - (BRACE, "brace"), - (BRACKET, "bracket"), - (BUILTIN_ATTRIBUTE, "builtinAttribute") => DECORATOR, - (BUILTIN_TYPE, "builtinType") => TYPE, - (CHAR, "character") => STRING, - (COLON, "colon"), - (COMMA, "comma"), - (COMPARISON, "comparison") => OPERATOR, - (CONST_PARAMETER, "constParameter"), - (CONST, "const") => VARIABLE, - (DERIVE_HELPER, "deriveHelper") => DECORATOR, - (DERIVE, "derive") => DECORATOR, - (DOT, "dot"), - (ESCAPE_SEQUENCE, "escapeSequence") => STRING, - (FORMAT_SPECIFIER, "formatSpecifier") => STRING, - (GENERIC, "generic") => TYPE_PARAMETER, - (INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING, - (LABEL, "label"), - (LIFETIME, "lifetime"), - (LOGICAL, "logical") => OPERATOR, - (MACRO_BANG, "macroBang") => MACRO, - (NEGATION, "negation") => OPERATOR, - (PARENTHESIS, "parenthesis"), - (PROC_MACRO, "procMacro") => MACRO, - (PUNCTUATION, "punctuation"), - (SELF_KEYWORD, "selfKeyword") => KEYWORD, - (SELF_TYPE_KEYWORD, "selfTypeKeyword") => KEYWORD, - (SEMICOLON, "semicolon"), - (STATIC, "static") => VARIABLE, - (TOOL_MODULE, "toolModule") => DECORATOR, - (TYPE_ALIAS, "typeAlias") => TYPE, - (UNION, "union") => TYPE, - (UNRESOLVED_REFERENCE, "unresolvedReference"), - } -]; +pub(crate) fn standard_fallback_type(token: SupportedType) -> Option { + Some(match token { + SupportedType::Comment => SupportedType::Comment, + SupportedType::Decorator => SupportedType::Decorator, + SupportedType::EnumMember => SupportedType::EnumMember, + SupportedType::Enum => SupportedType::Enum, + SupportedType::Function => SupportedType::Function, + SupportedType::Interface => SupportedType::Interface, + SupportedType::Keyword => SupportedType::Keyword, + SupportedType::Macro => SupportedType::Macro, + SupportedType::Method => SupportedType::Method, + SupportedType::Namespace => SupportedType::Namespace, + SupportedType::Number => SupportedType::Number, + SupportedType::Operator => SupportedType::Operator, + SupportedType::Parameter => SupportedType::Parameter, + SupportedType::Property => SupportedType::Property, + SupportedType::String => SupportedType::String, + SupportedType::Struct => SupportedType::Struct, + SupportedType::TypeParameter => SupportedType::TypeParameter, + SupportedType::Variable => SupportedType::Variable, + SupportedType::Type => SupportedType::Type, + SupportedType::Label => SupportedType::Label, + _ => return None, + }) +} macro_rules! count_tts { () => {0usize}; ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)}; } -macro_rules! define_semantic_token_modifiers { - ( - standard { - $($standard:ident),*$(,)? - } - custom { - $(($custom:ident, $string:literal)),*$(,)? - } - ) => { - pub(crate) mod modifiers { - use super::SemanticTokenModifier; +#[repr(u32)] +#[derive(EnumIter, Debug, PartialEq, Clone, Copy)] +pub(crate) enum SupportedModifiers { + Async, + Documentation, + Declaration, + Static, + DefaultLibrary, + Deprecated, + Associated, + AttributeModifier, + Callable, + Constant, + Consuming, + ControlFlow, + CrateRoot, + Injected, + IntraDocLink, + Library, + MacroModifier, + Mutable, + ProcMacroModifier, + Public, + Reference, + TraitModifier, + Unsafe, +} - $(pub(crate) const $standard: SemanticTokenModifier = SemanticTokenModifier::$standard;)* - $(pub(crate) const $custom: SemanticTokenModifier = SemanticTokenModifier::new($string);)* +impl From<&SupportedModifiers> for String { + fn from(e: &SupportedModifiers) -> Self { + match *e { + SupportedModifiers::Async => SemanticTokenModifiers::Async.into(), + SupportedModifiers::Documentation => SemanticTokenModifiers::Documentation.into(), + SupportedModifiers::Declaration => SemanticTokenModifiers::Declaration.into(), + SupportedModifiers::Static => SemanticTokenModifiers::Static.into(), + SupportedModifiers::DefaultLibrary => SemanticTokenModifiers::DefaultLibrary.into(), + SupportedModifiers::Deprecated => SemanticTokenModifiers::Deprecated.into(), + SupportedModifiers::Associated => "associated".to_owned(), + SupportedModifiers::AttributeModifier => "attribute".to_owned(), + SupportedModifiers::Callable => "callable".to_owned(), + SupportedModifiers::Constant => "constant".to_owned(), + SupportedModifiers::Consuming => "consuming".to_owned(), + SupportedModifiers::ControlFlow => "controlFlow".to_owned(), + SupportedModifiers::CrateRoot => "crateRoot".to_owned(), + SupportedModifiers::Injected => "injected".to_owned(), + SupportedModifiers::IntraDocLink => "intraDocLink".to_owned(), + SupportedModifiers::Library => "library".to_owned(), + SupportedModifiers::MacroModifier => "macro".to_owned(), + SupportedModifiers::Mutable => "mutable".to_owned(), + SupportedModifiers::ProcMacroModifier => "procMacro".to_owned(), + SupportedModifiers::Public => "public".to_owned(), + SupportedModifiers::Reference => "reference".to_owned(), + SupportedModifiers::TraitModifier => "trait".to_owned(), + SupportedModifiers::Unsafe => "unsafe".to_owned(), } - - pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ - $(SemanticTokenModifier::$standard,)* - $(self::modifiers::$custom),* - ]; - - const LAST_STANDARD_MOD: usize = count_tts!($($standard)*); - }; + } } -define_semantic_token_modifiers![ - standard { - ASYNC, - DOCUMENTATION, - DECLARATION, - STATIC, - DEFAULT_LIBRARY, - DEPRECATED, - } - custom { - (ASSOCIATED, "associated"), - (ATTRIBUTE_MODIFIER, "attribute"), - (CALLABLE, "callable"), - (CONSTANT, "constant"), - (CONSUMING, "consuming"), - (CONTROL_FLOW, "controlFlow"), - (CRATE_ROOT, "crateRoot"), - (INJECTED, "injected"), - (INTRA_DOC_LINK, "intraDocLink"), - (LIBRARY, "library"), - (MACRO_MODIFIER, "macro"), - (MUTABLE, "mutable"), - (PROC_MACRO_MODIFIER, "procMacro"), - (PUBLIC, "public"), - (REFERENCE, "reference"), - (TRAIT_MODIFIER, "trait"), - (UNSAFE, "unsafe"), +impl fmt::Display for SupportedModifiers { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let string: String = self.into(); + write!(f, "{string}") } -]; +} + +const LAST_STANDARD_MOD: usize = + count_tts!(ASYNC DOCUMENTATION Declaration Static DefaultLibrary Deprecated); #[derive(Default)] pub(crate) struct ModifierSet(pub(crate) u32); @@ -176,9 +251,9 @@ impl ModifierSet { } } -impl ops::BitOrAssign for ModifierSet { - fn bitor_assign(&mut self, rhs: SemanticTokenModifier) { - let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap(); +impl ops::BitOrAssign for ModifierSet { + fn bitor_assign(&mut self, rhs: SupportedModifiers) { + let idx = SupportedModifiers::iter().position(|it| it == rhs).unwrap(); self.0 |= 1 << idx; } } @@ -190,12 +265,12 @@ pub(crate) struct SemanticTokensBuilder { id: String, prev_line: u32, prev_char: u32, - data: Vec, + data: Vec, } impl SemanticTokensBuilder { pub(crate) fn new(id: String) -> Self { - SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() } + SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Vec::new() } } /// Push a new token onto the builder @@ -213,7 +288,7 @@ impl SemanticTokensBuilder { // A token cannot be multiline let token_len = range.end.character - range.start.character; - let token = SemanticToken { + let token = lsp_types::SemanticToken { delta_line: push_line, delta_start: push_char, length: token_len, @@ -232,7 +307,10 @@ impl SemanticTokensBuilder { } } -pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec { +pub(crate) fn diff_tokens( + old: &[lsp_types::SemanticToken], + new: &[lsp_types::SemanticToken], +) -> Vec { let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count(); let (_, old) = old.split_at(offset); @@ -258,16 +336,16 @@ pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec u32 { - SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32 +pub(crate) fn type_index(kind: SupportedType) -> u32 { + kind as u32 } #[cfg(test)] mod tests { use super::*; - fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken { - SemanticToken { + fn from(t: (u32, u32, u32, u32, u32)) -> lsp_types::SemanticToken { + lsp_types::SemanticToken { delta_line: t.0, delta_start: t.1, length: t.2, diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index d59e9d8434c7..228232d00a3a 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -58,43 +58,43 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { match symbol_kind { - SymbolKind::Function => lsp_types::SymbolKind::FUNCTION, - SymbolKind::Method => lsp_types::SymbolKind::METHOD, - SymbolKind::Struct => lsp_types::SymbolKind::STRUCT, - SymbolKind::Enum => lsp_types::SymbolKind::ENUM, - SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER, - SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE, + SymbolKind::Function => lsp_types::SymbolKind::Function, + SymbolKind::Method => lsp_types::SymbolKind::Method, + SymbolKind::Struct => lsp_types::SymbolKind::Struct, + SymbolKind::Enum => lsp_types::SymbolKind::Enum, + SymbolKind::Variant => lsp_types::SymbolKind::EnumMember, + SymbolKind::Trait => lsp_types::SymbolKind::Interface, SymbolKind::Macro | SymbolKind::ProcMacro | SymbolKind::BuiltinAttr | SymbolKind::Attribute | SymbolKind::Derive - | SymbolKind::DeriveHelper => lsp_types::SymbolKind::FUNCTION, - SymbolKind::CrateRoot => lsp_types::SymbolKind::PACKAGE, - SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::MODULE, + | SymbolKind::DeriveHelper => lsp_types::SymbolKind::Function, + SymbolKind::CrateRoot => lsp_types::SymbolKind::Package, + SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::Module, SymbolKind::TypeAlias | SymbolKind::TypeParam | SymbolKind::SelfType => { - lsp_types::SymbolKind::TYPE_PARAMETER + lsp_types::SymbolKind::TypeParameter } - SymbolKind::Field => lsp_types::SymbolKind::FIELD, - SymbolKind::Static => lsp_types::SymbolKind::CONSTANT, - SymbolKind::Const => lsp_types::SymbolKind::CONSTANT, - SymbolKind::ConstParam => lsp_types::SymbolKind::CONSTANT, - SymbolKind::Impl => lsp_types::SymbolKind::OBJECT, + SymbolKind::Field => lsp_types::SymbolKind::Field, + SymbolKind::Static => lsp_types::SymbolKind::Constant, + SymbolKind::Const => lsp_types::SymbolKind::Constant, + SymbolKind::ConstParam => lsp_types::SymbolKind::Constant, + SymbolKind::Impl => lsp_types::SymbolKind::Object, SymbolKind::Local | SymbolKind::SelfParam | SymbolKind::LifetimeParam | SymbolKind::ValueParam - | SymbolKind::Label => lsp_types::SymbolKind::VARIABLE, - SymbolKind::Union => lsp_types::SymbolKind::STRUCT, - SymbolKind::InlineAsmRegOrRegClass => lsp_types::SymbolKind::VARIABLE, + | SymbolKind::Label => lsp_types::SymbolKind::Variable, + SymbolKind::Union => lsp_types::SymbolKind::Struct, + SymbolKind::InlineAsmRegOrRegClass => lsp_types::SymbolKind::Variable, } } pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolKind { match kind { StructureNodeKind::SymbolKind(symbol) => symbol_kind(symbol), - StructureNodeKind::Region => lsp_types::SymbolKind::NAMESPACE, - StructureNodeKind::ExternBlock => lsp_types::SymbolKind::NAMESPACE, + StructureNodeKind::Region => lsp_types::SymbolKind::Namespace, + StructureNodeKind::ExternBlock => lsp_types::SymbolKind::Namespace, } } @@ -102,21 +102,21 @@ pub(crate) fn document_highlight_kind( category: ReferenceCategory, ) -> Option { if category.contains(ReferenceCategory::WRITE) { - return Some(lsp_types::DocumentHighlightKind::WRITE); + return Some(lsp_types::DocumentHighlightKind::Write); } if category.contains(ReferenceCategory::READ) { - return Some(lsp_types::DocumentHighlightKind::READ); + return Some(lsp_types::DocumentHighlightKind::Read); } None } pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity { match severity { - Severity::Error => lsp_types::DiagnosticSeverity::ERROR, - Severity::Warning => lsp_types::DiagnosticSeverity::WARNING, - Severity::WeakWarning => lsp_types::DiagnosticSeverity::HINT, + Severity::Error => lsp_types::DiagnosticSeverity::Error, + Severity::Warning => lsp_types::DiagnosticSeverity::Warning, + Severity::WeakWarning => lsp_types::DiagnosticSeverity::Hint, // unreachable - Severity::Allow => lsp_types::DiagnosticSeverity::INFORMATION, + Severity::Allow => lsp_types::DiagnosticSeverity::Information, } } @@ -130,44 +130,44 @@ pub(crate) fn completion_item_kind( completion_item_kind: CompletionItemKind, ) -> lsp_types::CompletionItemKind { match completion_item_kind { - CompletionItemKind::Binding => lsp_types::CompletionItemKind::VARIABLE, - CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::STRUCT, - CompletionItemKind::InferredType => lsp_types::CompletionItemKind::SNIPPET, - CompletionItemKind::Keyword => lsp_types::CompletionItemKind::KEYWORD, - CompletionItemKind::Snippet => lsp_types::CompletionItemKind::SNIPPET, - CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::REFERENCE, - CompletionItemKind::Expression => lsp_types::CompletionItemKind::SNIPPET, + CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable, + CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct, + CompletionItemKind::InferredType => lsp_types::CompletionItemKind::Snippet, + CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword, + CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet, + CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::Reference, + CompletionItemKind::Expression => lsp_types::CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(symbol) => match symbol { - SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::Method => lsp_types::CompletionItemKind::METHOD, - SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT, - SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, - SymbolKind::CrateRoot => lsp_types::CompletionItemKind::MODULE, - SymbolKind::Derive => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::DeriveHelper => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM, - SymbolKind::Field => lsp_types::CompletionItemKind::FIELD, - SymbolKind::Function => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::Impl => lsp_types::CompletionItemKind::TEXT, - SymbolKind::Label => lsp_types::CompletionItemKind::VARIABLE, - SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, - SymbolKind::Local => lsp_types::CompletionItemKind::VARIABLE, - SymbolKind::Macro => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::ProcMacro => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::Module => lsp_types::CompletionItemKind::MODULE, - SymbolKind::SelfParam => lsp_types::CompletionItemKind::VALUE, - SymbolKind::SelfType => lsp_types::CompletionItemKind::TYPE_PARAMETER, - SymbolKind::Static => lsp_types::CompletionItemKind::VALUE, - SymbolKind::Struct => lsp_types::CompletionItemKind::STRUCT, - SymbolKind::Trait => lsp_types::CompletionItemKind::INTERFACE, - SymbolKind::TypeAlias => lsp_types::CompletionItemKind::STRUCT, - SymbolKind::TypeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, - SymbolKind::Union => lsp_types::CompletionItemKind::STRUCT, - SymbolKind::ValueParam => lsp_types::CompletionItemKind::VALUE, - SymbolKind::Variant => lsp_types::CompletionItemKind::ENUM_MEMBER, - SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::FUNCTION, - SymbolKind::ToolModule => lsp_types::CompletionItemKind::MODULE, - SymbolKind::InlineAsmRegOrRegClass => lsp_types::CompletionItemKind::KEYWORD, + SymbolKind::Attribute => lsp_types::CompletionItemKind::Function, + SymbolKind::Method => lsp_types::CompletionItemKind::Method, + SymbolKind::Const => lsp_types::CompletionItemKind::Constant, + SymbolKind::ConstParam => lsp_types::CompletionItemKind::TypeParameter, + SymbolKind::CrateRoot => lsp_types::CompletionItemKind::Module, + SymbolKind::Derive => lsp_types::CompletionItemKind::Function, + SymbolKind::DeriveHelper => lsp_types::CompletionItemKind::Function, + SymbolKind::Enum => lsp_types::CompletionItemKind::Enum, + SymbolKind::Field => lsp_types::CompletionItemKind::Field, + SymbolKind::Function => lsp_types::CompletionItemKind::Function, + SymbolKind::Impl => lsp_types::CompletionItemKind::Text, + SymbolKind::Label => lsp_types::CompletionItemKind::Variable, + SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TypeParameter, + SymbolKind::Local => lsp_types::CompletionItemKind::Variable, + SymbolKind::Macro => lsp_types::CompletionItemKind::Function, + SymbolKind::ProcMacro => lsp_types::CompletionItemKind::Function, + SymbolKind::Module => lsp_types::CompletionItemKind::Module, + SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value, + SymbolKind::SelfType => lsp_types::CompletionItemKind::TypeParameter, + SymbolKind::Static => lsp_types::CompletionItemKind::Value, + SymbolKind::Struct => lsp_types::CompletionItemKind::Struct, + SymbolKind::Trait => lsp_types::CompletionItemKind::Interface, + SymbolKind::TypeAlias => lsp_types::CompletionItemKind::Struct, + SymbolKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter, + SymbolKind::Union => lsp_types::CompletionItemKind::Struct, + SymbolKind::ValueParam => lsp_types::CompletionItemKind::Value, + SymbolKind::Variant => lsp_types::CompletionItemKind::EnumMember, + SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::Function, + SymbolKind::ToolModule => lsp_types::CompletionItemKind::Module, + SymbolKind::InlineAsmRegOrRegClass => lsp_types::CompletionItemKind::Keyword, }, } } @@ -185,7 +185,7 @@ pub(crate) fn completion_text_edit( line_index: &LineIndex, insert_replace_support: Option, indel: Indel, -) -> lsp_types::CompletionTextEdit { +) -> lsp_types::CompletionItemTextEdit { let text_edit = text_edit(line_index, indel); match insert_replace_support { Some(cursor_pos) => lsp_types::InsertReplaceEdit { @@ -208,7 +208,7 @@ pub(crate) fn snippet_text_edit( let annotation_id = annotation.filter(|_| client_supports_annotations).map(|it| it.to_string()); let text_edit = text_edit(line_index, indel); let insert_text_format = - if is_snippet { Some(lsp_types::InsertTextFormat::SNIPPET) } else { None }; + if is_snippet { Some(lsp_types::InsertTextFormat::Snippet) } else { None }; lsp_ext::SnippetTextEdit { range: text_edit.range, new_text: text_edit.new_text, @@ -250,7 +250,7 @@ pub(crate) fn completion_items( fields_to_resolve: &CompletionFieldsToResolve, line_index: &LineIndex, version: Option, - tdpp: lsp_types::TextDocumentPositionParams, + tdpp: &lsp_types::TextDocumentPositionParams, completion_trigger_character: Option, mut items: Vec, ) -> Vec { @@ -269,7 +269,7 @@ pub(crate) fn completion_items( fields_to_resolve, line_index, version, - &tdpp, + tdpp, max_relevance, completion_trigger_character, item, @@ -340,12 +340,12 @@ fn completion_item( Some(text_edit.unwrap()) }; - let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::SNIPPET); + let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::Snippet); let tags = if fields_to_resolve.resolve_tags { something_to_resolve |= item.deprecated; None } else { - item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]) + item.deprecated.then(|| vec![lsp_types::CompletionItemTag::Deprecated]) }; let command = if item.trigger_call_info && client_commands.trigger_parameter_hints { if fields_to_resolve.resolve_command { @@ -383,6 +383,7 @@ fn completion_item( .not() .then_some(additional_text_edits), documentation, + #[expect(deprecated, reason = "we do use tags")] deprecated: item.deprecated.then_some(item.deprecated), tags, command, @@ -491,7 +492,7 @@ pub(crate) fn signature_help( let params = call_info .parameter_labels() .map(|label| lsp_types::ParameterInformation { - label: lsp_types::ParameterLabel::Simple(label.to_owned()), + label: lsp_types::ParameterInformationLabel::String(label.to_owned()), documentation: None, }) .collect::>(); @@ -513,10 +514,10 @@ pub(crate) fn signature_help( .chars() .map(|c| c.len_utf16()) .sum::() as u32; - [start, end] + (start, end) }) .map(|label_offsets| lsp_types::ParameterInformation { - label: lsp_types::ParameterLabel::LabelOffsets(label_offsets), + label: lsp_types::ParameterInformationLabel::Tuple(label_offsets), documentation: None, }) .collect::>(); @@ -535,7 +536,7 @@ pub(crate) fn signature_help( label.push_str(param); let end = label.len() as u32; params.push(lsp_types::ParameterInformation { - label: lsp_types::ParameterLabel::LabelOffsets([start, end]), + label: lsp_types::ParameterInformationLabel::Tuple((start, end)), documentation: None, }); } @@ -551,7 +552,8 @@ pub(crate) fn signature_help( }) }); - let active_parameter = call_info.active_parameter.map(|it| it as u32); + let active_parameter = + call_info.active_parameter.map(|it| lsp_types::ActiveParameter::Int(it as u32)); let signature = lsp_types::SignatureInformation { label, @@ -639,9 +641,9 @@ pub(crate) fn inlay_hint( padding_right: Some(inlay_hint.pad_right), kind: match inlay_hint.kind { InlayKind::Parameter | InlayKind::GenericParameter => { - Some(lsp_types::InlayHintKind::PARAMETER) + Some(lsp_types::InlayHintKind::Parameter) } - InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE), + InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::Type), _ => None, }, text_edits, @@ -657,7 +659,7 @@ fn inlay_hint_label( something_to_resolve: &mut bool, needs_resolve: bool, mut label: InlayHintLabel, -) -> Cancellable<(lsp_types::InlayHintLabel, Option)> { +) -> Cancellable<(lsp_types::Label, Option)> { let (label, tooltip) = match &*label.parts { [InlayHintLabelPart { linked_location: None, .. }] => { let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap(); @@ -670,16 +672,16 @@ fn inlay_hint_label( } }); let hint_tooltip = match tooltip { - Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)), + Some(ide::InlayTooltip::String(s)) => Some(lsp_types::Tooltip::String(s)), Some(ide::InlayTooltip::Markdown(s)) => { - Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent { + Some(lsp_types::Tooltip::MarkupContent(lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value: s, })) } None => None, }; - (lsp_types::InlayHintLabel::String(text), hint_tooltip) + (lsp_types::Label::String(text), hint_tooltip) } _ => { let parts = label @@ -694,16 +696,12 @@ fn inlay_hint_label( } }); let tooltip = match tooltip { - Some(ide::InlayTooltip::String(s)) => { - Some(lsp_types::InlayHintLabelPartTooltip::String(s)) - } + Some(ide::InlayTooltip::String(s)) => Some(lsp_types::Tooltip::String(s)), Some(ide::InlayTooltip::Markdown(s)) => { - Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent( - lsp_types::MarkupContent { - kind: lsp_types::MarkupKind::Markdown, - value: s, - }, - )) + Some(lsp_types::Tooltip::MarkupContent(lsp_types::MarkupContent { + kind: lsp_types::MarkupKind::Markdown, + value: s, + })) } None => None, }; @@ -726,7 +724,7 @@ fn inlay_hint_label( }) }) .collect::>()?; - (lsp_types::InlayHintLabel::LabelParts(parts), None) + (lsp_types::Label::InlayHintLabelPartList(parts), None) } }; Ok((label, tooltip)) @@ -773,11 +771,11 @@ pub(crate) fn semantic_tokens( if !non_standard_tokens { ty = match standard_fallback_type(ty) { - Some(ty) => ty, + Some(fallback) => fallback, None => continue, }; mods.standard_fallback(); - } + }; let token_index = semantic_tokens::type_index(ty); let modifier_bitset = mods.0; @@ -805,106 +803,106 @@ pub(crate) fn semantic_token_delta( fn semantic_token_type_and_modifiers( highlight: Highlight, -) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { - use semantic_tokens::{modifiers as mods, types}; +) -> (semantic_tokens::SupportedType, semantic_tokens::ModifierSet) { + use semantic_tokens::{SupportedModifiers, SupportedType}; let mut mods = semantic_tokens::ModifierSet::default(); let ty = match highlight.tag { HlTag::Symbol(symbol) => match symbol { - SymbolKind::Attribute => types::DECORATOR, - SymbolKind::Derive => types::DERIVE, - SymbolKind::DeriveHelper => types::DERIVE_HELPER, + SymbolKind::Attribute => SupportedType::Decorator, + SymbolKind::Derive => SupportedType::Derive, + SymbolKind::DeriveHelper => SupportedType::DeriveHelper, SymbolKind::CrateRoot => { - mods |= mods::CRATE_ROOT; - types::NAMESPACE + mods |= SupportedModifiers::CrateRoot; + SupportedType::Namespace } - SymbolKind::Module => types::NAMESPACE, - SymbolKind::Impl => types::TYPE_ALIAS, - SymbolKind::Field => types::PROPERTY, - SymbolKind::TypeParam => types::TYPE_PARAMETER, - SymbolKind::ConstParam => types::CONST_PARAMETER, - SymbolKind::LifetimeParam => types::LIFETIME, - SymbolKind::Label => types::LABEL, - SymbolKind::ValueParam => types::PARAMETER, - SymbolKind::SelfParam => types::SELF_KEYWORD, - SymbolKind::SelfType => types::SELF_TYPE_KEYWORD, - SymbolKind::Local => types::VARIABLE, - SymbolKind::Method => types::METHOD, - SymbolKind::Function => types::FUNCTION, - SymbolKind::Const => types::CONST, - SymbolKind::Static => types::STATIC, - SymbolKind::Struct => types::STRUCT, - SymbolKind::Enum => types::ENUM, - SymbolKind::Variant => types::ENUM_MEMBER, - SymbolKind::Union => types::UNION, - SymbolKind::TypeAlias => types::TYPE_ALIAS, - SymbolKind::Trait => types::INTERFACE, - SymbolKind::Macro => types::MACRO, - SymbolKind::ProcMacro => types::PROC_MACRO, - SymbolKind::BuiltinAttr => types::BUILTIN_ATTRIBUTE, - SymbolKind::ToolModule => types::TOOL_MODULE, - SymbolKind::InlineAsmRegOrRegClass => types::KEYWORD, + SymbolKind::Module => SupportedType::Namespace, + SymbolKind::Impl => SupportedType::TypeAlias, + SymbolKind::Field => SupportedType::Property, + SymbolKind::TypeParam => SupportedType::TypeParameter, + SymbolKind::ConstParam => SupportedType::ConstParameter, + SymbolKind::LifetimeParam => SupportedType::Lifetime, + SymbolKind::Label => SupportedType::Label, + SymbolKind::ValueParam => SupportedType::Parameter, + SymbolKind::SelfParam => SupportedType::SelfKeyword, + SymbolKind::SelfType => SupportedType::SelfTypeKeyword, + SymbolKind::Local => SupportedType::Variable, + SymbolKind::Method => SupportedType::Method, + SymbolKind::Function => SupportedType::Function, + SymbolKind::Const => SupportedType::Const, + SymbolKind::Static => SupportedType::Static, + SymbolKind::Struct => SupportedType::Struct, + SymbolKind::Enum => SupportedType::Enum, + SymbolKind::Variant => SupportedType::EnumMember, + SymbolKind::Union => SupportedType::Union, + SymbolKind::TypeAlias => SupportedType::TypeAlias, + SymbolKind::Trait => SupportedType::Interface, + SymbolKind::Macro => SupportedType::Macro, + SymbolKind::ProcMacro => SupportedType::ProcMacro, + SymbolKind::BuiltinAttr => SupportedType::BuiltinAttribute, + SymbolKind::ToolModule => SupportedType::ToolModule, + SymbolKind::InlineAsmRegOrRegClass => SupportedType::Keyword, }, - HlTag::AttributeBracket => types::ATTRIBUTE_BRACKET, - HlTag::BoolLiteral => types::BOOLEAN, - HlTag::BuiltinType => types::BUILTIN_TYPE, - HlTag::ByteLiteral | HlTag::NumericLiteral => types::NUMBER, - HlTag::CharLiteral => types::CHAR, - HlTag::Comment => types::COMMENT, - HlTag::EscapeSequence => types::ESCAPE_SEQUENCE, - HlTag::InvalidEscapeSequence => types::INVALID_ESCAPE_SEQUENCE, - HlTag::FormatSpecifier => types::FORMAT_SPECIFIER, - HlTag::Keyword => types::KEYWORD, - HlTag::None => types::GENERIC, + HlTag::AttributeBracket => SupportedType::AttributeBracket, + HlTag::BoolLiteral => SupportedType::Boolean, + HlTag::BuiltinType => SupportedType::BuiltinType, + HlTag::ByteLiteral | HlTag::NumericLiteral => SupportedType::Number, + HlTag::CharLiteral => SupportedType::Char, + HlTag::Comment => SupportedType::Comment, + HlTag::EscapeSequence => SupportedType::EscapeSequence, + HlTag::InvalidEscapeSequence => SupportedType::InvalidEscapeSequence, + HlTag::FormatSpecifier => SupportedType::FormatSpecifier, + HlTag::Keyword => SupportedType::Keyword, + HlTag::None => SupportedType::Generic, HlTag::Operator(op) => match op { - HlOperator::Bitwise => types::BITWISE, - HlOperator::Arithmetic => types::ARITHMETIC, - HlOperator::Logical => types::LOGICAL, - HlOperator::Negation => types::NEGATION, - HlOperator::Comparison => types::COMPARISON, - HlOperator::Other => types::OPERATOR, + HlOperator::Bitwise => SupportedType::Bitwise, + HlOperator::Arithmetic => SupportedType::Arithmetic, + HlOperator::Logical => SupportedType::Logical, + HlOperator::Negation => SupportedType::Negation, + HlOperator::Comparison => SupportedType::Comparison, + HlOperator::Other => SupportedType::Operator, }, - HlTag::StringLiteral => types::STRING, - HlTag::UnresolvedReference => types::UNRESOLVED_REFERENCE, + HlTag::StringLiteral => SupportedType::String, + HlTag::UnresolvedReference => SupportedType::UnresolvedReference, HlTag::Punctuation(punct) => match punct { - HlPunct::Bracket => types::BRACKET, - HlPunct::Brace => types::BRACE, - HlPunct::Parenthesis => types::PARENTHESIS, - HlPunct::Angle => types::ANGLE, - HlPunct::Comma => types::COMMA, - HlPunct::Dot => types::DOT, - HlPunct::Colon => types::COLON, - HlPunct::Semi => types::SEMICOLON, - HlPunct::Other => types::PUNCTUATION, - HlPunct::MacroBang => types::MACRO_BANG, + HlPunct::Bracket => SupportedType::Bracket, + HlPunct::Brace => SupportedType::Brace, + HlPunct::Parenthesis => SupportedType::Parenthesis, + HlPunct::Angle => SupportedType::Angle, + HlPunct::Comma => SupportedType::Comma, + HlPunct::Dot => SupportedType::Dot, + HlPunct::Colon => SupportedType::Colon, + HlPunct::Semi => SupportedType::Semicolon, + HlPunct::Other => SupportedType::Punctuation, + HlPunct::MacroBang => SupportedType::MacroBang, }, }; for modifier in highlight.mods.iter() { let modifier = match modifier { - HlMod::Associated => mods::ASSOCIATED, - HlMod::Async => mods::ASYNC, - HlMod::Attribute => mods::ATTRIBUTE_MODIFIER, - HlMod::Callable => mods::CALLABLE, - HlMod::Const => mods::CONSTANT, - HlMod::Consuming => mods::CONSUMING, - HlMod::ControlFlow => mods::CONTROL_FLOW, - HlMod::CrateRoot => mods::CRATE_ROOT, - HlMod::DefaultLibrary => mods::DEFAULT_LIBRARY, - HlMod::Deprecated => mods::DEPRECATED, - HlMod::Definition => mods::DECLARATION, - HlMod::Documentation => mods::DOCUMENTATION, - HlMod::Injected => mods::INJECTED, - HlMod::IntraDocLink => mods::INTRA_DOC_LINK, - HlMod::Library => mods::LIBRARY, - HlMod::Macro => mods::MACRO_MODIFIER, - HlMod::ProcMacro => mods::PROC_MACRO_MODIFIER, - HlMod::Mutable => mods::MUTABLE, - HlMod::Public => mods::PUBLIC, - HlMod::Reference => mods::REFERENCE, - HlMod::Static => mods::STATIC, - HlMod::Trait => mods::TRAIT_MODIFIER, - HlMod::Unsafe => mods::UNSAFE, + HlMod::Associated => SupportedModifiers::Associated, + HlMod::Async => SupportedModifiers::Async, + HlMod::Attribute => SupportedModifiers::AttributeModifier, + HlMod::Callable => SupportedModifiers::Callable, + HlMod::Const => SupportedModifiers::Constant, + HlMod::Consuming => SupportedModifiers::Consuming, + HlMod::ControlFlow => SupportedModifiers::ControlFlow, + HlMod::CrateRoot => SupportedModifiers::CrateRoot, + HlMod::DefaultLibrary => SupportedModifiers::DefaultLibrary, + HlMod::Deprecated => SupportedModifiers::Deprecated, + HlMod::Definition => SupportedModifiers::Declaration, + HlMod::Documentation => SupportedModifiers::Documentation, + HlMod::Injected => SupportedModifiers::Injected, + HlMod::IntraDocLink => SupportedModifiers::IntraDocLink, + HlMod::Library => SupportedModifiers::Library, + HlMod::Macro => SupportedModifiers::MacroModifier, + HlMod::ProcMacro => SupportedModifiers::ProcMacroModifier, + HlMod::Mutable => SupportedModifiers::Mutable, + HlMod::Public => SupportedModifiers::Public, + HlMod::Reference => SupportedModifiers::Reference, + HlMod::Static => SupportedModifiers::Static, + HlMod::Trait => SupportedModifiers::TraitModifier, + HlMod::Unsafe => SupportedModifiers::Unsafe, }; mods |= modifier; } @@ -983,7 +981,7 @@ pub(crate) fn folding_range( } } -pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url { +pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Uri { snap.file_id_to_url(file_id) } @@ -991,8 +989,8 @@ pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url /// This will only happen when processing windows paths. /// /// When processing non-windows path, this is essentially the same as `Url::from_file_path`. -pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url { - let url = lsp_types::Url::from_file_path(path).unwrap(); +pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Uri { + let url = lsp_types::Uri(path.to_string()); match path.components().next() { Some(Utf8Component::Prefix(prefix)) if matches!(prefix.kind(), Utf8Prefix::Disk(_) | Utf8Prefix::VerbatimDisk(_)) => @@ -1003,7 +1001,8 @@ pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url { } let driver_letter_range = { - let (scheme, drive_letter, _rest) = match url.as_str().splitn(3, ':').collect_tuple() { + let uri = url.to_string(); + let (scheme, drive_letter, _rest) = match uri.splitn(3, ':').collect_tuple() { Some(it) => it, None => return url, }; @@ -1014,18 +1013,21 @@ pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url { // Note: lowercasing the `path` itself doesn't help, the `Url::parse` // machinery *also* canonicalizes the drive letter. So, just massage the // string in place. - let mut url: String = url.into(); + let mut url: String = url.to_string().to_owned(); url[driver_letter_range].make_ascii_lowercase(); - lsp_types::Url::parse(&url).unwrap() + lsp_types::Uri(url) } pub(crate) fn optional_versioned_text_document_identifier( snap: &GlobalStateSnapshot, file_id: FileId, ) -> lsp_types::OptionalVersionedTextDocumentIdentifier { - let url = url(snap, file_id); - let version = snap.url_file_version(&url); - lsp_types::OptionalVersionedTextDocumentIdentifier { uri: url, version } + let uri = url(snap, file_id); + let version = snap.url_file_version(&uri); + lsp_types::OptionalVersionedTextDocumentIdentifier { + text_document_identifier: lsp_types::TextDocumentIdentifier { uri }, + version, + } } pub(crate) fn location( @@ -1042,7 +1044,7 @@ pub(crate) fn location( /// Prefer using `location_link`, if the client has the cap. pub(crate) fn location_from_nav( snap: &GlobalStateSnapshot, - nav: NavigationTarget, + nav: &NavigationTarget, ) -> Cancellable { let url = url(snap, nav.file_id); let line_index = snap.file_line_index(nav.file_id)?; @@ -1077,7 +1079,7 @@ pub(crate) fn location_link( fn location_info( snap: &GlobalStateSnapshot, target: NavigationTarget, -) -> Cancellable<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { +) -> Cancellable<(lsp_types::Uri, lsp_types::Range, lsp_types::Range)> { let line_index = snap.file_line_index(target.file_id)?; let target_uri = url(snap, target.file_id); @@ -1091,25 +1093,90 @@ pub(crate) fn goto_definition_response( snap: &GlobalStateSnapshot, src: Option, targets: Vec, -) -> Cancellable { +) -> Cancellable { if snap.config.location_link() { - let links = targets - .into_iter() - .unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range)) - .map(|nav| location_link(snap, src, nav)) - .collect::>>()?; + let links = targets_to_links(snap, src, targets)?; Ok(links.into()) } else { - let locations = targets - .into_iter() - .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) - .unique() - .map(|range| location(snap, range)) - .collect::>>()?; - Ok(locations.into()) + let locations = targets_to_locations(snap, targets)?; + Ok(lsp_types::DefinitionRequestResponse::Definition(lsp_types::Definition::LocationList( + locations, + ))) + } +} + +pub(crate) fn goto_declaration_response( + snap: &GlobalStateSnapshot, + src: Option, + targets: Vec, +) -> Cancellable { + if snap.config.location_link() { + let links = targets_to_links(snap, src, targets)?; + Ok(links.into()) + } else { + let locations = targets_to_locations(snap, targets)?; + Ok(lsp_types::DeclarationRequestResponse::Declaration( + lsp_types::Declaration::LocationList(locations), + )) } } +pub(crate) fn goto_implementation_response( + snap: &GlobalStateSnapshot, + src: Option, + targets: Vec, +) -> Cancellable { + if snap.config.location_link() { + let links = targets_to_links(snap, src, targets)?; + Ok(links.into()) + } else { + let locations = targets_to_locations(snap, targets)?; + Ok(lsp_types::ImplementationRequestResponse::Definition( + lsp_types::Definition::LocationList(locations), + )) + } +} + +pub(crate) fn goto_type_definition_response( + snap: &GlobalStateSnapshot, + src: Option, + targets: Vec, +) -> Cancellable { + if snap.config.location_link() { + let links = targets_to_links(snap, src, targets)?; + Ok(links.into()) + } else { + let locations = targets_to_locations(snap, targets)?; + Ok(lsp_types::TypeDefinitionRequestResponse::Definition( + lsp_types::Definition::LocationList(locations), + )) + } +} + +fn targets_to_links( + snap: &GlobalStateSnapshot, + src: Option>, + targets: Vec, +) -> Result, ide_db::base_db::salsa::Cancelled> { + targets + .into_iter() + .unique_by(|nav| (nav.file_id, nav.full_range, nav.focus_range)) + .map(|nav| location_link(snap, src, nav)) + .collect::>>() +} + +fn targets_to_locations( + snap: &GlobalStateSnapshot, + targets: Vec, +) -> Result, ide_db::base_db::salsa::Cancelled> { + targets + .into_iter() + .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) + .unique() + .map(|range| location(snap, range)) + .collect::>>() +} + fn outside_workspace_annotation_id() -> String { String::from("OutsideWorkspace") } @@ -1318,19 +1385,21 @@ pub(crate) fn snippet_text_document_ops( match file_system_edit { FileSystemEdit::CreateFile { dst, initial_contents } => { let uri = snap.anchored_path(&dst); - let create_file = lsp_types::ResourceOp::Create(lsp_types::CreateFile { + let create_file = lsp_types::DocumentChange::CreateFile(lsp_types::CreateFile { uri: uri.clone(), options: None, annotation_id: None, }); - ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file)); + ops.push(lsp_ext::SnippetDocumentChangeOperation::Change(create_file)); if !initial_contents.is_empty() { - let text_document = - lsp_types::OptionalVersionedTextDocumentIdentifier { uri, version: None }; + let text_document = lsp_types::OptionalVersionedTextDocumentIdentifier { + text_document_identifier: lsp_types::TextDocumentIdentifier { uri }, + version: None, + }; let text_edit = lsp_ext::SnippetTextEdit { range: lsp_types::Range::default(), new_text: initial_contents, - insert_text_format: Some(lsp_types::InsertTextFormat::PLAIN_TEXT), + insert_text_format: Some(lsp_types::InsertTextFormat::PlainText), annotation_id: None, }; let edit_file = @@ -1348,9 +1417,9 @@ pub(crate) fn snippet_text_document_ops( { rename_file.annotation_id = Some(outside_workspace_annotation_id()) } - ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename( - rename_file, - ))) + ops.push(lsp_ext::SnippetDocumentChangeOperation::Change( + lsp_types::DocumentChange::RenameFile(rename_file), + )) } FileSystemEdit::MoveDir { src, src_id, dst } => { let old_uri = snap.anchored_path(&src); @@ -1362,9 +1431,9 @@ pub(crate) fn snippet_text_document_ops( { rename_file.annotation_id = Some(outside_workspace_annotation_id()) } - ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename( - rename_file, - ))) + ops.push(lsp_ext::SnippetDocumentChangeOperation::Change( + lsp_types::DocumentChange::RenameFile(rename_file), + )) } } Ok(ops) @@ -1449,42 +1518,38 @@ impl From for lsp_types::WorkspaceEdit { lsp_types::WorkspaceEdit { changes: None, document_changes: snippet_workspace_edit.document_changes.map(|changes| { - lsp_types::DocumentChanges::Operations( - changes - .into_iter() - .map(|change| match change { - lsp_ext::SnippetDocumentChangeOperation::Op(op) => { - lsp_types::DocumentChangeOperation::Op(op) - } - lsp_ext::SnippetDocumentChangeOperation::Edit(edit) => { - lsp_types::DocumentChangeOperation::Edit( - lsp_types::TextDocumentEdit { - text_document: edit.text_document, - edits: edit.edits.into_iter().map(From::from).collect(), - }, - ) - } - }) - .collect(), - ) + changes + .into_iter() + .map(|change| match change { + lsp_ext::SnippetDocumentChangeOperation::Change(op) => op, + lsp_ext::SnippetDocumentChangeOperation::Edit(edit) => { + lsp_types::DocumentChange::TextDocumentEdit( + lsp_types::TextDocumentEdit { + text_document: edit.text_document, + edits: edit.edits.into_iter().map(From::from).collect(), + }, + ) + } + }) + .collect() }), change_annotations: snippet_workspace_edit.change_annotations, } } } -impl From - for lsp_types::OneOf -{ +impl From for lsp_types::Edit { fn from( lsp_ext::SnippetTextEdit { annotation_id, insert_text_format:_, new_text, range }: lsp_ext::SnippetTextEdit, ) -> Self { match annotation_id { - Some(annotation_id) => lsp_types::OneOf::Right(lsp_types::AnnotatedTextEdit { - text_edit: lsp_types::TextEdit { range, new_text }, - annotation_id, - }), - None => lsp_types::OneOf::Left(lsp_types::TextEdit { range, new_text }), + Some(annotation_id) => { + lsp_types::Edit::AnnotatedTextEdit(lsp_types::AnnotatedTextEdit { + text_edit: lsp_types::TextEdit { range, new_text }, + annotation_id, + }) + } + None => lsp_types::Edit::TextEdit(lsp_types::TextEdit { range, new_text }), } } } @@ -1495,7 +1560,7 @@ pub(crate) fn call_hierarchy_item( ) -> Cancellable { let name = target.name.to_string(); let detail = target.description.clone(); - let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::FUNCTION); + let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function); let (uri, range, selection_range) = location_info(snap, target)?; Ok(lsp_types::CallHierarchyItem { name, @@ -1511,12 +1576,12 @@ pub(crate) fn call_hierarchy_item( pub(crate) fn code_action_kind(kind: AssistKind) -> lsp_types::CodeActionKind { match kind { - AssistKind::Generate => lsp_types::CodeActionKind::EMPTY, - AssistKind::QuickFix => lsp_types::CodeActionKind::QUICKFIX, - AssistKind::Refactor => lsp_types::CodeActionKind::REFACTOR, - AssistKind::RefactorExtract => lsp_types::CodeActionKind::REFACTOR_EXTRACT, - AssistKind::RefactorInline => lsp_types::CodeActionKind::REFACTOR_INLINE, - AssistKind::RefactorRewrite => lsp_types::CodeActionKind::REFACTOR_REWRITE, + AssistKind::Generate => lsp_types::CodeActionKind::Empty, + AssistKind::QuickFix => lsp_types::CodeActionKind::QuickFix, + AssistKind::Refactor => lsp_types::CodeActionKind::Refactor, + AssistKind::RefactorExtract => lsp_types::CodeActionKind::RefactorExtract, + AssistKind::RefactorInline => lsp_types::CodeActionKind::RefactorInline, + AssistKind::RefactorRewrite => lsp_types::CodeActionKind::RefactorRewrite, } } @@ -1765,7 +1830,7 @@ pub(crate) fn code_lens( let doc_pos = lsp_types::TextDocumentPositionParams::new(id, pos); - let goto_params = lsp_types::request::GotoImplementationParams { + let goto_params = lsp_types::ImplementationParams { text_document_position_params: doc_pos, work_done_progress_params: Default::default(), partial_result_params: Default::default(), @@ -1895,7 +1960,7 @@ pub(crate) mod command { pub(crate) fn show_references( title: String, - uri: &lsp_types::Url, + uri: &lsp_types::Uri, position: lsp_types::Position, locations: Vec, ) -> lsp_types::Command { @@ -1911,6 +1976,7 @@ pub(crate) mod command { to_value(position).unwrap(), to_value(locations).unwrap(), ]), + tooltip: None, } } @@ -1919,6 +1985,7 @@ pub(crate) mod command { title: title.to_owned(), command: "rust-analyzer.runSingle".into(), arguments: Some(vec![to_value(runnable).unwrap()]), + tooltip: None, } } @@ -1927,6 +1994,7 @@ pub(crate) mod command { title: "âš™\u{fe0e} Debug".into(), command: "rust-analyzer.debugSingle".into(), arguments: Some(vec![to_value(runnable).unwrap()]), + tooltip: None, } } @@ -1936,6 +2004,7 @@ pub(crate) mod command { command: "rust-analyzer.interpretFunction".into(), // FIXME: use the `_runnable` here. arguments: Some(vec![]), + tooltip: None, } } @@ -1956,6 +2025,7 @@ pub(crate) mod command { title: nav.name.to_string(), command: "rust-analyzer.gotoLocation".into(), arguments: Some(vec![value]), + tooltip: None, }) } @@ -1964,6 +2034,7 @@ pub(crate) mod command { title: "triggerParameterHints".into(), command: "rust-analyzer.triggerParameterHints".into(), arguments: None, + tooltip: None, } } @@ -1972,6 +2043,7 @@ pub(crate) mod command { title: "rename".into(), command: "rust-analyzer.rename".into(), arguments: None, + tooltip: None, } } } diff --git a/crates/rust-analyzer/src/lsp/utils.rs b/crates/rust-analyzer/src/lsp/utils.rs index 5bea7084fdb5..660f2c9316bf 100644 --- a/crates/rust-analyzer/src/lsp/utils.rs +++ b/crates/rust-analyzer/src/lsp/utils.rs @@ -1,8 +1,8 @@ //! Utilities for LSP-related boilerplate code. -use std::{mem, ops::Range}; +use std::{mem, ops::Range, vec}; use lsp_server::Notification; -use lsp_types::request::Request; +use lsp_types::{MessageActionItem, Request}; use triomphe::Arc; use crate::{ @@ -16,10 +16,8 @@ pub(crate) fn invalid_params_error(message: String) -> LspError { LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message } } -pub(crate) fn notification_is( - notification: &Notification, -) -> bool { - notification.method == N::METHOD +pub(crate) fn notification_is(notification: &Notification) -> bool { + notification.method == N::METHOD.to_string() } #[derive(Debug, Eq, PartialEq)] @@ -39,37 +37,34 @@ impl Progress { impl GlobalState { pub(crate) fn show_message( &mut self, - typ: lsp_types::MessageType, + kind: lsp_types::MessageType, message: String, show_open_log_button: bool, ) { - match self.config.open_server_logs() && show_open_log_button { - true => self.send_request::( + match self.config.open_server_logs() && show_open_log_button { + true => self.send_request::( lsp_types::ShowMessageRequestParams { - typ, + kind, message, actions: Some(vec![lsp_types::MessageActionItem { title: "Open server logs".to_owned(), - properties: Default::default(), }]), }, |this, resp| { let lsp_server::Response { error: None, result: Some(result), .. } = resp - else { return }; - if let Ok(Some(_item)) = crate::from_json::< - ::Result, - >( - lsp_types::request::ShowMessageRequest::METHOD, &result + else { + return; + }; + if let Ok(Some(_item)) = crate::from_json::>( + lsp_types::ShowMessageRequest::METHOD.to_string(), + &result, ) { - this.send_notification::(()); + this.send_notification::(()); } }, ), - false => self.send_notification::( - lsp_types::ShowMessageParams { - typ, - message, - }, + false => self.send_notification::( + lsp_types::ShowMessageParams { kind, message }, ), } } @@ -81,15 +76,15 @@ impl GlobalState { Some(additional_info) => { tracing::error!("{message}:\n{additional_info}"); self.show_message( - lsp_types::MessageType::ERROR, + lsp_types::MessageType::Error, message, tracing::enabled!(tracing::Level::ERROR), ); } None => { tracing::error!("{message}"); - self.send_notification::( - lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message }, + self.send_notification::( + lsp_types::ShowMessageParams { kind: lsp_types::MessageType::Error, message }, ); } } @@ -135,12 +130,12 @@ impl GlobalState { tracing::debug!(?token, ?state, "report_progress {message:?}"); let work_done_progress = match state { Progress::Begin => { - self.send_request::( + self.send_request::( lsp_types::WorkDoneProgressCreateParams { token: token.clone() }, |_, _| (), ); - lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin { + WorkProgress::WorkDoneProgressBegin(lsp_types::WorkDoneProgressBegin { title: title.into(), cancellable, message, @@ -148,23 +143,30 @@ impl GlobalState { }) } Progress::Report => { - lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport { + WorkProgress::WorkDoneProgressReport(lsp_types::WorkDoneProgressReport { cancellable, message, percentage, }) } Progress::End => { - lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd { message }) + WorkProgress::WorkDoneProgressEnd(lsp_types::WorkDoneProgressEnd { message }) } }; - self.send_notification::(lsp_types::ProgressParams { + self.send_notification::(lsp_types::ProgressParams { token, - value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress), + value: serde_json::to_value(work_done_progress).unwrap(), }); } } +#[derive(serde::Serialize)] +enum WorkProgress { + WorkDoneProgressBegin(lsp_types::WorkDoneProgressBegin), + WorkDoneProgressReport(lsp_types::WorkDoneProgressReport), + WorkDoneProgressEnd(lsp_types::WorkDoneProgressEnd), +} + pub(crate) fn apply_document_changes( encoding: PositionEncoding, file_contents: &str, @@ -172,15 +174,26 @@ pub(crate) fn apply_document_changes( ) -> String { // If at least one of the changes is a full document change, use the last // of them as the starting point and ignore all previous changes. - let (mut text, content_changes) = - match content_changes.iter().rposition(|change| change.range.is_none()) { - Some(idx) => { - let text = mem::take(&mut content_changes[idx].text); - (text, &content_changes[idx + 1..]) - } - None => (file_contents.to_owned(), &content_changes[..]), - }; - if content_changes.is_empty() { + let (mut text, r_partial_changes); + match content_changes.iter_mut().rev().try_fold(Vec::new(), |mut acc, change| match change { + lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangePartial(partial) => { + acc.push(partial); + Ok(acc) + } + lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( + whole, + ) => Err((whole, acc)), + }) { + Err((whole_document, reversed_partial_changes)) => { + text = mem::take(&mut whole_document.text); + r_partial_changes = reversed_partial_changes; + } + Ok(partials) => { + text = file_contents.to_owned(); + r_partial_changes = partials; + } + } + if r_partial_changes.is_empty() { return text; } @@ -198,16 +211,13 @@ pub(crate) fn apply_document_changes( // remember the last valid line in the index and only rebuild it if needed. // The VFS will normalize the end of lines to `\n`. let mut index_valid = !0u32; - for change in content_changes { - // The None case can't happen as we have handled it above already - if let Some(range) = change.range { - if index_valid <= range.end.line { - *Arc::make_mut(&mut line_index.index) = ide::LineIndex::new(&text); - } - index_valid = range.start.line; - if let Ok(range) = from_proto::text_range(&line_index, range) { - text.replace_range(Range::::from(range), &change.text); - } + for change in r_partial_changes.iter().rev() { + if index_valid <= change.range.end.line { + *Arc::make_mut(&mut line_index.index) = ide::LineIndex::new(&text); + } + index_valid = change.range.start.line; + if let Ok(range) = from_proto::text_range(&line_index, change.range) { + text.replace_range(Range::::from(range), &change.text); } } text @@ -221,10 +231,10 @@ pub(crate) fn all_edits_are_disjoint( ) -> bool { let mut edit_ranges = Vec::new(); match completion.text_edit.as_ref() { - Some(lsp_types::CompletionTextEdit::Edit(edit)) => { + Some(lsp_types::CompletionItemTextEdit::TextEdit(edit)) => { edit_ranges.push(edit.range); } - Some(lsp_types::CompletionTextEdit::InsertAndReplace(edit)) => { + Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(edit)) => { let replace = edit.replace; let insert = edit.insert; if replace.start != insert.start @@ -252,10 +262,7 @@ pub(crate) fn all_edits_are_disjoint( #[cfg(test)] mod tests { use ide_db::line_index::WideEncoding; - use lsp_types::{ - CompletionItem, CompletionTextEdit, InsertReplaceEdit, Position, Range, - TextDocumentContentChangeEvent, - }; + use lsp_types::{CompletionItem, InsertReplaceEdit, Position, Range}; use super::*; @@ -263,14 +270,14 @@ mod tests { fn test_apply_document_changes() { macro_rules! c { [$($sl:expr, $sc:expr; $el:expr, $ec:expr => $text:expr),+] => { - vec![$(TextDocumentContentChangeEvent { - range: Some(Range { + vec![$(::lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangePartial(lsp_types::TextDocumentContentChangePartial { + range: Range { start: Position { line: $sl, character: $sc }, end: Position { line: $el, character: $ec }, - }), - range_length: None, + }, text: String::from($text), - }),+] + ..Default::default() + })),+] }; } @@ -280,11 +287,11 @@ mod tests { let text = apply_document_changes( encoding, &text, - vec![TextDocumentContentChangeEvent { - range: None, - range_length: None, - text: String::from("the"), - }], + vec![ + lsp_types::TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( + lsp_types::TextDocumentContentChangeWholeDocument { text: String::from("the") }, + ), + ], ); assert_eq!(text, "the"); let text = apply_document_changes(encoding, &text, c![0, 3; 0, 3 => " quick"]); @@ -332,7 +339,11 @@ mod tests { #[test] fn empty_completion_disjoint_tests() { - let empty_completion = CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); + let empty_completion = CompletionItem { + label: "label".to_owned(), + detail: Some("detail".to_owned()), + ..Default::default() + }; let disjoint_edit_1 = lsp_types::TextEdit::new( Range::new(Position::new(2, 2), Position::new(3, 3)), @@ -384,17 +395,19 @@ mod tests { "new_text".to_owned(), ); - let mut completion_with_joint_edits = - CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); - completion_with_joint_edits.additional_text_edits = - Some(vec![disjoint_edit.clone(), joint_edit.clone()]); + let mut completion_with_joint_edits = CompletionItem { + label: "label".to_owned(), + detail: Some("detail".to_owned()), + additional_text_edits: Some(vec![disjoint_edit.clone(), joint_edit.clone()]), + ..Default::default() + }; assert!( !all_edits_are_disjoint(&completion_with_joint_edits, &[]), "Completion with disjoint edits fails the validation even with empty extra edits" ); completion_with_joint_edits.text_edit = - Some(CompletionTextEdit::Edit(disjoint_edit.clone())); + Some(lsp_types::CompletionItemTextEdit::TextEdit(disjoint_edit.clone())); completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit.clone()]); assert!( !all_edits_are_disjoint(&completion_with_joint_edits, &[]), @@ -402,7 +415,7 @@ mod tests { ); completion_with_joint_edits.text_edit = - Some(CompletionTextEdit::InsertAndReplace(InsertReplaceEdit { + Some(lsp_types::CompletionItemTextEdit::InsertReplaceEdit(InsertReplaceEdit { new_text: "new_text".to_owned(), insert: disjoint_edit.range, replace: disjoint_edit_2.range, @@ -429,10 +442,12 @@ mod tests { "new_text".to_owned(), ); - let mut completion_with_disjoint_edits = - CompletionItem::new_simple("label".to_owned(), "detail".to_owned()); - completion_with_disjoint_edits.text_edit = Some(CompletionTextEdit::Edit(disjoint_edit)); - let completion_with_disjoint_edits = completion_with_disjoint_edits; + let completion_with_disjoint_edits = CompletionItem { + label: "label".to_owned(), + detail: Some("detail".to_owned()), + text_edit: Some(lsp_types::CompletionItemTextEdit::TextEdit(disjoint_edit)), + ..Default::default() + }; assert!( all_edits_are_disjoint(&completion_with_disjoint_edits, &[]), diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index f5b3658ea90c..e0da5d7fa709 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -11,7 +11,7 @@ use std::{ use crossbeam_channel::{Receiver, never, select}; use ide_db::base_db::{SourceDatabase, VfsPath}; use lsp_server::{Connection, Notification, Request}; -use lsp_types::{TextDocumentIdentifier, notification::Notification as _}; +use lsp_types::{Notification as _, TextDocumentIdentifier}; use stdx::thread::ThreadIntent; use tracing::{Level, error, span}; use vfs::{AbsPathBuf, FileId, loader::LoadingProgress}; @@ -99,7 +99,7 @@ impl fmt::Display for Event { #[derive(Debug)] pub(crate) enum DeferredTask { - CheckIfIndexed(lsp_types::Url), + CheckIfIndexed(lsp_types::Uri), CheckProcMacroSources(Vec), } @@ -145,8 +145,8 @@ impl fmt::Debug for Event { match self { Event::Lsp(lsp_server::Message::Notification(not)) - if (notification_is::(not) - || notification_is::(not)) => + if (notification_is::(not) + || notification_is::(not)) => { return debug_non_verbose(not, f); } @@ -207,7 +207,7 @@ impl GlobalState { if matches!( &event, Event::Lsp(lsp_server::Message::Notification(Notification { method, .. })) - if method == lsp_types::notification::Exit::METHOD + if method == &lsp_types::ExitNotification::METHOD.to_string() ) { return Ok(()); } @@ -218,33 +218,43 @@ impl GlobalState { } fn register_did_save_capability(&mut self, additional_patterns: impl Iterator) { - let additional_filters = additional_patterns.map(|pattern| lsp_types::DocumentFilter { - language: None, - scheme: None, - pattern: (Some(pattern)), + let additional_filters = additional_patterns.map(|pattern| { + lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( + lsp_types::TextDocumentFilterPattern { + language: None, + scheme: None, + pattern: pattern.into(), + }, + )) }); let mut selectors = vec![ - lsp_types::DocumentFilter { - language: None, - scheme: None, - pattern: Some("**/*.rs".into()), - }, - lsp_types::DocumentFilter { - language: None, - scheme: None, - pattern: Some("**/Cargo.toml".into()), - }, - lsp_types::DocumentFilter { - language: None, - scheme: None, - pattern: Some("**/Cargo.lock".into()), - }, + lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( + lsp_types::TextDocumentFilterPattern { + language: None, + scheme: None, + pattern: "**/*.rs".to_owned().into(), + }, + )), + lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( + lsp_types::TextDocumentFilterPattern { + language: None, + scheme: None, + pattern: "**/Cargo.toml".to_owned().into(), + }, + )), + lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern( + lsp_types::TextDocumentFilterPattern { + language: None, + scheme: None, + pattern: "**/Cargo.lock".to_owned().into(), + }, + )), ]; selectors.extend(additional_filters); let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions { - include_text: Some(false), + save_options: lsp_types::SaveOptions { include_text: Some(false) }, text_document_registration_options: lsp_types::TextDocumentRegistrationOptions { document_selector: Some(selectors), }, @@ -255,7 +265,7 @@ impl GlobalState { method: "textDocument/didSave".to_owned(), register_options: Some(serde_json::to_value(save_registration_options).unwrap()), }; - self.send_request::( + self.send_request::( lsp_types::RegistrationParams { registrations: vec![registration] }, |_, _| (), ); @@ -443,10 +453,7 @@ impl GlobalState { self.handle_flycheck_msg(message, &mut cargo_finished); } if cargo_finished { - self.send_request::( - (), - |_, _| (), - ); + self.send_request::((), |_, _| ()); } } Event::TestResult(message) => { @@ -502,24 +509,21 @@ impl GlobalState { // Refresh semantic tokens if the client supports it. if self.config.semantic_tokens_refresh() { self.semantic_tokens_cache.lock().clear(); - self.send_request::((), |_, _| ()); + self.send_request::((), |_, _| ()); } // Refresh code lens if the client supports it. if self.config.code_lens_refresh() { - self.send_request::((), |_, _| ()); + self.send_request::((), |_, _| ()); } // Refresh inlay hints if the client supports it. if self.config.inlay_hints_refresh() { - self.send_request::((), |_, _| ()); + self.send_request::((), |_, _| ()); } if self.config.diagnostics_refresh() { - self.send_request::( - (), - |_, _| (), - ); + self.send_request::((), |_, _| ()); } } @@ -773,9 +777,9 @@ impl GlobalState { || self.fetch_workspace_error().is_err()); self.show_message( match health { - lsp_ext::Health::Ok => lsp_types::MessageType::INFO, - lsp_ext::Health::Warning => lsp_types::MessageType::WARNING, - lsp_ext::Health::Error => lsp_types::MessageType::ERROR, + lsp_ext::Health::Ok => lsp_types::MessageType::Info, + lsp_ext::Health::Warning => lsp_types::MessageType::Warning, + lsp_ext::Health::Error => lsp_types::MessageType::Error, }, message.clone(), open_log_button, @@ -851,7 +855,7 @@ impl GlobalState { self.discover_handles.push(handle) } Err(e) => self.show_message( - lsp_types::MessageType::ERROR, + lsp_types::MessageType::Error, format!("Failed to spawn project discovery command: {e:#}"), false, ), @@ -899,7 +903,7 @@ impl GlobalState { } Task::BuildDepsHaveChanged => self.build_deps_changed = true, Task::DiscoverTest(tests) => { - self.send_notification::(tests); + self.send_notification::(tests); } } } @@ -1112,7 +1116,7 @@ impl GlobalState { // The notification requires the namespace form (with underscores) of the target let test_id = format!("{}::{name}", message.target.target.replace('-', "_")); - self.send_notification::( + self.send_notification::( lsp_ext::ChangeTestStateParams { test_id, state }, ); } @@ -1120,12 +1124,12 @@ impl GlobalState { CargoTestOutput::Finished => { self.test_run_remaining_jobs = self.test_run_remaining_jobs.saturating_sub(1); if self.test_run_remaining_jobs == 0 { - self.send_notification::(()); + self.send_notification::(()); self.test_run_session = None; } } CargoTestOutput::Custom { text } => { - self.send_notification::(text); + self.send_notification::(text); } } } @@ -1246,7 +1250,7 @@ impl GlobalState { /// Handles a request. fn on_request(&mut self, req: Request) { let mut dispatcher = RequestDispatcher { req: Some(req), global_state: self }; - dispatcher.on_sync_mut::(|s, ()| { + dispatcher.on_sync_mut::(|s, ()| { s.shutdown_requested = true; Ok(()) }); @@ -1264,7 +1268,6 @@ impl GlobalState { } use crate::handlers::request as handlers; - use lsp_types::request as lsp_request; const RETRY: bool = true; const NO_RETRY: bool = false; @@ -1273,90 +1276,90 @@ impl GlobalState { dispatcher // Request handlers that must run on the main thread // because they mutate GlobalState: - .on_sync_mut::(handlers::handle_workspace_reload) - .on_sync_mut::(handlers::handle_proc_macros_rebuild) - .on_sync_mut::(handlers::handle_memory_usage) - .on_sync_mut::(handlers::handle_run_test) + .on_sync_mut::(handlers::handle_workspace_reload) + .on_sync_mut::(handlers::handle_proc_macros_rebuild) + .on_sync_mut::(handlers::handle_memory_usage) + .on_sync_mut::(handlers::handle_run_test) // Request handlers which are related to the user typing // are run on the main thread to reduce latency: - .on_sync::(handlers::handle_join_lines) - .on_sync::(handlers::handle_on_enter) - .on_sync::(handlers::handle_selection_range) - .on_sync::(handlers::handle_matching_brace) - .on_sync::(handlers::handle_on_type_formatting) + .on_sync::(handlers::handle_join_lines) + .on_sync::(handlers::handle_on_enter) + .on_sync::(handlers::handle_selection_range) + .on_sync::(handlers::handle_matching_brace) + .on_sync::(handlers::handle_on_type_formatting) // Formatting should be done immediately as the editor might wait on it, but we can't // put it on the main thread as we do not want the main thread to block on rustfmt. // So we have an extra thread just for formatting requests to make sure it gets handled // as fast as possible. - .on_fmt_thread::(handlers::handle_formatting) - .on_fmt_thread::(handlers::handle_range_formatting) + .on_fmt_thread::(handlers::handle_formatting) + .on_fmt_thread::(handlers::handle_range_formatting) // We can’t run latency-sensitive request handlers which do semantic // analysis on the main thread because that would block other // requests. Instead, we run these request handlers on higher priority // threads in the threadpool. // FIXME: Retrying can make the result of this stale? - .on_latency_sensitive::(handlers::handle_completion) + .on_latency_sensitive::(handlers::handle_completion) // FIXME: Retrying can make the result of this stale - .on_latency_sensitive::(handlers::handle_completion_resolve) - .on_latency_sensitive::(handlers::handle_semantic_tokens_full) - .on_latency_sensitive::(handlers::handle_semantic_tokens_full_delta) - .on_latency_sensitive::(handlers::handle_semantic_tokens_range) + .on_latency_sensitive::(handlers::handle_completion_resolve) + .on_latency_sensitive::(handlers::handle_semantic_tokens_full) + .on_latency_sensitive::(handlers::handle_semantic_tokens_full_delta) + .on_latency_sensitive::(handlers::handle_semantic_tokens_range) // FIXME: Some of these NO_RETRY could be retries if the file they are interested didn't change. // All other request handlers - .on_with_vfs_default::(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError { + .on_with_vfs_default::(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError { code: lsp_server::ErrorCode::ServerCancelled as i32, message: "server cancelled the request".to_owned(), data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData { retrigger_request: true }).ok(), }) - .on::(handlers::handle_document_symbol) - .on::(handlers::handle_folding_range) - .on::(handlers::handle_signature_help) - .on::(handlers::handle_will_rename_files) - .on::(handlers::handle_goto_definition) - .on::(handlers::handle_goto_declaration) - .on::(handlers::handle_goto_implementation) - .on::(handlers::handle_goto_type_definition) - .on::(handlers::handle_inlay_hints) - .on_identity::(handlers::handle_inlay_hints_resolve) - .on::(handlers::handle_code_lens) - .on_identity::(handlers::handle_code_lens_resolve) - .on::(handlers::handle_prepare_rename) - .on::(handlers::handle_rename) - .on::(handlers::handle_references) - .on::(handlers::handle_document_highlight) - .on::(handlers::handle_call_hierarchy_prepare) - .on::(handlers::handle_call_hierarchy_incoming) - .on::(handlers::handle_call_hierarchy_outgoing) + .on::(handlers::handle_document_symbol) + .on::(handlers::handle_folding_range) + .on::(handlers::handle_signature_help) + .on::(handlers::handle_will_rename_files) + .on::(handlers::handle_goto_definition) + .on::(handlers::handle_goto_declaration) + .on::(handlers::handle_goto_implementation) + .on::(handlers::handle_goto_type_definition) + .on::(handlers::handle_inlay_hints) + .on_identity::(handlers::handle_inlay_hints_resolve) + .on::(handlers::handle_code_lens) + .on_identity::(handlers::handle_code_lens_resolve) + .on::(handlers::handle_prepare_rename) + .on::(handlers::handle_rename) + .on::(handlers::handle_references) + .on::(handlers::handle_document_highlight) + .on::(handlers::handle_call_hierarchy_prepare) + .on::(handlers::handle_call_hierarchy_incoming) + .on::(handlers::handle_call_hierarchy_outgoing) // All other request handlers (lsp extension) - .on::(handlers::fetch_dependency_list) - .on::(handlers::handle_analyzer_status) + .on::(handlers::fetch_dependency_list) + .on::(handlers::handle_analyzer_status) .on::(handlers::handle_view_file_text) - .on::(handlers::handle_view_crate_graph) - .on::(handlers::handle_view_item_tree) - .on::(handlers::handle_discover_test) - .on::(handlers::handle_workspace_symbol) - .on::(handlers::handle_ssr) - .on::(handlers::handle_view_recursive_memory_layout) - .on::(handlers::handle_view_syntax_tree) - .on::(handlers::handle_view_hir) - .on::(handlers::handle_view_mir) - .on::(handlers::handle_interpret_function) - .on::(handlers::handle_expand_macro) - .on::(handlers::handle_parent_module) - .on::(handlers::handle_child_modules) - .on::(handlers::handle_runnables) - .on::(handlers::handle_related_tests) + .on::(handlers::handle_view_crate_graph) + .on::(handlers::handle_view_item_tree) + .on::(handlers::handle_discover_test) + .on::(handlers::handle_workspace_symbol) + .on::(handlers::handle_ssr) + .on::(handlers::handle_view_recursive_memory_layout) + .on::(handlers::handle_view_syntax_tree) + .on::(handlers::handle_view_hir) + .on::(handlers::handle_view_mir) + .on::(handlers::handle_interpret_function) + .on::(handlers::handle_expand_macro) + .on::(handlers::handle_parent_module) + .on::(handlers::handle_child_modules) + .on::(handlers::handle_runnables) + .on::(handlers::handle_related_tests) .on::(handlers::handle_code_action) .on_identity::(handlers::handle_code_action_resolve) .on::(handlers::handle_hover) - .on::(handlers::handle_open_docs) - .on::(handlers::handle_open_cargo_toml) - .on::(handlers::handle_move_item) + .on::(handlers::handle_open_docs) + .on::(handlers::handle_open_cargo_toml) + .on::(handlers::handle_move_item) // - .on::(handlers::internal_testing_fetch_config) - .on::(handlers::get_failed_obligations) + .on::(handlers::internal_testing_fetch_config) + .on::(handlers::get_failed_obligations) .finish(); } @@ -1365,28 +1368,37 @@ impl GlobalState { let _p = span!(Level::INFO, "GlobalState::on_notification", not.method = ?not.method).entered(); use crate::handlers::notification as handlers; - use lsp_types::notification as notifs; NotificationDispatcher { not: Some(not), global_state: self } - .on_sync_mut::(handlers::handle_cancel) - .on_sync_mut::( + .on_sync_mut::(handlers::handle_cancel) + .on_sync_mut::( handlers::handle_work_done_progress_cancel, ) - .on_sync_mut::(handlers::handle_did_open_text_document) - .on_sync_mut::(handlers::handle_did_change_text_document) - .on_sync_mut::(handlers::handle_did_close_text_document) - .on_sync_mut::(handlers::handle_did_save_text_document) - .on_sync_mut::( + .on_sync_mut::( + handlers::handle_did_open_text_document, + ) + .on_sync_mut::( + handlers::handle_did_change_text_document, + ) + .on_sync_mut::( + handlers::handle_did_close_text_document, + ) + .on_sync_mut::( + handlers::handle_did_save_text_document, + ) + .on_sync_mut::( handlers::handle_did_change_configuration, ) - .on_sync_mut::( + .on_sync_mut::( handlers::handle_did_change_workspace_folders, ) - .on_sync_mut::(handlers::handle_did_change_watched_files) - .on_sync_mut::(handlers::handle_cancel_flycheck) - .on_sync_mut::(handlers::handle_clear_flycheck) - .on_sync_mut::(handlers::handle_run_flycheck) - .on_sync_mut::(handlers::handle_abort_run_test) + .on_sync_mut::( + handlers::handle_did_change_watched_files, + ) + .on_sync_mut::(handlers::handle_cancel_flycheck) + .on_sync_mut::(handlers::handle_clear_flycheck) + .on_sync_mut::(handlers::handle_run_flycheck) + .on_sync_mut::(handlers::handle_abort_run_test) .finish(); } } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 1832275eb38d..4d11af18ea32 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -547,8 +547,8 @@ impl GlobalState { // FIXME: can we abort the build scripts here if they are already running? self.workspaces = Arc::new(workspaces); self.check_workspaces_msrv().for_each(|message| { - self.send_notification::( - lsp_types::ShowMessageParams { typ: lsp_types::MessageType::WARNING, message }, + self.send_notification::( + lsp_types::ShowMessageParams { kind: lsp_types::MessageType::Warning, message }, ); }); @@ -573,51 +573,51 @@ impl GlobalState { .filter(|it| it.is_local) .map(|it| it.include); - let mut watchers: Vec = - if self.config.did_change_watched_files_relative_pattern_support() { - // When relative patterns are supported by the client, prefer using them - filter - .flat_map(|include| { - include.into_iter().flat_map(|base| { - [ - (base.clone(), "**/*.rs"), - (base.clone(), "**/Cargo.{lock,toml}"), - (base.clone(), "**/rust-analyzer.toml"), - (base, "**/*.md"), - ] - }) - }) - .map(|(base, pat)| lsp_types::FileSystemWatcher { - glob_pattern: lsp_types::GlobPattern::Relative( - lsp_types::RelativePattern { - base_uri: lsp_types::OneOf::Right( - lsp_types::Url::from_file_path(base).unwrap(), - ), - pattern: pat.to_owned(), - }, - ), - kind: None, - }) - .collect() - } else { - // When they're not, integrate the base to make them into absolute patterns - filter - .flat_map(|include| { - include.into_iter().flat_map(|base| { - [ - format!("{base}/**/*.rs"), - format!("{base}/**/Cargo.{{toml,lock}}"), - format!("{base}/**/rust-analyzer.toml"), - format!("{base}/**/*.md"), - ] - }) + let mut watchers: Vec = if self + .config + .did_change_watched_files_relative_pattern_support() + { + // When relative patterns are supported by the client, prefer using them + filter + .flat_map(|include| { + include.into_iter().flat_map(|base| { + [ + (base.clone(), "**/*.rs"), + (base.clone(), "**/Cargo.{lock,toml}"), + (base.clone(), "**/rust-analyzer.toml"), + (base, "**/*.md"), + ] }) - .map(|glob_pattern| lsp_types::FileSystemWatcher { - glob_pattern: lsp_types::GlobPattern::String(glob_pattern), - kind: None, + }) + .map(|(base, pat)| lsp_types::FileSystemWatcher { + glob_pattern: lsp_types::GlobPattern::RelativePattern( + lsp_types::RelativePattern { + base_uri: lsp_types::BaseUri::Uri(lsp_types::Uri(base.to_string())), + pattern: pat.to_owned(), + }, + ), + kind: None, + }) + .collect() + } else { + // When they're not, integrate the base to make them into absolute patterns + filter + .flat_map(|include| { + include.into_iter().flat_map(|base| { + [ + format!("{base}/**/*.rs"), + format!("{base}/**/Cargo.{{toml,lock}}"), + format!("{base}/**/rust-analyzer.toml"), + format!("{base}/**/*.md"), + ] }) - .collect() - }; + }) + .map(|glob_pattern| lsp_types::FileSystemWatcher { + glob_pattern: lsp_types::GlobPattern::Pattern(glob_pattern), + kind: None, + }) + .collect() + }; // Also explicitly watch any build files configured in JSON project files. for ws in self.workspaces.iter() { @@ -627,7 +627,7 @@ impl GlobalState { continue; }; watchers.push(lsp_types::FileSystemWatcher { - glob_pattern: lsp_types::GlobPattern::String( + glob_pattern: lsp_types::GlobPattern::Pattern( build.build_file.to_string(), ), kind: None, @@ -641,7 +641,7 @@ impl GlobalState { .chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref))) .flatten() .map(|glob_pattern| lsp_types::FileSystemWatcher { - glob_pattern: lsp_types::GlobPattern::String(glob_pattern.to_string()), + glob_pattern: lsp_types::GlobPattern::Pattern(glob_pattern.to_string()), kind: None, }), ); @@ -653,7 +653,7 @@ impl GlobalState { method: "workspace/didChangeWatchedFiles".to_owned(), register_options: Some(serde_json::to_value(registration_options).unwrap()), }; - self.send_request::( + self.send_request::( lsp_types::RegistrationParams { registrations: vec![registration] }, |_, _| (), ); diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index a8632630784b..7ba103f91752 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -20,23 +20,19 @@ mod ratoml; mod support; mod testdir; -use std::{collections::HashMap, path::PathBuf, time::Instant}; +use std::{path::PathBuf, time::Instant}; use ide_db::FxHashMap; use lsp_types::{ - CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, - DocumentFormattingParams, DocumentRangeFormattingParams, FileRename, FormattingOptions, - GotoDefinitionParams, HoverParams, InlayHint, InlayHintLabel, InlayHintParams, - PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem, - TextDocumentPositionParams, WorkDoneProgressParams, - notification::DidOpenTextDocument, - request::{ - CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest, - InlayHintRequest, InlayHintResolveRequest, RangeFormatting, WillRenameFiles, - WorkspaceSymbolRequest, - }, + CodeActionContext, CodeActionParams, CodeActionRequest, CompletionParams, CompletionRequest, + DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DocumentFormattingParams, + DocumentFormattingRequest, DocumentRangeFormattingParams, DocumentRangeFormattingRequest, + FileRename, FormattingOptions, HoverParams, HoverRequest, InlayHint, InlayHintParams, + InlayHintRequest, InlayHintResolveRequest, Label, LanguageKind, PartialResultParams, Position, + Range, RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, TypeDefinitionParams, + TypeDefinitionRequest, WillRenameFilesRequest, WorkDoneProgressParams, WorkspaceSymbolRequest, }; -use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams}; +use rust_analyzer::lsp::ext::{OnEnterRequest, RunnablesParams, RunnablesRequest}; use serde_json::json; use stdx::format_to_acc; @@ -68,8 +64,8 @@ use std::collections::Spam; .server() .wait_until_workspace_is_loaded(); - let res = server.send_request::(CompletionParams { - text_document_position: TextDocumentPositionParams::new( + let res = server.send_request::(CompletionParams { + text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/lib.rs"), Position::new(0, 23), ), @@ -112,13 +108,13 @@ fn f() { let hint = hints.pop().unwrap(); assert!(hint.data.is_some()); assert!( - matches!(&hint.label, InlayHintLabel::LabelParts(parts) if parts[1].location.is_none()) + matches!(&hint.label, Label::InlayHintLabelPartList(parts) if parts[1].location.is_none()) ); let res = server.send_request::(hint); let hint = serde_json::from_value::(res).unwrap(); assert!(hint.data.is_none()); assert!( - matches!(&hint.label, InlayHintLabel::LabelParts(parts) if parts[1].location.is_some()) + matches!(&hint.label, Label::InlayHintLabelPartList(parts) if parts[1].location.is_some()) ); } @@ -160,8 +156,8 @@ use dependency2::Spam; .server() .wait_until_workspace_is_loaded(); - let res = server.send_request::(CompletionParams { - text_document_position: TextDocumentPositionParams::new( + let res = server.send_request::(CompletionParams { + text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/lib.rs"), Position::new(5, 18), ), @@ -171,8 +167,8 @@ use dependency2::Spam; }); assert!(res.to_string().contains("SpecialHashMap"), "{}", res.to_string()); - let res = server.send_request::(CompletionParams { - text_document_position: TextDocumentPositionParams::new( + let res = server.send_request::(CompletionParams { + text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/lib.rs"), Position::new(6, 18), ), @@ -199,8 +195,8 @@ use dependency2::Spam; std::thread::sleep(std::time::Duration::from_secs(3)); - let res = server.send_request::(CompletionParams { - text_document_position: TextDocumentPositionParams::new( + let res = server.send_request::(CompletionParams { + text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/lib.rs"), Position::new(5, 18), ), @@ -210,8 +206,8 @@ use dependency2::Spam; }); assert!(!res.to_string().contains("SpecialHashMap")); - let res = server.send_request::(CompletionParams { - text_document_position: TextDocumentPositionParams::new( + let res = server.send_request::(CompletionParams { + text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/lib.rs"), Position::new(6, 18), ), @@ -256,7 +252,7 @@ fn main() {} .server() .wait_until_workspace_is_loaded(); - server.request::( + server.request::( RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None }, json!([ { @@ -407,7 +403,7 @@ mod tests { .wait_until_workspace_is_loaded(); for runnable in ["consumer", "dependency", "devdependency"] { - server.request::( + server.request::( RunnablesParams { text_document: server.doc_id(&format!("{runnable}/src/lib.rs")), position: None, @@ -472,7 +468,7 @@ fn otherpkg() {} .server() .wait_until_workspace_is_loaded(); - server.request::( + server.request::( RunnablesParams { text_document: server.doc_id("foo/mainpkg/src/main.rs"), position: None }, json!([ "{...}", @@ -497,7 +493,7 @@ fn otherpkg() {} ]), ); - server.request::( + server.request::( RunnablesParams { text_document: server.doc_id("foo/otherpkg/src/lib.rs"), position: None }, json!([ "{...}", @@ -547,7 +543,7 @@ pub use std::collections::HashMap; ) .wait_until_workspace_is_loaded(); - server.request::( + server.request::( DocumentFormattingParams { text_document: server.doc_id("src/lib.rs"), options: FormattingOptions { @@ -556,7 +552,6 @@ pub use std::collections::HashMap; insert_final_newline: None, trim_final_newlines: None, trim_trailing_whitespace: None, - properties: HashMap::new(), }, work_done_progress_params: WorkDoneProgressParams::default(), }, @@ -600,13 +595,12 @@ pub use std::collections::HashMap; ) .wait_until_workspace_is_loaded(); - server.request::( + server.request::( DocumentFormattingParams { text_document: server.doc_id("src/lib.rs"), options: FormattingOptions { tab_size: 4, insert_spaces: false, - properties: HashMap::new(), insert_final_newline: None, trim_final_newlines: None, trim_trailing_whitespace: None, @@ -651,7 +645,7 @@ fn main() {} ) .wait_until_workspace_is_loaded(); - server.request::( + server.request::( DocumentFormattingParams { text_document: server.doc_id("src/lib.rs"), options: FormattingOptions { @@ -660,7 +654,6 @@ fn main() {} insert_final_newline: None, trim_final_newlines: None, trim_trailing_whitespace: None, - properties: HashMap::new(), }, work_done_progress_params: WorkDoneProgressParams::default(), }, @@ -707,7 +700,7 @@ fn main() { .server() .wait_until_workspace_is_loaded(); - server.request::( + server.request::( DocumentRangeFormattingParams { range: Range { end: Position { line: 1, character: 0 }, @@ -720,7 +713,6 @@ fn main() { insert_final_newline: None, trim_final_newlines: None, trim_trailing_whitespace: None, - properties: HashMap::new(), }, work_done_progress_params: WorkDoneProgressParams::default(), }, @@ -928,17 +920,17 @@ fn main() {{}} .wait_until_workspace_is_loaded(); for i in 0..10 { - server.notification::(DidOpenTextDocumentParams { + server.notification::(DidOpenTextDocumentParams { text_document: TextDocumentItem { uri: server.doc_id(&format!("src/m{i}.rs")).uri, - language_id: "rust".to_owned(), + language_id: LanguageKind::Rust, version: 0, text: "/// Docs\nfn foo() {}".to_owned(), }, }); } let start = Instant::now(); - server.request::( + server.request::( TextDocumentPositionParams { text_document: server.doc_id("src/m0.rs"), position: Position { line: 0, character: 5 }, @@ -976,7 +968,7 @@ version = \"0.0.0\" .server() .wait_until_workspace_is_loaded(); - server.request::( + server.request::( TextDocumentPositionParams { text_document: server.doc_id("src/main.rs"), position: Position { line: 0, character: 8 }, @@ -1089,8 +1081,8 @@ fn main() { }); assert!(res.to_string().contains("&str")); - server.request::( - GotoDefinitionParams { + server.request::( + TypeDefinitionParams { text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/main.rs"), Position::new(28, 9), @@ -1115,8 +1107,8 @@ fn main() { }]), ); - server.request::( - GotoDefinitionParams { + server.request::( + TypeDefinitionParams { text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/main.rs"), Position::new(29, 9), @@ -1309,7 +1301,7 @@ use crate::old_folder::nested::foo as bar; Project::with_fixture(code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded(); //rename same level file - server.request::( + server.request::( RenameFilesParams { files: vec![FileRename { old_uri: base_path.join("src/old_file.rs").to_str().unwrap().to_owned(), @@ -1344,7 +1336,7 @@ use crate::old_folder::nested::foo as bar; ); //rename file from mod.rs to foo.rs - server.request::( + server.request::( RenameFilesParams { files: vec![FileRename { old_uri: base_path.join("src/from_mod/mod.rs").to_str().unwrap().to_owned(), @@ -1355,7 +1347,7 @@ use crate::old_folder::nested::foo as bar; ); //rename file from foo.rs to mod.rs - server.request::( + server.request::( RenameFilesParams { files: vec![FileRename { old_uri: base_path.join("src/to_mod/foo.rs").to_str().unwrap().to_owned(), @@ -1366,7 +1358,7 @@ use crate::old_folder::nested::foo as bar; ); //rename same level file - server.request::( + server.request::( RenameFilesParams { files: vec![FileRename { old_uri: base_path.join("src/old_folder").to_str().unwrap().to_owned(), @@ -1568,7 +1560,7 @@ fn test() { .server() .wait_until_workspace_is_loaded(); - let res = server.send_request::( + let res = server.send_request::( rust_analyzer::lsp::ext::GetFailedObligationsParams { text_document: server.doc_id("src/lib.rs"), position: Position::new(4, 19), diff --git a/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/crates/rust-analyzer/tests/slow-tests/ratoml.rs index dd113babffeb..6eff52ef4355 100644 --- a/crates/rust-analyzer/tests/slow-tests/ratoml.rs +++ b/crates/rust-analyzer/tests/slow-tests/ratoml.rs @@ -1,23 +1,24 @@ use crate::support::{Project, Server}; use crate::testdir::TestDir; use lsp_types::{ - DidChangeTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, - TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, Url, + DidChangeTextDocumentNotification, DidChangeTextDocumentParams, + DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DidSaveTextDocumentNotification, + DidSaveTextDocumentParams, TextDocumentContentChangeEvent, + TextDocumentContentChangeWholeDocument, TextDocumentIdentifier, TextDocumentItem, Uri, VersionedTextDocumentIdentifier, - notification::{DidChangeTextDocument, DidOpenTextDocument, DidSaveTextDocument}, }; use paths::Utf8PathBuf; use rust_analyzer::config::Config; use rust_analyzer::lsp::ext::{ - InternalTestingFetchConfig, InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, - InternalTestingFetchConfigResponse, + InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, + InternalTestingFetchConfigRequest, InternalTestingFetchConfigResponse, }; use serde_json::json; use test_utils::skip_slow_tests; struct RatomlTest { - urls: Vec, + urls: Vec, server: Server, tmp_path: Utf8PathBuf, } @@ -54,7 +55,7 @@ impl RatomlTest { case } - fn fixture_path(&self, fixture: &str) -> Url { + fn fixture_path(&self, fixture: &str) -> Uri { let mut lines = fixture.trim().split('\n'); let mut path = @@ -81,73 +82,79 @@ impl RatomlTest { path = path.join(piece); } - Url::parse( - format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/")) - .as_str(), - ) - .unwrap() + Uri(format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/"))) } fn create(&mut self, fixture_path: &str, text: String) { - let url = self.fixture_path(fixture_path); + let uri = self.fixture_path(fixture_path); - self.server.notification::(DidOpenTextDocumentParams { + self.server.notification::(DidOpenTextDocumentParams { text_document: TextDocumentItem { - uri: url.clone(), - language_id: "rust".to_owned(), + uri: uri.clone(), + language_id: lsp_types::LanguageKind::Rust, version: 0, text: String::new(), }, }); - self.server.notification::(DidChangeTextDocumentParams { - text_document: VersionedTextDocumentIdentifier { uri: url, version: 0 }, - content_changes: vec![TextDocumentContentChangeEvent { - range: None, - range_length: None, - text, - }], - }); + self.server.notification::( + DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { + text_document_identifier: TextDocumentIdentifier { uri }, + version: 0, + }, + + content_changes: vec![ + TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( + TextDocumentContentChangeWholeDocument { text }, + ), + ], + }, + ); } fn delete(&mut self, file_idx: usize) { - self.server.notification::(DidOpenTextDocumentParams { + self.server.notification::(DidOpenTextDocumentParams { text_document: TextDocumentItem { uri: self.urls[file_idx].clone(), - language_id: "rust".to_owned(), + language_id: lsp_types::LanguageKind::Rust, version: 0, text: "".to_owned(), }, }); // See if deleting ratoml file will make the config of interest to return to its default value. - self.server.notification::(DidSaveTextDocumentParams { + self.server.notification::(DidSaveTextDocumentParams { text_document: TextDocumentIdentifier { uri: self.urls[file_idx].clone() }, text: Some("".to_owned()), }); } fn edit(&mut self, file_idx: usize, text: String) { - self.server.notification::(DidOpenTextDocumentParams { + self.server.notification::(DidOpenTextDocumentParams { text_document: TextDocumentItem { uri: self.urls[file_idx].clone(), - language_id: "rust".to_owned(), + language_id: lsp_types::LanguageKind::Rust, version: 0, text: String::new(), }, }); - self.server.notification::(DidChangeTextDocumentParams { - text_document: VersionedTextDocumentIdentifier { - uri: self.urls[file_idx].clone(), - version: 0, + self.server.notification::( + DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { + text_document_identifier: TextDocumentIdentifier { + uri: self.urls[file_idx].clone(), + }, + version: 0, + }, + content_changes: vec![ + TextDocumentContentChangeEvent::TextDocumentContentChangeWholeDocument( + TextDocumentContentChangeWholeDocument { text }, + ), + ], }, - content_changes: vec![TextDocumentContentChangeEvent { - range: None, - range_length: None, - text, - }], - }); + ); } fn query( @@ -156,7 +163,7 @@ impl RatomlTest { source_file_idx: usize, expected: InternalTestingFetchConfigResponse, ) { - let res = self.server.send_request::( + let res = self.server.send_request::( InternalTestingFetchConfigParams { text_document: Some(TextDocumentIdentifier { uri: self.urls[source_file_idx].clone(), diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index 73904036730b..46ffcd9009ec 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -9,7 +9,7 @@ use crossbeam_channel::{Receiver, after, select}; use itertools::Itertools; use lsp_server::{Connection, Message, Notification, Request}; use lsp_types::{ - PublishDiagnosticsParams, TextDocumentIdentifier, Url, notification::Exit, request::Shutdown, + ExitNotification, PublishDiagnosticsParams, ShutdownRequest, TextDocumentIdentifier, Uri, }; use parking_lot::{Mutex, MutexGuard}; use paths::{Utf8Path, Utf8PathBuf}; @@ -229,13 +229,13 @@ impl Project<'_> { ..Default::default() }), text_document: Some(lsp_types::TextDocumentClientCapabilities { - definition: Some(lsp_types::GotoCapability { + definition: Some(lsp_types::DefinitionClientCapabilities { link_support: Some(true), ..Default::default() }), code_action: Some(lsp_types::CodeActionClientCapabilities { code_action_literal_support: Some( - lsp_types::CodeActionLiteralSupport::default(), + lsp_types::ClientCodeActionLiteralOptions::default(), ), ..Default::default() }), @@ -244,7 +244,7 @@ impl Project<'_> { ..Default::default() }), inlay_hint: Some(lsp_types::InlayHintClientCapabilities { - resolve_support: Some(lsp_types::InlayHintResolveClientCapabilities { + resolve_support: Some(lsp_types::ClientInlayHintResolveOptions { properties: vec![ "textEdits".to_owned(), "tooltip".to_owned(), @@ -321,22 +321,22 @@ impl Server { pub(crate) fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier { let path = self.dir.path().join(rel_path); - TextDocumentIdentifier { uri: Url::from_file_path(path).unwrap() } + TextDocumentIdentifier { uri: Uri(path.to_string()) } } pub(crate) fn notification(&self, params: N::Params) where - N: lsp_types::notification::Notification, + N: lsp_types::Notification, N::Params: Serialize, { - let r = Notification::new(N::METHOD.to_owned(), params); + let r = Notification::new(N::METHOD.into(), params); self.send_notification(r) } #[track_caller] pub(crate) fn request(&self, params: R::Params, expected_resp: Value) where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: Serialize, { let actual = self.send_request::(params); @@ -354,13 +354,13 @@ impl Server { #[track_caller] pub(crate) fn send_request(&self, params: R::Params) -> Value where - R: lsp_types::request::Request, + R: lsp_types::Request, R::Params: Serialize, { let id = self.req_id.get(); self.req_id.set(id.wrapping_add(1)); - let r = Request::new(id.into(), R::METHOD.to_owned(), params); + let r = Request::new(id.into(), R::METHOD.to_string(), params); self.send_request_(r) } #[track_caller] @@ -493,7 +493,7 @@ impl Server { pub(crate) fn write_file_and_save(&self, path: &str, text: String) { fs::write(self.dir.path().join(path), &text).unwrap(); - self.notification::( + self.notification::( lsp_types::DidSaveTextDocumentParams { text_document: self.doc_id(path), text: Some(text), @@ -504,8 +504,8 @@ impl Server { impl Drop for Server { fn drop(&mut self) { - self.request::((), Value::Null); - self.notification::(()); + self.request::((), Value::Null); + self.notification::(()); } } diff --git a/docs/book/src/contributing/lsp-extensions.md b/docs/book/src/contributing/lsp-extensions.md index 8ba6f6ab531e..41610ecaff46 100644 --- a/docs/book/src/contributing/lsp-extensions.md +++ b/docs/book/src/contributing/lsp-extensions.md @@ -1,5 +1,5 @@