From 14db6108f2b233f2a9d1b63390f9647e064ddc23 Mon Sep 17 00:00:00 2001 From: Thorsten Muerell Date: Thu, 2 Nov 2017 07:34:26 +0100 Subject: [PATCH] Compile the whole buffer --- package.json | 38 ++++++++--- src/connections.ts | 4 +- src/extension.ts | 154 ++++++++---------------------------------- src/resultsetview.ts | 11 ++- src/sessionmanager.ts | 142 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 209 insertions(+), 140 deletions(-) create mode 100644 src/sessionmanager.ts diff --git a/package.json b/package.json index c2089be..e4004d2 100644 --- a/package.json +++ b/package.json @@ -23,21 +23,37 @@ "title": "Execute SQL Snippet" }, { - "command": "selectConnection", - "title": "Selects the connection to use" - } + "command": "frog.compileFile", + "title": "Compiles the current file" + }, + { + "command": "frog.selectConnection", + "title": "Selects the connection to use" + }, + { + "command": "frog.setRowLimit", + "title": "Sets the row limit" + } + ], + "keybindings": [ + { + "command": "frog.executeSnippet", + "key": "ctrl+enter", + "mac": "ctrl+enter" + }, + { + "command": "frog.compileFile", + "key": "ctrl+alt+c", + "mac": "ctrl+alt+c" + } + ], - "keybindings": [{ - "command": "frog.executeSnippet", - "key": "ctrl+enter", - "mac": "ctrl+enter" - }], "views": { "explorer": [ { - "id": "connections", - "name": "Connections" - } + "id": "connections", + "name": "Connections" + } ] }, "languages": [ diff --git a/src/connections.ts b/src/connections.ts index 46f1942..f10d5cd 100644 --- a/src/connections.ts +++ b/src/connections.ts @@ -16,7 +16,7 @@ export class FolderNode { export class ConnectionNode { - constructor(public name:string, public host:string, public port:Number, public schema:String, public username:String, public password:String) { + constructor(public name:string, public host:string, public port:number, public schema:string, public username:string, public password:string) { } } @@ -68,7 +68,7 @@ export class ConnectionProvider implements TreeDataProvider, TextDocum label: element.name, collapsibleState: void 0, command: { - command: 'selectConnection', + command: 'frog.selectConnection', arguments: [element], title: 'Open Connection' } diff --git a/src/extension.ts b/src/extension.ts index c762b58..ccfce73 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,43 +5,20 @@ import * as vscode from 'vscode'; import { ConnectionProvider, ConnectionNode } from './connections' import { TextDocumentContentProvider } from './resultsetview' import { BlockDetector } from './editorsupport' +import { SessionManager } from './sessionmanager' -const { spawn } = require('child_process'); -const extensionName = "frog"; - -let currentConnection : ConnectionNode = null; -let dbSession = null; - +let sessionManager : SessionManager = null; +let rowLimit = 50; // this method is called when your extension is activated // your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { - let previewUri = vscode.Uri.parse('frog-view://authority/resultset'); - - let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); - statusBarItem.text = 'Frog: No connection' - statusBarItem.show() - context.subscriptions.push(statusBarItem); - + sessionManager = new SessionManager(context); + const connectionProvider = new ConnectionProvider(); - let myOutputChannel = vscode.window.createOutputChannel('SQL Query Results'); - context.subscriptions.push(myOutputChannel); - - let diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName); - context.subscriptions.push(diagnosticCollection); - vscode.window.registerTreeDataProvider('connections', connectionProvider); - let provider = new TextDocumentContentProvider(); - let registration = vscode.workspace.registerTextDocumentContentProvider('frog-view', provider); - - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "frog" is now active!'); - - let disposable = vscode.commands.registerCommand('frog.executeSnippet', () => { - // The code you place here will be executed every time your command is executed - + let disposable = vscode.commands.registerCommand('frog.executeSnippet', () => { let editor = vscode.window.activeTextEditor; if (!editor) return; @@ -54,117 +31,42 @@ export function activate(context: vscode.ExtensionContext) { let text = editor.document.getText(editor.selection); - if (!dbSession) { - if (!currentConnection) { - vscode.window.showWarningMessage('No connection selected'); - return; - } - - let extPath = vscode.extensions.getExtension("todie.frog").extensionPath; - dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', currentConnection.host, currentConnection.port, currentConnection.schema, currentConnection.username, currentConnection.password]); - - let outputBuffer = ""; - - dbSession.stdout.on('data', (data) => { - outputBuffer += data.toString(); - - try { - let json = JSON.parse(outputBuffer); - - //console.log(json); - - const diagnostics = []; - let cd = json['columnDefinitions'] - - if (!json['rows']) { - if ('dbOutput' in json) { - myOutputChannel.append(json['dbOutput'].map((x) => `DB: ${x}\n`).join('')); - } - if (json['userErrors']) { - myOutputChannel.append("Errors found:\n"); - - const document = vscode.window.activeTextEditor.document; - - for (let error of json['userErrors'][0]['lines']) { - let range = document.lineAt(selection.start.line + error['line'] - 1).range; - let diagnostic = new vscode.Diagnostic(range, error['text'], vscode.DiagnosticSeverity.Error); - diagnostic.source = extensionName; - diagnostic.code = "code"; - diagnostics.push(diagnostic); - myOutputChannel.append(error['line'] + ": " + error['text'] + "\n"); - } - - diagnosticCollection.set(document.uri, diagnostics); - } else if (json['exception']) { - myOutputChannel.append("Exception caught: " + json['exceptionMessage'] + "\n"); - } else if ("affectedRows" in json) { - myOutputChannel.append(json['affectedRows'] + " rows affected.\n"); - } else { - myOutputChannel.append("SQL executed successfully.\n"); - } - } else { - provider.setData(json); - provider.update(previewUri); - - vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Result Set View').then((success) => { - }, (reason) => { - vscode.window.showErrorMessage(reason); - }); - - myOutputChannel.append("Query successful.\n"); - } - - myOutputChannel.append("-- " + new Date() + " -------------------------------\n"); - outputBuffer = ""; - statusBarItem.text = currentConnection.name + " (Connected)"; - } catch (e) { - console.log(e); - } - statusBarItem.text = currentConnection.name + " (Connected)"; - }); - - dbSession.stderr.on('data', (data) => { - myOutputChannel.show(true); - myOutputChannel.append(data.toString()); - }); - - dbSession.on('close', (code) => { - console.log(`child process exited with code ${code}`); - dbSession = null; - }); - } - if (!text) { vscode.window.showInformationMessage('No text selected'); return; } - - myOutputChannel.append("-- " + new Date() + " -------------------------------\n"); //Executing: '" + text + "'\n"); - let input = { "sql": text, "rowLimit": 30 }; - dbSession.stdin.write(JSON.stringify(input) + "\n--- END ---\n"); - statusBarItem.text = currentConnection.name + " (Connected, Query running...)"; + sessionManager.execute(text, rowLimit); }); + context.subscriptions.push(disposable); - context.subscriptions.push(disposable, registration); + disposable = vscode.commands.registerCommand('frog.compileFile', () => { + let editor = vscode.window.activeTextEditor; + + const text = editor.document.getText(); + + sessionManager.execute(text, rowLimit); + }); + context.subscriptions.push(disposable); function changeSession(node: ConnectionNode) { - currentConnection = node; - statusBarItem.text = node.name; - if (dbSession) { - dbSession.stdin.end(); - dbSession = null; - } + sessionManager.currentConnection = node; } - vscode.commands.registerCommand('selectConnection', (node: ConnectionNode) => { - if (!dbSession) { - changeSession(node) + disposable = vscode.commands.registerCommand('frog.setRowLimit', (args : Object) => { + rowLimit = args['rowLimit']; + vscode.window.showInformationMessage(`Row limit set to ${args['rowLimit']}`); + }); + context.subscriptions.push(disposable); + + vscode.commands.registerCommand('frog.selectConnection', (node: ConnectionNode) => { + if (!sessionManager.isSessionActive()) { + sessionManager.currentConnection = node; } else { vscode.window.showInformationMessage(`You want to change the connection to '${node.name}'. Sure?`, 'Yes') .then( (selection) => { if (selection == 'Yes') { - changeSession(node); + sessionManager.currentConnection = node; } }, (reason) => {}) } @@ -173,5 +75,5 @@ export function activate(context: vscode.ExtensionContext) { // this method is called when your extension is deactivated export function deactivate() { - if (dbSession) dbSession.stdin.end(); + sessionManager.closeSession(); } \ No newline at end of file diff --git a/src/resultsetview.ts b/src/resultsetview.ts index ac218f2..e18913f 100644 --- a/src/resultsetview.ts +++ b/src/resultsetview.ts @@ -16,9 +16,18 @@ export class TextDocumentContentProvider implements vscode.TextDocumentContentPr border: solid 1px white; padding: 3px; } + #limitBox a { + color: white; + padding: 3px; + } ` - let text = `${styles}` + const choosableLimits = [2,10,50] + let limitBox = '

Limit Results: ' + + choosableLimits.map((limit) => + `${limit}`).join('') + '

' + + let text = `${styles}${limitBox}
` text += this._data['columnDefinitions'].map((x) => ``).join('') text += '' text += this._data['rows'].map((r) => diff --git a/src/sessionmanager.ts b/src/sessionmanager.ts new file mode 100644 index 0000000..5784983 --- /dev/null +++ b/src/sessionmanager.ts @@ -0,0 +1,142 @@ +import * as vscode from 'vscode'; +import { ConnectionNode } from './connections' +import { spawn } from 'child_process' +import { TextDocumentContentProvider } from './resultsetview' + +const extensionName = "frog"; +const previewUri = vscode.Uri.parse('frog-view://authority/resultset'); + +export class SessionManager { + private _currentConnection : ConnectionNode + private outputChannel + private diagnosticCollection; + private statusBarItem + private dbSession + private provider + + constructor(context: vscode.ExtensionContext) { + + this.outputChannel = vscode.window.createOutputChannel('SQL Query Results'); + context.subscriptions.push(this.outputChannel); + + this.diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName); + context.subscriptions.push(this.diagnosticCollection); + + this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + this.statusBarItem.text = 'Frog: No connection' + this.statusBarItem.show() + context.subscriptions.push(this.statusBarItem); + + this.provider = new TextDocumentContentProvider(); + let registration = vscode.workspace.registerTextDocumentContentProvider('frog-view', this.provider); + } + + public set currentConnection(c : ConnectionNode) { + this.statusBarItem.text = c.name; + if (this.dbSession) this.closeSession(); + } + + public get currentConnection() : ConnectionNode { + return this.currentConnection; + } + + public isSessionActive() : boolean { + return this.dbSession; + } + + public closeSession() { + if (!this.dbSession) return; + + this.dbSession.stdin.end(); + this.dbSession = null; + } + + public check() { + if (!this.currentConnection) { + vscode.window.showWarningMessage('No connection selected'); + return; + } + + let extPath = vscode.extensions.getExtension("todie.frog").extensionPath; + this.dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', this.currentConnection.host, this.currentConnection.port.toString(), this.currentConnection.schema, this.currentConnection.username, this.currentConnection.password]); + + let outputBuffer = ""; + + this.dbSession.stdout.on('data', (data) => { + outputBuffer += data.toString(); + + try { + let json = JSON.parse(outputBuffer); + + const diagnostics = []; + let cd = json['columnDefinitions'] + + if (!json['rows']) { + if ('dbOutput' in json) { + this.outputChannel.append(json['dbOutput'].map((x) => `DB: ${x}\n`).join('')); + } + if (json['userErrors']) { + this.outputChannel.append("Errors found:\n"); + + const editor = vscode.window.activeTextEditor; + const document = editor.document; + + for (let error of json['userErrors'][0]['lines']) { + let range = document.lineAt(editor.selection.start.line + error['line'] - 1).range; + let diagnostic = new vscode.Diagnostic(range, error['text'], vscode.DiagnosticSeverity.Error); + diagnostic.source = extensionName; + diagnostic.code = "code"; + diagnostics.push(diagnostic); + this.outputChannel.append(error['line'] + ": " + error['text'] + "\n"); + } + + this.diagnosticCollection.set(document.uri, diagnostics); + } else if (json['exception']) { + this.outputChannel.append("Exception caught: " + json['exceptionMessage'] + "\n"); + } else if ("affectedRows" in json) { + this.outputChannel.append(json['affectedRows'] + " rows affected.\n"); + } else { + this.outputChannel.append("SQL executed successfully.\n"); + } + } else { + this.provider.setData(json); + this.provider.update(previewUri); + + vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Result Set View').then((success) => { + }, (reason) => { + vscode.window.showErrorMessage(reason); + }); + + this.outputChannel.append("Query successful.\n"); + } + + this.outputChannel.append("-- " + new Date() + " -------------------------------\n"); + outputBuffer = ""; + this.statusBarItem.text = this.currentConnection.name + " (Connected)"; + } catch (e) { + console.log(e); + } + this.statusBarItem.text = this.currentConnection.name + " (Connected)"; + }); + + this.dbSession.stderr.on('data', (data) => { + this.outputChannel.show(true); + this.outputChannel.append(data.toString()); + }); + + this.dbSession.on('close', (code) => { + console.log(`child process exited with code ${code}`); + this.dbSession = null; + }); + + } + + public execute(text : string, rowLimit : number) { + this.check(); + + this.outputChannel.append("-- " + new Date() + " -------------------------------\n"); //Executing: '" + text + "'\n"); + let input = { "sql": text, "rowLimit": rowLimit }; + this.dbSession.stdin.write(JSON.stringify(input) + "\n--- END ---\n"); + this.statusBarItem.text = this.currentConnection.name + " (Connected, Query running...)"; + } +} \ No newline at end of file
${x['name']}