Skip to content

Commit

Permalink
Merge pull request #136 from keraion/stdin_filename
Browse files Browse the repository at this point in the history
Add support for --stdin-filename for nested config
  • Loading branch information
RobertOstermann authored Jul 3, 2024
2 parents 5847504 + 680b389 commit e98ca58
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 68 deletions.
61 changes: 38 additions & 23 deletions src/features/helper/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from "path";
import * as vscode from "vscode";
import { DiagnosticSeverity } from "vscode";

import SQLFluff from "../providers/sqlfluff";
import DiagnosticSetting from "./types/diagnosticSetting";
import EnvironmentVariable from "./types/environmentVariable";
import FormatLanguageSettings from "./types/formatLanguageSettings";
Expand Down Expand Up @@ -33,6 +34,14 @@ export default class Configuration {
});
}
});

vscode.workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration("sqlfluff.executablePath")) {
SQLFluff.getCLIVersion();
}
});

SQLFluff.getCLIVersion();
}

public static environmentVariables(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
Expand Down Expand Up @@ -217,7 +226,7 @@ export default class Configuration {
public static noqaDisabledRules(): string[] {
const defaultDisabledRules = ["L015", "L017", "L019", "L030", "L032", "L034", "L035", "L037", "L038", "L040", "L041", "L042", "L043", "L044", "L054", "L058", "L063", "L064"];
const noqa = vscode.workspace
.getConfiguration("sqlfluff.codeActions")
.getConfiguration("sqlfluff.codeActions")
.get<string[] | boolean>("noqa", defaultDisabledRules);

if (typeof noqa === "boolean") return [];
Expand All @@ -235,18 +244,18 @@ export default class Configuration {

public static formatLanguages(): string[] {
const languageSettings: (FormatLanguageSettings | string)[] | undefined = vscode.workspace
.getConfiguration("sqlfluff.format")
.get("languages");
.getConfiguration("sqlfluff.format")
.get("languages");


const languages: string[] = [];
languageSettings?.forEach((languageSetting: FormatLanguageSettings | string) => {
if (typeof languageSetting === "string") {
languages.push(languageSetting);
} else {
languages.push(languageSetting.language)
}
})
if (typeof languageSetting === "string") {
languages.push(languageSetting);
} else {
languages.push(languageSetting.language);
}
});

return languages;
}
Expand All @@ -258,31 +267,31 @@ export default class Configuration {

const languages: string[] = [];
languageSettings?.forEach((languageSetting: FormatLanguageSettings | string) => {
if (typeof languageSetting === "string") {
languages.push(languageSetting);
} else if (languageSetting.contextMenuFormatOptions) {
languages.push(languageSetting.language);
}
})
if (typeof languageSetting === "string") {
languages.push(languageSetting);
} else if (languageSetting.contextMenuFormatOptions) {
languages.push(languageSetting.language);
}
});

return languages;
}

public static formatLanguageSetting(languageId: string): FormatLanguageSettings | undefined {
const languageSettings: (FormatLanguageSettings | string)[] | undefined = vscode.workspace
.getConfiguration("sqlfluff.format")
.get("languages");
.getConfiguration("sqlfluff.format")
.get("languages");

const setting = languageSettings?.find((languageSetting: FormatLanguageSettings | string) => {
if (typeof languageSettings === "string") return false;
if (typeof languageSettings === "string") return false;

const typedSetting = languageSetting as unknown as FormatLanguageSettings;
if (typedSetting.language === languageId) return true;
const typedSetting = languageSetting as unknown as FormatLanguageSettings;
if (typedSetting.language === languageId) return true;

return false;
});
return false;
});

if (typeof setting === "string") return undefined
if (typeof setting === "string") return undefined;
return setting;
}

