Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions squawk-vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ Surface SQL related lint errors directly in VSCode.

## Install

Install via the [VSCode marketplace](https://marketplace.visualstudio.com/items?itemName=sbdchd.squawk).

## Install

### From online marketplace

Open the [online marketplace listing](https://marketplace.visualstudio.com/items?itemName=sbdchd.squawk) for Squawk and click "Install". Follow the prompts to open VSCode and install Squawk.
Expand All @@ -26,6 +22,15 @@ Download the extension package from the [latest Github release](https://github.c

With `vsce` installed from NPM (`npm install -g @vscode/vsce`), clone [this repo](https://github.com/sbdchd/vscode-squawk) and run `vsce package`. Install the resulting package with `code --install-extension squawk-*.vsix`

## Settings

```json
{
// enable tracing logs
"squawk.trace.server": "verbose"
}
```

## Dev

Make sure you're on a vscode version >= the one defined in the `package.json`,
Expand Down
1 change: 1 addition & 0 deletions squawk-vscode/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default tseslint.config(
plugins: {},
rules: {
"no-console": "error",
"quotes": ["error", "double", { "avoidEscape": true }],
"@typescript-eslint/no-unused-vars": [
"error",
{
Expand Down
90 changes: 80 additions & 10 deletions squawk-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,65 @@ import {
StateChangeEvent,
} from "vscode-languageclient/node"

// via rust-analyzer
// https://github.com/rust-lang/rust-analyzer/blob/f14bf95931f17ae1830a77d6f0dff38cabb401da/editors/code/src/util.ts#L157C1-L157C1
class LazyOutputChannel implements vscode.OutputChannel {
constructor(name: string) {
this.name = name
}

name: string
_channel: vscode.OutputChannel | undefined

get channel(): vscode.OutputChannel {
if (!this._channel) {
this._channel = vscode.window.createOutputChannel(this.name)
}
return this._channel
}

append(value: string): void {
this.channel.append(value)
}

appendLine(value: string): void {
this.channel.appendLine(value)
}

replace(value: string): void {
this.channel.replace(value)
}

clear(): void {
if (this._channel) {
this._channel.clear()
}
}

show(
columnOrPreserveFocus?: vscode.ViewColumn | boolean,
preserveFocus?: boolean,
): void {
if (typeof columnOrPreserveFocus === "boolean") {
this.channel.show(columnOrPreserveFocus)
} else {
this.channel.show(columnOrPreserveFocus, preserveFocus)
}
}

hide(): void {
if (this._channel) {
this._channel.hide()
}
}

dispose(): void {
if (this._channel) {
this._channel.dispose()
}
}
}

let client: LanguageClient | undefined
let log: Pick<
vscode.LogOutputChannel,
Expand Down Expand Up @@ -144,7 +203,7 @@ function updateStatusBarItem(statusBarItem: vscode.StatusBarItem) {
switch (client.state) {
case State.Stopped:
statusText = "Stopped"
icon = "$(error) "
icon = "$(stop-circle) "
backgroundColor = new vscode.ThemeColor("statusBarItem.warningBackground")
break
case State.Starting:
Expand Down Expand Up @@ -207,6 +266,7 @@ async function startServer(context: vscode.ExtensionContext) {
const serverOptions: ServerOptions = serverExecutable
const clientOptions: LanguageClientOptions = {
documentSelector: [{ language: "sql" }, { language: "postgres" }],
traceOutputChannel: new LazyOutputChannel("Squawk Trace"),
outputChannel: vscode.window.createOutputChannel("Squawk Language Server"),
}
client = new LanguageClient(
Expand All @@ -228,7 +288,7 @@ async function startServer(context: vscode.ExtensionContext) {
await client.start()
log.info("server started successfully")
} catch (error) {
log.error(`Failed to start server:`, error)
log.error("Failed to start server:", error)
vscode.window.showErrorMessage(`Failed to start server: ${String(error)}`)
}
}
Expand Down Expand Up @@ -307,10 +367,12 @@ class SyntaxTreeProvider implements vscode.TextDocumentContentProvider {
try {
const document = this._activeEditor?.document
if (!document) {
return "Error: no active editor found"
vscode.window.showErrorMessage("Error: no active editor found")
return ""
}
if (!client) {
return "Error: no client found"
vscode.window.showErrorMessage("Error: no client found")
return ""
}
const uri = document.uri.toString()
log.info(`Requesting syntax tree for: ${uri}`)
Expand All @@ -320,8 +382,11 @@ class SyntaxTreeProvider implements vscode.TextDocumentContentProvider {
log.info("Syntax tree received")
return response
} catch (error) {
log.error(`Failed to get syntax tree:`, error)
return `Error: Failed to get syntax tree: ${String(error)}`
log.error("Failed to get syntax tree:", error)
vscode.window.showErrorMessage(
`Failed to get syntax tree:\n${String(error)}`,
)
return ""
}
}
}
Expand Down Expand Up @@ -378,10 +443,12 @@ class TokensProvider implements vscode.TextDocumentContentProvider {
try {
const document = this._activeEditor?.document
if (!document) {
return "Error: no active editor found"
vscode.window.showErrorMessage("Error: no active editor found")
return ""
}
if (!client) {
return "Error: no client found"
vscode.window.showErrorMessage("Error: no client found")
return ""
}
const uri = document.uri.toString()
log.info(`Requesting tokens for: ${uri}`)
Expand All @@ -391,8 +458,11 @@ class TokensProvider implements vscode.TextDocumentContentProvider {
log.info("Tokens received")
return response
} catch (error) {
log.error(`Failed to get tokens:`, error)
return `Error: Failed to get tokens: ${String(error)}`
log.error("Failed to get tokens:", error)
vscode.window.showErrorMessage(
`Error: Failed to get tokens:\n${String(error)}`,
)
return ""
}
}
}
Expand Down
Loading