From afad04be395a79b57fb12fdcddae4d240aa6ac74 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Mon, 30 Jun 2025 19:57:21 -0400 Subject: [PATCH] vscode: add status bar item to show server logs also: - add missing docs page for syntax errors - clear diagnostics on file close -- fixes stale diagnostics when switching file type from sql to plain text --- crates/squawk/src/main.rs | 2 +- crates/squawk_server/src/lib.rs | 35 +++++++++++++++++++++++---- docs/docs/syntax-error.md | 43 +++++++++++++++++++++++++++++++++ docs/sidebars.js | 1 + squawk-vscode/package.json | 5 ++++ squawk-vscode/src/extension.ts | 23 +++++++++++++++--- 6 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 docs/docs/syntax-error.md diff --git a/crates/squawk/src/main.rs b/crates/squawk/src/main.rs index 63ad5881..bb332dc4 100644 --- a/crates/squawk/src/main.rs +++ b/crates/squawk/src/main.rs @@ -220,7 +220,7 @@ Please open an issue at https://github.com/sbdchd/squawk/issues/new with the log if let Some(subcommand) = opts.cmd { match subcommand { Command::Server => { - squawk_server::run_server().context("language server failed")?; + squawk_server::run().context("language server failed")?; } Command::UploadToGithub(args) => { github::check_and_comment_on_pr( diff --git a/crates/squawk_server/src/lib.rs b/crates/squawk_server/src/lib.rs index a3203b71..bdb60af8 100644 --- a/crates/squawk_server/src/lib.rs +++ b/crates/squawk_server/src/lib.rs @@ -4,18 +4,19 @@ use log::info; use lsp_server::{Connection, Message, Notification, Response}; use lsp_types::{ CodeDescription, Diagnostic, DiagnosticSeverity, DidChangeTextDocumentParams, - DidOpenTextDocumentParams, GotoDefinitionParams, GotoDefinitionResponse, InitializeParams, - Location, OneOf, Position, PublishDiagnosticsParams, Range, ServerCapabilities, - TextDocumentSyncCapability, TextDocumentSyncKind, Url, + DidCloseTextDocumentParams, DidOpenTextDocumentParams, GotoDefinitionParams, + GotoDefinitionResponse, InitializeParams, Location, OneOf, Position, PublishDiagnosticsParams, + Range, ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind, Url, notification::{ - DidChangeTextDocument, DidOpenTextDocument, Notification as _, PublishDiagnostics, + DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, Notification as _, + PublishDiagnostics, }, request::{GotoDefinition, Request}, }; use squawk_linter::Linter; use squawk_syntax::{Parse, SourceFile}; -pub fn run_server() -> Result<()> { +pub fn run() -> Result<()> { info!("Starting Squawk LSP server"); let (connection, io_threads) = Connection::stdio(); @@ -74,6 +75,8 @@ fn main_loop(connection: Connection, params: serde_json::Value) -> Result<()> { handle_did_open(&connection, notif)?; } else if notif.method == DidChangeTextDocument::METHOD { handle_did_change(&connection, notif)?; + } else if notif.method == DidCloseTextDocument::METHOD { + handle_did_close(&connection, notif)?; } } } @@ -126,6 +129,28 @@ fn handle_did_change(connection: &Connection, notif: lsp_server::Notification) - Ok(()) } +fn handle_did_close(connection: &Connection, notif: lsp_server::Notification) -> Result<()> { + let params: DidCloseTextDocumentParams = serde_json::from_value(notif.params)?; + let uri = params.text_document.uri; + + let publish_params = PublishDiagnosticsParams { + uri, + diagnostics: vec![], + version: None, + }; + + let notification = Notification { + method: PublishDiagnostics::METHOD.to_owned(), + params: serde_json::to_value(publish_params)?, + }; + + connection + .sender + .send(Message::Notification(notification))?; + + Ok(()) +} + fn lint(connection: &Connection, uri: lsp_types::Url, content: &str, version: i32) -> Result<()> { let parse: Parse = SourceFile::parse(content); let parse_errors = parse.errors(); diff --git a/docs/docs/syntax-error.md b/docs/docs/syntax-error.md new file mode 100644 index 00000000..4e28da83 --- /dev/null +++ b/docs/docs/syntax-error.md @@ -0,0 +1,43 @@ +--- +id: syntax-error +title: syntax-error +--- + +## problem + +Squawk encountered invalid syntax when parsing. + +## examples + +trailing comma + +```sql +select f(1,2,); +-- error[syntax-error]: unexpected trailing comma +-- --> stdin:1:13 +-- | +-- 1 | select f(1,2,); +-- | ^ +-- | +``` + +missing semicolon + +```sql +select * from t +select id from users where email = email; +-- error[syntax-error]: expected SEMICOLON +-- --> stdin:1:16 +-- | +-- 1 | select * from t +-- | ^ +-- | +``` + +## solutions + +Fix the syntax error. + +:::note +Squawk might be mistaken, if you think that's the case, please [open an issue](https://github.com/sbdchd/squawk/issues/new)! +::: diff --git a/docs/sidebars.js b/docs/sidebars.js index 04644b6d..66b6ebff 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -31,6 +31,7 @@ module.exports = { "ban-create-domain-with-constraint", "ban-alter-domain-with-add-constraint", "ban-truncate-cascade", + "syntax-error", // xtask:new-rule:error-name ], }, diff --git a/squawk-vscode/package.json b/squawk-vscode/package.json index 1a8380b3..5742dbcc 100644 --- a/squawk-vscode/package.json +++ b/squawk-vscode/package.json @@ -36,6 +36,11 @@ "command": "squawk.serverVersion", "title": "Show Server Version", "category": "Squawk" + }, + { + "command": "squawk.showLogs", + "title": "Show Server Logs", + "category": "Squawk" } ], "languages": [ diff --git a/squawk-vscode/src/extension.ts b/squawk-vscode/src/extension.ts index b1a3cb17..46d2fce8 100644 --- a/squawk-vscode/src/extension.ts +++ b/squawk-vscode/src/extension.ts @@ -32,6 +32,24 @@ export async function activate(context: vscode.ExtensionContext) { ) context.subscriptions.push(serverVersionCommand) + const showLogsCommand = vscode.commands.registerCommand( + "squawk.showLogs", + () => { + client?.outputChannel?.show() + }, + ) + context.subscriptions.push(showLogsCommand) + + const statusBarItem = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + 100, + ) + statusBarItem.text = "Squawk" + statusBarItem.tooltip = "Click to show Squawk Language Server logs" + statusBarItem.command = "squawk.showLogs" + statusBarItem.show() + context.subscriptions.push(statusBarItem) + await startServer(context) } @@ -66,10 +84,7 @@ async function startServer(context: vscode.ExtensionContext) { } const serverOptions: ServerOptions = serverExecutable const clientOptions: LanguageClientOptions = { - documentSelector: [ - { scheme: "file", language: "sql" }, - { scheme: "file", language: "postgres" }, - ], + documentSelector: [{ language: "sql" }, { language: "postgres" }], outputChannel: vscode.window.createOutputChannel("Squawk Language Server"), } client = new LanguageClient(