Expand Down Expand Up @@ -378,6 +387,12 @@ export default class Configuration {

public static formatFileArguments(): string[] {
const extraArguments = [...this.fixArguments()];
if (
!SQLFluff.isForceDeprecated() &&
!extraArguments.some((x) => x == "--force")
) {
extraArguments.push("--force");
}

return extraArguments;
}
Expand Down
2 changes: 1 addition & 1 deletion src/features/providers/linter/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default class LintingProvider {
const workspaceFolder = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined;
const rootPath = workspaceFolder ? Utilities.normalizePath(workspaceFolder) : undefined;
const workingDirectory = workspacePath ?? Configuration.workingDirectory(rootPath);
const filePath = document ? Utilities.normalizePath(document.fileName) : workingDirectory;
const filePath = document && !document.isUntitled ? Utilities.normalizePath(document.fileName) : workingDirectory;

if (!filePath) {
Utilities.outputChannel.appendLine("ERROR: File path not found.");
Expand Down
143 changes: 99 additions & 44 deletions src/features/providers/sqlfluff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import CommandType from "./types/commandType";

export default class SQLFluff {
static childProcesses: CProcess.ChildProcess[] = [];
static version: [major: number, minor: number, patch: number];

static isForceDeprecated = () => {
return SQLFluff.version >= [3, 0, 0];
};

static supportsStdinFilename = () => {
return SQLFluff.version > [3, 0, 5];
};

public static async run(
workingDirectory: string | undefined,
Expand Down Expand Up @@ -86,74 +95,107 @@ export default class SQLFluff {
const normalizedWorkingDirectory = workingDirectory ? Utilities.normalizePath(workingDirectory) : undefined;
const shouldUseStdin = !!options.fileContents?.length;
const finalArgs = [command, ...args, ...Configuration.extraArguments()];
const targetFileRelativePath = SQLFluff.getTargetFileRelativePath(options, normalizedWorkingDirectory);

Utilities.appendHyphenatedLine();
if (shouldUseStdin) {
Utilities.outputChannel.appendLine("Reading from stdin, not file, input may be dirty/partial");
if (SQLFluff.supportsStdinFilename() && targetFileRelativePath) {
finalArgs.push("--stdin-filename");
finalArgs.push(targetFileRelativePath);
}
finalArgs.push("-");
} else if (options.workspacePath) {
Utilities.outputChannel.appendLine("Reading from workspace, not stdin");
} else {
Utilities.outputChannel.appendLine("Reading from file, not stdin");
finalArgs.push(targetFileRelativePath!);
}

if (Configuration.dbtInterfaceEnabled() && command === CommandType.LINT) {
return await SQLFluff.runDbtInterface(shouldUseStdin, options);
}

return SQLFluff.runCommand(
finalArgs,
normalizedWorkingDirectory,
shouldUseStdin,
options,
command,
);
}

private static getTargetFileRelativePath(options: CommandOptions, normalizedWorkingDirectory: string | undefined) {
if (options.filePath) {
// We want to use relative path to the file so intermediate sqlfluff config files can be found
const normalizedFilePath = Utilities.normalizePath(options.filePath);
const targetFileRelativePath = normalizedWorkingDirectory
return normalizedWorkingDirectory
? Utilities.normalizePath(path.relative(normalizedWorkingDirectory, normalizedFilePath))
: normalizedFilePath;
finalArgs.push(targetFileRelativePath);
}
}

if (Configuration.dbtInterfaceEnabled() && command === CommandType.LINT) {
const dbtInterface = new DbtInterface(
shouldUseStdin ? options.fileContents : undefined,
options.workspacePath ?? options.filePath,
Configuration.config(),
);

Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n");
Utilities.outputChannel.appendLine(dbtInterface.getLintURL());
if (shouldUseStdin) {
Utilities.outputChannel.appendLine("\n-----Request Body-----\n");
if (options.fileContents) {
Utilities.outputChannel.appendLine(options.fileContents);
} else {
Utilities.outputChannel.appendLine("ERROR: File contents not found.");
}
private static async runDbtInterface(
shouldUseStdin: boolean,
options: CommandOptions,
): Promise<CommandOutput> {
const dbtInterface = new DbtInterface(
shouldUseStdin ? options.fileContents : undefined,
options.workspacePath ?? options.filePath,
Configuration.config(),
);

Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n");
Utilities.outputChannel.appendLine(dbtInterface.getLintURL());
if (shouldUseStdin) {
Utilities.outputChannel.appendLine("\n-----Request Body-----\n");
if (options.fileContents) {
Utilities.outputChannel.appendLine(options.fileContents);
} else {
Utilities.outputChannel.appendLine("ERROR: File contents not found.");
}
}

Utilities.appendHyphenatedLine();
Utilities.appendHyphenatedLine();

const response: any = await dbtInterface.lint();
const output: FilePath[] = [
{
filepath: options.filePath,
violations: response.result ?? [],
},
];
const response: any = await dbtInterface.lint();
const output: FilePath[] = [
{
filepath: options.filePath,
violations: response.result ?? [],
},
];

Utilities.outputChannel.appendLine("Raw dbt-omsosis /lint output:");
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2));
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine("Raw dbt-omsosis /lint output:");
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2));
Utilities.appendHyphenatedLine();

return new Promise<CommandOutput>((resolve) => {
const code = response?.error?.code ?? 0;
const succeeded = code === 0;
if (!succeeded && !Configuration.suppressNotifications()) {
const message = response?.error?.message ?? "DBT-Interface linting error.";
const detail = response?.error?.data?.error ?? "";
return new Promise<CommandOutput>((resolve) => {
const code = response?.error?.code ?? 0;
const succeeded = code === 0;
if (!succeeded && !Configuration.suppressNotifications()) {
const message = response?.error?.message ?? "DBT-Interface linting error.";
const detail = response?.error?.data?.error ?? "";

vscode.window.showErrorMessage([message, detail].join("\n"));
}
vscode.window.showErrorMessage([message, detail].join("\n"));
}

resolve({
resolve({
// 0 = all good, 1 = format passed but contains unfixable linting violations, 65 = lint passed but found errors
succeeded: succeeded,
lines: [JSON.stringify(output)],
});
succeeded: succeeded,
lines: [JSON.stringify(output)],
});
}
});
}

private static runCommand(
finalArgs: string[],
normalizedWorkingDirectory: string | undefined,
shouldUseStdin: boolean,
options: CommandOptions | undefined,
command: CommandType | undefined,
): Promise<CommandOutput> {
return new Promise<CommandOutput>((resolve) => {
const stdoutLint = new LineDecoder();
const stdoutFix: Buffer[] = [];
Expand Down Expand Up @@ -184,7 +226,7 @@ export default class SQLFluff {
childProcess.stdout.on("data", onStdoutDataEvent);
childProcess.stderr.on("data", onStderrDataEvent);
childProcess.on("close", (code, number) => onCloseEvent(code, number, childProcess));
if (shouldUseStdin) {
if (shouldUseStdin && options) {
childProcess.stdin.write(options.fileContents);
childProcess.stdin.end();
}
Expand Down Expand Up @@ -270,4 +312,17 @@ export default class SQLFluff {
}
});
}

static getCLIVersion() {
this.runCommand(["--version"], undefined, false, undefined, undefined).then(
(output) => {
const arr = output.lines[0]
.split("version ")[1]
.split(".", 3)
.map((s) => Number(s));
this.version = [arr[0], arr[1], arr[2]];
Utilities.outputChannel.appendLine(`sqlfluff version: ${this.version}`);
},
);
}
}

0 comments on commit e98ca58

Please sign in to comment.