From a348f1eaa4c35c3f1fbce9d9f05d36ab5158240d Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Fri, 15 Dec 2023 10:14:39 -0500 Subject: [PATCH 01/12] Update "format selection" and/or "format document" to use dbt-core-interface --- src/features/providers/sqlfluff.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/features/providers/sqlfluff.ts b/src/features/providers/sqlfluff.ts index 43dff42..2a06b45 100644 --- a/src/features/providers/sqlfluff.ts +++ b/src/features/providers/sqlfluff.ts @@ -25,6 +25,31 @@ export default class SQLFluff { throw new Error("You must supply either a target file path or the file contents to scan"); } + if (Configuration.dbtInterfaceEnabled() && command === CommandType.FIX) { + // TODO: Make two API calls: + // 1. Register the dbt project with the dbt-core-interface server + // 2. Run the dbt-core-interface format command + // + // Example curl commands below. Note that these commands use hardcoded + // values and paths. Need to get these from somewhere. + // curl -X POST \ + // -H "Content-Type: application/json" \ + // -H "X-dbt-Project: dbt_project" \ + // -d '{ + // "project_dir": "/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/dbt_project", + // "profiles_dir": "/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/profiles_yml", + // "target": "dev" + // }' \ + // http://localhost:8581/register + // + // + // curl -X POST \ + // -H "Content-Type: application/json" \ + // -H "X-dbt-Project: dbt_project" \ + // "http://localhost:8581/format?sql_path=/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/dbt_project/models/my_new_project/issue_1608.sql" + return + } + // This is an unlikely scenario, but we should limit the amount of processes happening at once. while (SQLFluff.childProcesses.length > 10) { const process = SQLFluff.childProcesses.shift(); From b47156babdd85b9b5ff3abfb5be66dad5a72a17d Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 09:46:42 -0500 Subject: [PATCH 02/12] Update "fix" to hit the new /format endpoint --- src/features/helper/dbtInterface.ts | 69 ++++++++++++++++++++++++++++- src/features/providers/sqlfluff.ts | 65 ++++++++++++++++++--------- 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/features/helper/dbtInterface.ts b/src/features/helper/dbtInterface.ts index 8735b4c..d251f59 100644 --- a/src/features/helper/dbtInterface.ts +++ b/src/features/helper/dbtInterface.ts @@ -64,6 +64,16 @@ export class DbtInterface { return url; } + public getFormatURL(): string { + let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?sql_path=${this.sql_path}`; + + if (this.extra_config_path) { + url += `&extra_config_path=${this.extra_config_path}`; + } + + return url; + } + public async healthCheck(): Promise { const abortController = new AbortController(); const timeoutHandler = setTimeout(() => { @@ -134,7 +144,64 @@ export class DbtInterface { ); } catch (error) { Utilities.appendHyphenatedLine(); - Utilities.outputChannel.appendLine("Raw dbt-omsosis /lint error response:"); + Utilities.outputChannel.appendLine("Raw dbt-core-interface /lint error response:"); + Utilities.appendHyphenatedLine(); + Utilities.outputChannel.appendLine(error as string); + Utilities.appendHyphenatedLine(); + + clearTimeout(timeoutHandler); + return failedToReachServerError; + } + clearTimeout(timeoutHandler); + return await response.json() as T; + } + + public async format(timeout = 25000) { + const failedToReachServerError: DbtInterfaceErrorContainer = { + error: { + code: DbtInterfaceErrorCode.FailedToReachServer, + message: "Query failed to reach dbt sync server.", + data: { + "error": `Is the server listening on the http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()} address?`, + }, + }, + }; + + const projectNotRegisteredError: DbtInterfaceErrorContainer = { + error: { + code: DbtInterfaceErrorCode.FailedToReachServer, + message: "dbt project not registered", + data: { + "error": "", + }, + }, + }; + + if (!await this.healthCheck()) { + Utilities.appendHyphenatedLine(); + Utilities.outputChannel.appendLine("Unhealthy dbt project:"); + Utilities.appendHyphenatedLine(); + return projectNotRegisteredError; + } + + const abortController = new AbortController(); + const timeoutHandler = setTimeout(() => { + abortController.abort(); + }, timeout); + let response: Response; + + try { + response = await fetch( + encodeURI(this.getFormatURL()), + { + method: "POST", + signal: abortController.signal as AbortSignal, + body: "", + }, + ); + } catch (error) { + Utilities.appendHyphenatedLine(); + Utilities.outputChannel.appendLine("Raw dbt-core-interface /format error response:"); Utilities.appendHyphenatedLine(); Utilities.outputChannel.appendLine(error as string); Utilities.appendHyphenatedLine(); diff --git a/src/features/providers/sqlfluff.ts b/src/features/providers/sqlfluff.ts index 2a06b45..51e32ad 100644 --- a/src/features/providers/sqlfluff.ts +++ b/src/features/providers/sqlfluff.ts @@ -26,28 +26,49 @@ export default class SQLFluff { } if (Configuration.dbtInterfaceEnabled() && command === CommandType.FIX) { - // TODO: Make two API calls: - // 1. Register the dbt project with the dbt-core-interface server - // 2. Run the dbt-core-interface format command - // - // Example curl commands below. Note that these commands use hardcoded - // values and paths. Need to get these from somewhere. - // curl -X POST \ - // -H "Content-Type: application/json" \ - // -H "X-dbt-Project: dbt_project" \ - // -d '{ - // "project_dir": "/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/dbt_project", - // "profiles_dir": "/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/profiles_yml", - // "target": "dev" - // }' \ - // http://localhost:8581/register - // - // - // curl -X POST \ - // -H "Content-Type: application/json" \ - // -H "X-dbt-Project: dbt_project" \ - // "http://localhost:8581/format?sql_path=/Users/barry/dev/dbt-core-interface/tests/sqlfluff_templater/fixtures/dbt/dbt_project/models/my_new_project/issue_1608.sql" - return + const dbtInterface = new DbtInterface( + undefined, + options.workspacePath ?? options.filePath, + Configuration.config(), + ); + + Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n"); + Utilities.outputChannel.appendLine(dbtInterface.getFormatURL()); + Utilities.appendHyphenatedLine(); + + const response: any = await dbtInterface.format(); + const output: FilePath[] = [ + { + filepath: options.filePath, + // The server returns a message field which contains any errors. + // Should we display this to the user in the error handling block + // below? + //message: response.message ?? "", + //violations: response.result ?? [], + }, + ]; + + Utilities.outputChannel.appendLine("Raw DBT-Interface /format output:"); + Utilities.appendHyphenatedLine(); + Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2)); + Utilities.appendHyphenatedLine(); + + return new Promise((resolve) => { + const code = response?.error?.code ?? 0; + const succeeded = code === 0; + if (!succeeded && !Configuration.suppressNotifications()) { + const message = response?.error?.message ?? "DBT-Interface formatting error."; + const detail = response?.error?.data?.error ?? ""; + + vscode.window.showErrorMessage([message, detail].join("\n")); + } + + resolve({ + // 0 = all good, 1 = format passed but contains unfixable linting violations, 65 = lint passed but found errors + succeeded: succeeded, + lines: [JSON.stringify(output)], + }); + }); } // This is an unlikely scenario, but we should limit the amount of processes happening at once. From ff3cf10bc84eb66010caac5d0259cedb336e42da Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 09:51:18 -0500 Subject: [PATCH 03/12] Fix build error --- src/features/providers/sqlfluff.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/features/providers/sqlfluff.ts b/src/features/providers/sqlfluff.ts index 51e32ad..c99fa20 100644 --- a/src/features/providers/sqlfluff.ts +++ b/src/features/providers/sqlfluff.ts @@ -44,7 +44,9 @@ export default class SQLFluff { // Should we display this to the user in the error handling block // below? //message: response.message ?? "", - //violations: response.result ?? [], + // The "FilePath" interface requires a "violations" field, but /format + // doesn't return any violations. We'll just return an empty array. + violations: [], }, ]; From 10a53729a9c018d689ade6d164e3369a1704e742 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 10:08:44 -0500 Subject: [PATCH 04/12] Fix JavaScript lint error --- src/features/helper/dbtInterface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/helper/dbtInterface.ts b/src/features/helper/dbtInterface.ts index d251f59..7e83bd1 100644 --- a/src/features/helper/dbtInterface.ts +++ b/src/features/helper/dbtInterface.ts @@ -84,7 +84,7 @@ export class DbtInterface { `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/health`, { method: "GET", - signal: abortController.signal as AbortSignal + signal: abortController.signal as AbortSignal, }, ); if (response.status === 200) { From 364e7d923f79372110db0b33fec56baf470671d2 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 10:36:47 -0500 Subject: [PATCH 05/12] Bug fix --- src/features/providers/sqlfluff.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/providers/sqlfluff.ts b/src/features/providers/sqlfluff.ts index c99fa20..3637587 100644 --- a/src/features/providers/sqlfluff.ts +++ b/src/features/providers/sqlfluff.ts @@ -68,7 +68,7 @@ export default class SQLFluff { resolve({ // 0 = all good, 1 = format passed but contains unfixable linting violations, 65 = lint passed but found errors succeeded: succeeded, - lines: [JSON.stringify(output)], + lines: [], }); }); } From 68962c2ec4418f634a994ac14a3e1d99ab36cf93 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 10:55:13 -0500 Subject: [PATCH 06/12] Add "Format document with sqlfluff" status bar button --- src/extension.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/extension.ts b/src/extension.ts index 3eaf77d..456b01d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -93,6 +93,14 @@ export const activate = (context: vscode.ExtensionContext) => { }; context.subscriptions.push(vscode.commands.registerCommand(fixCommand, fixCommandHandler)); + // Adds a "Fix document with sqlfluff" button to the lower right corner of + // the VS Code window + const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + customStatusBarItem.text = "$(pencil)"; + customStatusBarItem.tooltip = "Fix document with sqlfluff"; + customStatusBarItem.command = fixCommand; + customStatusBarItem.show(); + const formatSelection = "sqlfluff.format.selection"; const formatSelectionHandler = async () => { if (vscode.window.activeTextEditor) { From 937724e73f6e2601af7c16c8303f95ed7391b7ee Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 11:00:36 -0500 Subject: [PATCH 07/12] Don't add "Format selection" if using dbt-core-interface --- src/extension.ts | 50 +++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 456b01d..02aab37 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -29,7 +29,7 @@ export const activate = (context: vscode.ExtensionContext) => { ); // Register the "Format Selection" command - if (!Configuration.executeInTerminal()) { + if (!Configuration.executeInTerminal() && !Configuration.dbtInterfaceEnabled()) { const rangeFormattingProvider = new RangeFormattingEditProvider().activate(); vscode.languages.registerDocumentRangeFormattingEditProvider( selector, @@ -102,29 +102,31 @@ export const activate = (context: vscode.ExtensionContext) => { customStatusBarItem.show(); const formatSelection = "sqlfluff.format.selection"; - const formatSelectionHandler = async () => { - if (vscode.window.activeTextEditor) { - // Check if available language - const document = vscode.window.activeTextEditor.document; - const range = new vscode.Range( - vscode.window.activeTextEditor.selection.start, - vscode.window.activeTextEditor.selection.end, - ) - - const textEdits = await FormatSelectionProvider.provideTextEdits( - document, - range, - ); - - textEdits.forEach((textEdit) => { - const workspaceEdit = new vscode.WorkspaceEdit(); - workspaceEdit.replace(document.uri, textEdit.range, textEdit.newText); - - vscode.workspace.applyEdit(workspaceEdit); - }) - } - }; - context.subscriptions.push(vscode.commands.registerCommand(formatSelection, formatSelectionHandler)); + if (!Configuration.dbtInterfaceEnabled()) { + const formatSelectionHandler = async () => { + if (vscode.window.activeTextEditor) { + // Check if available language + const document = vscode.window.activeTextEditor.document; + const range = new vscode.Range( + vscode.window.activeTextEditor.selection.start, + vscode.window.activeTextEditor.selection.end, + ) + + const textEdits = await FormatSelectionProvider.provideTextEdits( + document, + range, + ); + + textEdits.forEach((textEdit) => { + const workspaceEdit = new vscode.WorkspaceEdit(); + workspaceEdit.replace(document.uri, textEdit.range, textEdit.newText); + + vscode.workspace.applyEdit(workspaceEdit); + }) + } + }; + context.subscriptions.push(vscode.commands.registerCommand(formatSelection, formatSelectionHandler)); + } const debugCommand = "sqlfluff.debug"; const debugCommandHandler = async () => { From 67ba58d214b93551670a39809458cf966419aff8 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 18:57:16 -0500 Subject: [PATCH 08/12] Only add the "format document with sqlfluff" button when using dbt-core-interface --- src/extension.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 02aab37..52d88bf 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -93,16 +93,20 @@ export const activate = (context: vscode.ExtensionContext) => { }; context.subscriptions.push(vscode.commands.registerCommand(fixCommand, fixCommandHandler)); - // Adds a "Fix document with sqlfluff" button to the lower right corner of - // the VS Code window - const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); - customStatusBarItem.text = "$(pencil)"; - customStatusBarItem.tooltip = "Fix document with sqlfluff"; - customStatusBarItem.command = fixCommand; - customStatusBarItem.show(); - - const formatSelection = "sqlfluff.format.selection"; - if (!Configuration.dbtInterfaceEnabled()) { + if (Configuration.dbtInterfaceEnabled()) { + // When dbt-core-interface is enabled, adds a "Format document with + // sqlfluff" button to the lower right corner of the VS Code window. Use + // of the word "format" is deliberate, as the button hits the + // dbt-core-interface "/format" endpoint, equivalent to "sqlfluff format". + const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + customStatusBarItem.text = "$(pencil)"; + customStatusBarItem.tooltip = "Format document with sqlfluff"; + customStatusBarItem.command = fixCommand; + customStatusBarItem.show(); + } + else { + // When dbt-core-interface is not enabled, adds a "format selection" action. + const formatSelection = "sqlfluff.format.selection"; const formatSelectionHandler = async () => { if (vscode.window.activeTextEditor) { // Check if available language From 47c3b07d92411918dc090325c6e4d27023e5ad2e Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 2 Jan 2024 19:07:21 -0500 Subject: [PATCH 09/12] Add comments --- src/extension.ts | 6 ++++-- src/features/helper/dbtInterface.ts | 3 +++ src/features/providers/sqlfluff.ts | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 52d88bf..d2388c5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -28,7 +28,9 @@ export const activate = (context: vscode.ExtensionContext) => { formattingProvider, ); - // Register the "Format Selection" command + // Register the "Format Selection" command. NOTE: As mentioned elsewhere, + // the "format selection" action is only available when dbt-core-interface + // is not enabled. if (!Configuration.executeInTerminal() && !Configuration.dbtInterfaceEnabled()) { const rangeFormattingProvider = new RangeFormattingEditProvider().activate(); vscode.languages.registerDocumentRangeFormattingEditProvider( @@ -96,7 +98,7 @@ export const activate = (context: vscode.ExtensionContext) => { if (Configuration.dbtInterfaceEnabled()) { // When dbt-core-interface is enabled, adds a "Format document with // sqlfluff" button to the lower right corner of the VS Code window. Use - // of the word "format" is deliberate, as the button hits the + // of the word "format" (vs "fix") is deliberate, as the button hits the // dbt-core-interface "/format" endpoint, equivalent to "sqlfluff format". const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); customStatusBarItem.text = "$(pencil)"; diff --git a/src/features/helper/dbtInterface.ts b/src/features/helper/dbtInterface.ts index 7e83bd1..1a5190a 100644 --- a/src/features/helper/dbtInterface.ts +++ b/src/features/helper/dbtInterface.ts @@ -65,6 +65,9 @@ export class DbtInterface { } public getFormatURL(): string { + // This endpoint is equivalent to "sqlfluff format". The behavior is + // _similar_ to "sqlfluff fix", but it applies a different set of rules. + // https://docs.sqlfluff.com/en/stable/cli.html#sqlfluff-format let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?sql_path=${this.sql_path}`; if (this.extra_config_path) { diff --git a/src/features/providers/sqlfluff.ts b/src/features/providers/sqlfluff.ts index 3637587..bfdee42 100644 --- a/src/features/providers/sqlfluff.ts +++ b/src/features/providers/sqlfluff.ts @@ -26,6 +26,10 @@ export default class SQLFluff { } if (Configuration.dbtInterfaceEnabled() && command === CommandType.FIX) { + // Handles CommandType.FIX when dbt-core-interface is enabled. + // TRICKY: Note that this actually hits the dbt-core-interface /format + // endpoint. This is a deliberate choice, but may look odd to readers of + // the code. const dbtInterface = new DbtInterface( undefined, options.workspacePath ?? options.filePath, From 21f091a0cae940e4299a57903c9646d59f4c7682 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 16 Jan 2024 15:16:53 -0500 Subject: [PATCH 10/12] Re-enable Format Selection even when using dbt-interface --- src/extension.ts | 58 ++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index d2388c5..40e72bb 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -28,10 +28,8 @@ export const activate = (context: vscode.ExtensionContext) => { formattingProvider, ); - // Register the "Format Selection" command. NOTE: As mentioned elsewhere, - // the "format selection" action is only available when dbt-core-interface - // is not enabled. - if (!Configuration.executeInTerminal() && !Configuration.dbtInterfaceEnabled()) { + // Register the "Format Selection" command + if (!Configuration.executeInTerminal()) { const rangeFormattingProvider = new RangeFormattingEditProvider().activate(); vscode.languages.registerDocumentRangeFormattingEditProvider( selector, @@ -106,33 +104,31 @@ export const activate = (context: vscode.ExtensionContext) => { customStatusBarItem.command = fixCommand; customStatusBarItem.show(); } - else { - // When dbt-core-interface is not enabled, adds a "format selection" action. - const formatSelection = "sqlfluff.format.selection"; - const formatSelectionHandler = async () => { - if (vscode.window.activeTextEditor) { - // Check if available language - const document = vscode.window.activeTextEditor.document; - const range = new vscode.Range( - vscode.window.activeTextEditor.selection.start, - vscode.window.activeTextEditor.selection.end, - ) - - const textEdits = await FormatSelectionProvider.provideTextEdits( - document, - range, - ); - - textEdits.forEach((textEdit) => { - const workspaceEdit = new vscode.WorkspaceEdit(); - workspaceEdit.replace(document.uri, textEdit.range, textEdit.newText); - - vscode.workspace.applyEdit(workspaceEdit); - }) - } - }; - context.subscriptions.push(vscode.commands.registerCommand(formatSelection, formatSelectionHandler)); - } + + const formatSelection = "sqlfluff.format.selection"; + const formatSelectionHandler = async () => { + if (vscode.window.activeTextEditor) { + // Check if available language + const document = vscode.window.activeTextEditor.document; + const range = new vscode.Range( + vscode.window.activeTextEditor.selection.start, + vscode.window.activeTextEditor.selection.end, + ) + + const textEdits = await FormatSelectionProvider.provideTextEdits( + document, + range, + ); + + textEdits.forEach((textEdit) => { + const workspaceEdit = new vscode.WorkspaceEdit(); + workspaceEdit.replace(document.uri, textEdit.range, textEdit.newText); + + vscode.workspace.applyEdit(workspaceEdit); + }) + } + }; + context.subscriptions.push(vscode.commands.registerCommand(formatSelection, formatSelectionHandler)); const debugCommand = "sqlfluff.debug"; const debugCommandHandler = async () => { From 6a35417723492ce86042b147b7a0c50bbd1f271b Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Tue, 16 Jan 2024 15:32:04 -0500 Subject: [PATCH 11/12] "Format selection" now uses dbt-core-interface if enabled --- src/features/helper/dbtInterface.ts | 5 +- .../providers/formatter/rangeFormat.ts | 62 ++++++++++++++----- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/features/helper/dbtInterface.ts b/src/features/helper/dbtInterface.ts index 1a5190a..32786d8 100644 --- a/src/features/helper/dbtInterface.ts +++ b/src/features/helper/dbtInterface.ts @@ -69,6 +69,9 @@ export class DbtInterface { // _similar_ to "sqlfluff fix", but it applies a different set of rules. // https://docs.sqlfluff.com/en/stable/cli.html#sqlfluff-format let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?sql_path=${this.sql_path}`; + if (this.sql !== undefined) { + url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?`; + } if (this.extra_config_path) { url += `&extra_config_path=${this.extra_config_path}`; @@ -199,7 +202,7 @@ export class DbtInterface { { method: "POST", signal: abortController.signal as AbortSignal, - body: "", + body: this.sql, }, ); } catch (error) { diff --git a/src/features/providers/formatter/rangeFormat.ts b/src/features/providers/formatter/rangeFormat.ts index 8db2de8..0d783d2 100644 --- a/src/features/providers/formatter/rangeFormat.ts +++ b/src/features/providers/formatter/rangeFormat.ts @@ -2,6 +2,7 @@ import * as fs from "fs"; import * as vscode from "vscode"; import Configuration from "../../helper/configuration"; +import { DbtInterface } from "../../helper/dbtInterface"; import Utilities from "../../helper/utilities"; import SQLFluff from "../sqlfluff"; import CommandOptions from "../types/commandOptions"; @@ -72,24 +73,55 @@ export class FormatSelectionProvider { return []; } - const commandOptions: CommandOptions = { - filePath: filePath, - fileContents: document.getText(lineRange), - }; - - const result = await SQLFluff.run( - workingDirectory, - CommandType.FIX, - Configuration.formatFileArguments(), - commandOptions, - ); + let lines = undefined; + if (!Configuration.dbtInterfaceEnabled()) { + // Format the selection using sqlfluff CLI + const commandOptions: CommandOptions = { + filePath: filePath, + fileContents: document.getText(lineRange), + }; + + const result = await SQLFluff.run( + workingDirectory, + CommandType.FIX, + Configuration.formatFileArguments(), + commandOptions, + ); + + if (!result.succeeded) { + throw new Error("Command failed to execute, check logs for details"); + } - if (!result.succeeded) { - throw new Error("Command failed to execute, check logs for details"); + lines = FormatHelper.parseLines(result.lines); + } else { + // Format the selection using dbt-core-interface + const dbtInterface = new DbtInterface( + document.getText(lineRange), + workingDirectory, + Configuration.config(), + ); + + Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n"); + Utilities.outputChannel.appendLine(dbtInterface.getFormatURL()); + Utilities.appendHyphenatedLine(); + + const response: any = await dbtInterface.format(); + Utilities.outputChannel.appendLine("Raw DBT-Interface /format output:"); + Utilities.appendHyphenatedLine(); + Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2)); + Utilities.appendHyphenatedLine(); + + const code = response?.error?.code ?? 0; + const succeeded = code === 0; + if (succeeded) { + // response.sql is a multiline string. Split it into an array of lines. + // This is similar to FormatHelper.parseLines(), but it does not look + // for SQLFluff messages in the text because, given this is API output, + // there won't be any. + lines = response.sql.split(/\r?\n|\r|\n/g); + } } - let lines = FormatHelper.parseLines(result.lines); - const leadingWhitespace = document.lineAt(range.start.line).firstNonWhitespaceCharacterIndex + 1; lines = lines ? FormatHelper.addLeadingWhitespace(lines, document.languageId, leadingWhitespace) : undefined; From 8219043c0f4585b1c64a32771c2a13cc4b957d67 Mon Sep 17 00:00:00 2001 From: Barry Hart Date: Wed, 7 Feb 2024 19:30:43 -0500 Subject: [PATCH 12/12] PR review --- src/extension.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 40e72bb..3cbb8fe 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -98,8 +98,8 @@ export const activate = (context: vscode.ExtensionContext) => { // sqlfluff" button to the lower right corner of the VS Code window. Use // of the word "format" (vs "fix") is deliberate, as the button hits the // dbt-core-interface "/format" endpoint, equivalent to "sqlfluff format". - const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); - customStatusBarItem.text = "$(pencil)"; + const customStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + customStatusBarItem.text = "$(list-selection) Format SQL"; customStatusBarItem.tooltip = "Format document with sqlfluff"; customStatusBarItem.command = fixCommand; customStatusBarItem.show();