From 35de9fb0d34ab36ed395e059ff17ba2708dbc1b7 Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Tue, 5 Apr 2022 11:47:52 +1000 Subject: [PATCH 1/8] wip --- sway-lsp/src/capabilities/diagnostic.rs | 16 ++++++++++++++++ sway-lsp/src/server.rs | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/sway-lsp/src/capabilities/diagnostic.rs b/sway-lsp/src/capabilities/diagnostic.rs index cdc411c2800..0cf88c28a1e 100644 --- a/sway-lsp/src/capabilities/diagnostic.rs +++ b/sway-lsp/src/capabilities/diagnostic.rs @@ -1,6 +1,7 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use sway_core::{CompileError, CompileWarning}; +use crate::core::token::Token; pub fn get_diagnostics( warnings: Vec, @@ -35,6 +36,21 @@ pub fn get_diagnostics( vec![warnings, errors].into_iter().flatten().collect() } +pub fn generate_warnings_for_parsed_tokens(tokens: &Vec) -> Vec { + let warnings = tokens + .iter() + .map(|token| { + Diagnostic { + range: token.range, + severity: Some(DiagnosticSeverity::WARNING), + ..Default::default() + } + }) + .collect(); + + warnings +} + fn get_range(warning_or_error: &WarningOrError<'_>) -> Range { let (start, end) = match warning_or_error { WarningOrError::Error(error) => error.line_col(), diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index 1732d7b42e1..cc887987b22 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -112,6 +112,15 @@ impl LanguageServer for Backend { async fn did_open(&self, params: DidOpenTextDocumentParams) { let diagnostics = capabilities::text_sync::handle_open_file(self.session.clone(), ¶ms); + let mut diagnostics = vec![]; + self.session.documents + .iter() + .for_each(|document| { + diagnostics.extend(capabilities::diagnostic::generate_warnings_for_parsed_tokens(document.get_tokens())) + }); + + eprintln!("{:#?}", diagnostics); + if !diagnostics.is_empty() { self.client .publish_diagnostics(params.text_document.uri, diagnostics, None) From fb5105f1a4cd91a96904b917db81d3fa026ee5f8 Mon Sep 17 00:00:00 2001 From: JoshuaBatty Date: Tue, 5 Apr 2022 15:12:25 +1000 Subject: [PATCH 2/8] can now emit lsp warnings for all parsed tokens --- sway-lsp/src/capabilities/diagnostic.rs | 16 ----------- sway-lsp/src/server.rs | 35 ++++++++++++++++--------- sway-lsp/src/utils/debug.rs | 24 +++++++++++++++++ sway-lsp/src/utils/mod.rs | 1 + 4 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 sway-lsp/src/utils/debug.rs diff --git a/sway-lsp/src/capabilities/diagnostic.rs b/sway-lsp/src/capabilities/diagnostic.rs index 0cf88c28a1e..cdc411c2800 100644 --- a/sway-lsp/src/capabilities/diagnostic.rs +++ b/sway-lsp/src/capabilities/diagnostic.rs @@ -1,7 +1,6 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range}; use sway_core::{CompileError, CompileWarning}; -use crate::core::token::Token; pub fn get_diagnostics( warnings: Vec, @@ -36,21 +35,6 @@ pub fn get_diagnostics( vec![warnings, errors].into_iter().flatten().collect() } -pub fn generate_warnings_for_parsed_tokens(tokens: &Vec) -> Vec { - let warnings = tokens - .iter() - .map(|token| { - Diagnostic { - range: token.range, - severity: Some(DiagnosticSeverity::WARNING), - ..Default::default() - } - }) - .collect(); - - warnings -} - fn get_range(warning_or_error: &WarningOrError<'_>) -> Range { let (start, end) = match warning_or_error { WarningOrError::Error(error) => error.line_col(), diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index cc887987b22..e2a1ea5c3f0 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -3,6 +3,7 @@ use crate::core::{ document::{DocumentError, TextDocument}, session::Session, }; +use crate::utils::debug; use forc_util::find_manifest_dir; use std::sync::Arc; use sway_utils::helpers::get_sway_files; @@ -13,12 +14,20 @@ use tower_lsp::{jsonrpc, Client, LanguageServer}; pub struct Backend { pub client: Client, session: Arc, + debug: debug::DebugFlags, } impl Backend { pub fn new(client: Client) -> Self { let session = Arc::new(Session::new()); - Backend { client, session } + let debug = debug::DebugFlags { + parsed_tokens_as_warnings: false, + }; + Backend { + client, + session, + debug, + } } async fn log_info_message(&self, message: &str) { @@ -110,20 +119,22 @@ impl LanguageServer for Backend { // Document Handlers async fn did_open(&self, params: DidOpenTextDocumentParams) { + let uri = params.text_document.uri.clone(); let diagnostics = capabilities::text_sync::handle_open_file(self.session.clone(), ¶ms); - let mut diagnostics = vec![]; - self.session.documents - .iter() - .for_each(|document| { - diagnostics.extend(capabilities::diagnostic::generate_warnings_for_parsed_tokens(document.get_tokens())) - }); - - eprintln!("{:#?}", diagnostics); - - if !diagnostics.is_empty() { + // If parsed_tokens_as_warnings is true, take over the normal error and warning display behavior + // and instead show the parsed tokens as warnings. + // This is useful for debugging the lsp parser. + if self.debug.parsed_tokens_as_warnings { + if let Some(document) = self.session.documents.get(uri.path()) { + let diagnostics = debug::generate_warnings_for_parsed_tokens(document.get_tokens()); + self.client + .publish_diagnostics(uri, diagnostics, None) + .await; + } + } else if !diagnostics.is_empty() { self.client - .publish_diagnostics(params.text_document.uri, diagnostics, None) + .publish_diagnostics(uri, diagnostics, None) .await; } } diff --git a/sway-lsp/src/utils/debug.rs b/sway-lsp/src/utils/debug.rs new file mode 100644 index 00000000000..56ea6b3cebc --- /dev/null +++ b/sway-lsp/src/utils/debug.rs @@ -0,0 +1,24 @@ +use crate::core::token::Token; +use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity}; + +// Flags for debugging various parts of the server +#[derive(Debug)] +pub struct DebugFlags { + /// Instructs the client to draw squiggly lines + /// under all of the tokens that our server managed to parse + pub parsed_tokens_as_warnings: bool, +} + +pub fn generate_warnings_for_parsed_tokens(tokens: &[Token]) -> Vec { + let warnings = tokens + .iter() + .map(|token| Diagnostic { + range: token.range, + severity: Some(DiagnosticSeverity::WARNING), + message: token.name.clone(), + ..Default::default() + }) + .collect(); + + warnings +} diff --git a/sway-lsp/src/utils/mod.rs b/sway-lsp/src/utils/mod.rs index d07d6ffecff..bfbf8eb416b 100644 --- a/sway-lsp/src/utils/mod.rs +++ b/sway-lsp/src/utils/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod common; +pub(crate) mod debug; pub(crate) mod function; From a3af8a2b8952b0f5c834021d3efc550333a43ca1 Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Wed, 6 Apr 2022 16:46:46 +1000 Subject: [PATCH 3/8] set lsp DebugFlags via CLI input --- forc/src/cli/commands/lsp.rs | 18 +++++++++++++----- forc/src/cli/mod.rs | 2 +- forc/src/ops/mod.rs | 1 + sway-lsp/src/lib.rs | 8 +++++--- sway-lsp/src/server.rs | 13 +++++-------- sway-lsp/src/utils/debug.rs | 2 +- sway-lsp/src/utils/mod.rs | 2 +- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/forc/src/cli/commands/lsp.rs b/forc/src/cli/commands/lsp.rs index d6e977edaa2..9e73ffccf83 100644 --- a/forc/src/cli/commands/lsp.rs +++ b/forc/src/cli/commands/lsp.rs @@ -1,11 +1,19 @@ -use anyhow::Result; +use crate::ops::forc_lsp; +use anyhow::{bail, Result}; use clap::Parser; /// Run the LSP server. #[derive(Debug, Parser)] -pub(crate) struct Command {} +pub struct Command { + /// Instructs the client to draw squiggly lines + /// under all of the tokens that our server managed to parse + #[clap(long)] + pub parsed_tokens_as_warnings: bool, +} -pub(crate) async fn exec(_command: Command) -> Result<()> { - sway_lsp::start().await; - Ok(()) +pub(crate) async fn exec(command: Command) -> Result<()> { + match forc_lsp::exec(command).await { + Err(e) => bail!(e), + _ => Ok(()), + } } diff --git a/forc/src/cli/mod.rs b/forc/src/cli/mod.rs index a5c7ec84e92..7b13aa5e26f 100644 --- a/forc/src/cli/mod.rs +++ b/forc/src/cli/mod.rs @@ -16,7 +16,7 @@ pub use explorer::Command as ExplorerCommand; pub use format::Command as FormatCommand; pub use init::Command as InitCommand; pub use json_abi::Command as JsonAbiCommand; -use lsp::Command as LspCommand; +pub use lsp::Command as LspCommand; use parse_bytecode::Command as ParseBytecodeCommand; pub use run::Command as RunCommand; use test::Command as TestCommand; diff --git a/forc/src/ops/mod.rs b/forc/src/ops/mod.rs index c6df7a4120c..e099ca70597 100644 --- a/forc/src/ops/mod.rs +++ b/forc/src/ops/mod.rs @@ -5,5 +5,6 @@ pub mod forc_deploy; pub mod forc_explorer; pub mod forc_fmt; pub mod forc_init; +pub mod forc_lsp; pub mod forc_run; pub mod forc_update; diff --git a/sway-lsp/src/lib.rs b/sway-lsp/src/lib.rs index 55e99d62622..b8a4e5d97fa 100644 --- a/sway-lsp/src/lib.rs +++ b/sway-lsp/src/lib.rs @@ -4,13 +4,15 @@ mod capabilities; mod core; mod server; mod sway_config; -mod utils; +pub mod utils; use server::Backend; +use utils::debug::DebugFlags; -pub async fn start() { +pub async fn start(config: DebugFlags) { let stdin = tokio::io::stdin(); let stdout = tokio::io::stdout(); - let (service, socket) = LspService::new(Backend::new); + // let (service, socket) = LspService::new(Backend::new); + let (service, socket) = LspService::new(|client| Backend::new(client, config)); Server::new(stdin, stdout, socket).serve(service).await; } diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index e2a1ea5c3f0..e9bb48d9c10 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -3,7 +3,7 @@ use crate::core::{ document::{DocumentError, TextDocument}, session::Session, }; -use crate::utils::debug; +use crate::utils::debug::{self, DebugFlags}; use forc_util::find_manifest_dir; use std::sync::Arc; use sway_utils::helpers::get_sway_files; @@ -14,19 +14,16 @@ use tower_lsp::{jsonrpc, Client, LanguageServer}; pub struct Backend { pub client: Client, session: Arc, - debug: debug::DebugFlags, + config: DebugFlags, } impl Backend { - pub fn new(client: Client) -> Self { + pub fn new(client: Client, config: DebugFlags) -> Self { let session = Arc::new(Session::new()); - let debug = debug::DebugFlags { - parsed_tokens_as_warnings: false, - }; Backend { client, session, - debug, + config, } } @@ -125,7 +122,7 @@ impl LanguageServer for Backend { // If parsed_tokens_as_warnings is true, take over the normal error and warning display behavior // and instead show the parsed tokens as warnings. // This is useful for debugging the lsp parser. - if self.debug.parsed_tokens_as_warnings { + if self.config.parsed_tokens_as_warnings { if let Some(document) = self.session.documents.get(uri.path()) { let diagnostics = debug::generate_warnings_for_parsed_tokens(document.get_tokens()); self.client diff --git a/sway-lsp/src/utils/debug.rs b/sway-lsp/src/utils/debug.rs index 56ea6b3cebc..8a70c96786e 100644 --- a/sway-lsp/src/utils/debug.rs +++ b/sway-lsp/src/utils/debug.rs @@ -2,7 +2,7 @@ use crate::core::token::Token; use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity}; // Flags for debugging various parts of the server -#[derive(Debug)] +#[derive(Debug, Default)] pub struct DebugFlags { /// Instructs the client to draw squiggly lines /// under all of the tokens that our server managed to parse diff --git a/sway-lsp/src/utils/mod.rs b/sway-lsp/src/utils/mod.rs index bfbf8eb416b..4af74a1cc0f 100644 --- a/sway-lsp/src/utils/mod.rs +++ b/sway-lsp/src/utils/mod.rs @@ -1,3 +1,3 @@ pub(crate) mod common; -pub(crate) mod debug; +pub mod debug; pub(crate) mod function; From 2e8f970ab65aa6424f240cc627ac65167e98fa5a Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Wed, 6 Apr 2022 17:01:43 +1000 Subject: [PATCH 4/8] update tests to take a client and config --- sway-lsp/src/server.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index e9bb48d9c10..84685de3740 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -354,9 +354,13 @@ fn main() { assert_eq!(response, Ok(None)); } + fn config() -> DebugFlags { + Default::default() + } + #[tokio::test] async fn initialize() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -364,7 +368,7 @@ fn main() { #[tokio::test] async fn initialized() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -375,7 +379,7 @@ fn main() { #[tokio::test] async fn initializes_only_once() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let initialize = initialize_request(&mut service).await; @@ -391,7 +395,7 @@ fn main() { #[tokio::test] async fn shutdown() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -413,7 +417,7 @@ fn main() { #[tokio::test] async fn refuses_requests_after_shutdown() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -428,7 +432,7 @@ fn main() { #[tokio::test] async fn did_open() { - let (mut service, mut messages) = LspService::new(Backend::new); + let (mut service, mut messages) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -453,7 +457,7 @@ fn main() { #[tokio::test] async fn did_close() { - let (mut service, _) = LspService::new(Backend::new); + let (mut service, _) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; @@ -478,7 +482,7 @@ fn main() { #[tokio::test] async fn did_change() { - let (mut service, mut messages) = LspService::new(Backend::new); + let (mut service, mut messages) = LspService::new(|client| Backend::new(client, config())); // send "initialize" request let _ = initialize_request(&mut service).await; From 0dd107ea2a8206e7e70fcbc210b6b16229f6ad63 Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Thu, 7 Apr 2022 10:11:30 +1000 Subject: [PATCH 5/8] add ops forc_lsp module --- forc/src/ops/forc_lsp.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 forc/src/ops/forc_lsp.rs diff --git a/forc/src/ops/forc_lsp.rs b/forc/src/ops/forc_lsp.rs new file mode 100644 index 00000000000..7ca1630bfe0 --- /dev/null +++ b/forc/src/ops/forc_lsp.rs @@ -0,0 +1,13 @@ +use crate::cli::LspCommand; +use anyhow::Result; +use sway_lsp::utils::debug; + +pub async fn exec(command: LspCommand) -> Result<()> { + let config = debug::DebugFlags { + parsed_tokens_as_warnings: command.parsed_tokens_as_warnings, + }; + + sway_lsp::start(config).await; + + Ok(()) +} From c1843998517760989b7e60a4589a0b1a4e9587e2 Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Thu, 7 Apr 2022 10:12:53 +1000 Subject: [PATCH 6/8] cargo fmt --- sway-lsp/src/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway-lsp/src/server.rs b/sway-lsp/src/server.rs index 84685de3740..ada4055ab92 100644 --- a/sway-lsp/src/server.rs +++ b/sway-lsp/src/server.rs @@ -356,7 +356,7 @@ fn main() { fn config() -> DebugFlags { Default::default() - } + } #[tokio::test] async fn initialize() { From 140e7368678955bbcc3c1d61ff6c1f4179bd8b98 Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Thu, 7 Apr 2022 11:55:05 +1000 Subject: [PATCH 7/8] add Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76bf04dc899..c707783fd78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1966,9 +1966,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.92.0" +version = "0.92.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a69d4142d51b208c9fc3cea68b1a7fcef30354e7aa6ccad07250fd8430fc76" +checksum = "c79d4897790e8fd2550afa6d6125821edb5716e60e0e285046e070f0f6a06e0e" dependencies = [ "bitflags", "serde", From b84ab5c0944328b6185bdb9f3b561085153a167d Mon Sep 17 00:00:00 2001 From: Joshua Batty Date: Thu, 7 Apr 2022 12:21:16 +1000 Subject: [PATCH 8/8] remove commented line --- sway-lsp/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/sway-lsp/src/lib.rs b/sway-lsp/src/lib.rs index b8a4e5d97fa..c612aa8f059 100644 --- a/sway-lsp/src/lib.rs +++ b/sway-lsp/src/lib.rs @@ -12,7 +12,6 @@ pub async fn start(config: DebugFlags) { let stdin = tokio::io::stdin(); let stdout = tokio::io::stdout(); - // let (service, socket) = LspService::new(Backend::new); let (service, socket) = LspService::new(|client| Backend::new(client, config)); Server::new(stdin, stdout, socket).serve(service).await; }