diff --git a/src/formatCurrentFile.ts b/src/formatCurrentFile.ts index 41a02d8c..4f4ac422 100644 --- a/src/formatCurrentFile.ts +++ b/src/formatCurrentFile.ts @@ -8,6 +8,45 @@ import {sqlFileToFormatPath} from './constants'; import { SqlxBlockMetadata } from './types'; import { logger } from './logger'; +interface TemplateReplacement { + placeholder: string; + original: string; +} + +function preprocessSqlForSqlfluff(sqlText: string): { processedSql: string; replacements: TemplateReplacement[] } { + const replacements: TemplateReplacement[] = []; + let processedSql = sqlText; + let placeholderCounter = 1; + + const templateRegex = /\$\{[^}]+\}/g; + let match; + + while ((match = templateRegex.exec(sqlText)) !== null) { + const original = match[0]; + const placeholder = `DATAFORM_PLACEHOLDER_${placeholderCounter}`; + + replacements.push({ + placeholder, + original + }); + + processedSql = processedSql.replace(original, placeholder); + placeholderCounter++; + } + + return { processedSql, replacements }; +} + +function restoreDataformSyntax(formattedSql: string, replacements: TemplateReplacement[]): string { + let restoredSql = formattedSql; + + for (const replacement of replacements) { + restoredSql = restoredSql.replace(replacement.placeholder, replacement.original); + } + + return restoredSql; +} + export async function formatDataformSqlxFile(document:vscode.TextDocument){ let formattingCli = vscode.workspace.getConfiguration("vscode-dataform-tools").get("formattingCli"); if (formattingCli === "sqlfluff") { @@ -50,7 +89,9 @@ export async function formatSqlxFile(document:vscode.TextDocument, currentActive let spaceBetweenSameOps = '\n\n'; let sqlBlockText = await getTextForBlock(document, sqlBlockMeta); - writeCompiledSqlToFile(sqlBlockText, sqlFileToFormatPath); + + const { processedSql, replacements } = preprocessSqlForSqlfluff(sqlBlockText); + writeCompiledSqlToFile(processedSql, sqlFileToFormatPath); let [jsBlockText] = await Promise.all([ getTextForBlock(document, jsBlockMeta) ]); try { @@ -95,6 +136,11 @@ export async function formatSqlxFile(document:vscode.TextDocument, currentActive try { await getStdoutFromCliRun(exec, formatCmd); let formattedSql = await readFile(sqlFileToFormatPath); + + if (typeof formattedSql === 'string') { + formattedSql = restoreDataformSyntax(formattedSql, replacements); + } + (formattedSql === "") ? formattedSql: formattedSql = spaceBetweenBlocks + formattedSql; if (typeof formattedSql === 'string'){ diff --git a/src/test/test-workspace/.sqlfluff b/src/test/test-workspace/.sqlfluff index 953ecfd4..e07dd456 100644 --- a/src/test/test-workspace/.sqlfluff +++ b/src/test/test-workspace/.sqlfluff @@ -122,9 +122,10 @@ unquoted_identifiers_policy = all quoted_identifiers_policy = none [sqlfluff:templater:placeholder] -param_regex = (?s)\${\s*(?P[\w_]+)(?P(?:[^{}]+|{(?&rec)})*+)}|(?Pconfig|pre_operations|post_operations)\s*{(?&rec)} +param_regex = (?s)\${\s*(?P[\w_]+)(?P(?:[^{}]+|{(?&rec)})*+)}|(?Pconfig|pre_operations|post_operations|js)\s*{(?&rec)} ref = ref_table_placeholder self = self_table_placeholder when = config = pre_operations = +js =