e88d32f281
- pkg/lsp: JSON-RPC 2.0 LSP server (formatting, diagnostics, codeAction quick-fixes) - cmd/pgtidy: lsp and config subcommands - pkg/diagnostics: TextFix struct for byte-range autofixes - pkg/lint: MIG001/MIG003 autofixes, ApplyFixes helper, --fix flag on lint command - editors/vscode: TypeScript extension with LanguageClient, showVersion/showConfig/formatDocument commands, logo - editors/datagrip: Gradle JetBrains plugin via LSP4IJ, pluginIcon - .goreleaser.yaml, .github/workflows: CI + release pipeline - Makefile: snapshot, release, vscode-compile, vscode-package targets - go.mod + all imports: module path updated to git.warky.dev/wdevs/pgtidy - assets: logo files (256px, 128px, 1024px, ico)
106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
import * as cp from 'child_process';
|
|
import * as path from 'path';
|
|
import * as vscode from 'vscode';
|
|
import {
|
|
LanguageClient,
|
|
LanguageClientOptions,
|
|
ServerOptions,
|
|
TransportKind,
|
|
} from 'vscode-languageclient/node';
|
|
|
|
let client: LanguageClient | undefined;
|
|
let outputChannel: vscode.OutputChannel;
|
|
|
|
export function activate(context: vscode.ExtensionContext): void {
|
|
outputChannel = vscode.window.createOutputChannel('PgTidy');
|
|
context.subscriptions.push(outputChannel);
|
|
|
|
// Commands are always registered so they work even when the LSP is disabled.
|
|
context.subscriptions.push(
|
|
vscode.commands.registerCommand('pgtidy.showVersion', cmdShowVersion),
|
|
vscode.commands.registerCommand('pgtidy.showConfig', cmdShowConfig),
|
|
vscode.commands.registerCommand('pgtidy.formatDocument', cmdFormatDocument),
|
|
);
|
|
|
|
const cfg = vscode.workspace.getConfiguration('pgtidy');
|
|
if (!cfg.get<boolean>('enable', true)) {
|
|
return;
|
|
}
|
|
|
|
const bin = cfg.get<string>('path', 'pgtidy');
|
|
|
|
const serverOptions: ServerOptions = {
|
|
command: bin,
|
|
args: ['lsp'],
|
|
transport: TransportKind.stdio,
|
|
};
|
|
|
|
const clientOptions: LanguageClientOptions = {
|
|
documentSelector: [{ scheme: 'file', language: 'sql' }],
|
|
synchronize: {
|
|
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{sql,pgsql}'),
|
|
},
|
|
};
|
|
|
|
client = new LanguageClient('pgtidy', 'PgTidy', serverOptions, clientOptions);
|
|
context.subscriptions.push(client);
|
|
client.start();
|
|
}
|
|
|
|
export function deactivate(): Thenable<void> | undefined {
|
|
return client?.stop();
|
|
}
|
|
|
|
function binary(): string {
|
|
return vscode.workspace.getConfiguration('pgtidy').get<string>('path', 'pgtidy');
|
|
}
|
|
|
|
function contextDir(): string | undefined {
|
|
const folders = vscode.workspace.workspaceFolders;
|
|
if (folders && folders.length > 0) {
|
|
return folders[0].uri.fsPath;
|
|
}
|
|
const doc = vscode.window.activeTextEditor?.document;
|
|
if (doc && !doc.isUntitled) {
|
|
return path.dirname(doc.uri.fsPath);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function cmdShowVersion(): void {
|
|
cp.execFile(binary(), ['version'], (err, stdout, stderr) => {
|
|
if (err) {
|
|
vscode.window.showErrorMessage(`PgTidy: ${stderr.trim() || err.message}`);
|
|
return;
|
|
}
|
|
vscode.window.showInformationMessage(stdout.trim());
|
|
});
|
|
}
|
|
|
|
function cmdShowConfig(): void {
|
|
const cwd = contextDir();
|
|
cp.execFile(binary(), ['config'], { cwd }, (err, stdout, stderr) => {
|
|
if (err) {
|
|
vscode.window.showErrorMessage(`PgTidy: ${stderr.trim() || err.message}`);
|
|
return;
|
|
}
|
|
outputChannel.clear();
|
|
outputChannel.appendLine('PgTidy — effective configuration');
|
|
if (cwd) {
|
|
outputChannel.appendLine(`(resolved from: ${cwd})`);
|
|
}
|
|
outputChannel.appendLine('');
|
|
outputChannel.append(stdout);
|
|
outputChannel.show(true);
|
|
});
|
|
}
|
|
|
|
async function cmdFormatDocument(): Promise<void> {
|
|
const editor = vscode.window.activeTextEditor;
|
|
if (!editor) {
|
|
vscode.window.showWarningMessage('PgTidy: no active editor');
|
|
return;
|
|
}
|
|
await vscode.commands.executeCommand('editor.action.formatDocument');
|
|
}
|