Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCodeの設定UIからurborosql-fmtのオプションを指定できるようにする #52

Merged
merged 10 commits into from
May 2, 2024
Merged
5 changes: 5 additions & 0 deletions .changeset/strong-needles-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"uroborosql-fmt": minor
---

Added setting options to apply options of urborosql-fmt.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

174 changes: 174 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,179 @@
"uroborosql-fmt.configurationFilePath": {
"type": "string",
"description": "The path of configuration file. File extension must be `.json`. If you don't specify the path and `./.uroborosqlfmtrc.json` exists, formatter will use `./.uroborosqlfmtrc.json`. If you doesn't specify and `.uroborosqlfmtrc.json` doesn't exist, formatter will use formatters default configurations."
},
"uroborosql-fmt.debug": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"description": "Run in debug mode. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.tabSize": {
"type": [
"integer",
"null"
],
"minimum": 0,
"default": null,
"description": "Tab size used for formatting. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.complementAlias": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Complement aliases. Currently, column names are auto-completed with the same name. (e.g. `COL1` → `COL1 AS COL1`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.trimBindParam": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Trim the contents of the [bind parameters](https://future-architect.github.io/uroborosql-doc/background/#%E3%83%8F%E3%82%99%E3%82%A4%E3%83%B3%E3%83%88%E3%82%99%E3%83%8F%E3%82%9A%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF). (e.g. `/* foo */` → `/*foo*/`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.keywordCase": {
"type": [
"string",
"null"
],
"default": null,
"enum": [
"upper",
"lower",
"preserve"
],
"markdownDescription": "Unify the case of keywords. (No conversion in case of `\"preserve\"`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.identifierCase": {
"type": [
"string",
"null"
],
"default": null,
"enum": [
"upper",
"lower",
"preserve"
],
"markdownDescription": "Unify the case of identifiers. (No conversion in case of `\"preserve\"`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.maxCharPerLine": {
"type": [
"integer",
"null"
],
"default": null,
"markdownDescription": "If the total number of characters in the function name and arguments exceeds `max_char_per_line`, the arguments are formatted with new lines. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.complementOuterKeyword": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Complement the optional OUTER. (e.g. `LEFT JOIN` → `LEFT OUTER JOIN`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.complementColumnAsKeyword": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Complement `AS` in column aliases. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.removeTableAsKeyword": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Remove `AS` in table aliases. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.removeRedundantNest": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Remove redundant parentheses. (e.g. (`((foo))`) → `(foo)`) If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.complementSqlId": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"description": "Complement SQL ID. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.convertDoubleColonCast": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Convert casts by `X::type` to the form `CAST(X AS type)`. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
},
"uroborosql-fmt.unifyNotEqual": {
"type": [
"boolean",
"null"
],
"enum": [
true,
false,
null
],
"default": null,
"markdownDescription": "Convert comparison operator `<>` to `!=`. If this value is null, uroborosql-fmt refers the configuration file or uses the default value."
}
}
}
Expand Down Expand Up @@ -68,6 +241,7 @@
"eslint": "^8.50.0",
"mocha": "^10.2.0",
"prettier": "~3.2.0",
"ts-case-convert": "^2.0.7",
"typescript": "^5.2.2",
"undici": "^6.0.0"
}
Expand Down
3 changes: 1 addition & 2 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 54 additions & 11 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import {

import { TextDocument } from "vscode-languageserver-textdocument";

import { runfmt } from "uroborosql-fmt-napi";
import { runfmtWithSettings } from "uroborosql-fmt-napi";
import * as fs from "fs";

import { performance } from "perf_hooks";
import path = require("path");
import { URI } from "vscode-uri";
import { objectToSnake } from "ts-case-convert";
// Create a connection for the server, using Node's IPC as a transport.
// Also include all preview / proposed LSP features.
const connection = createConnection(ProposedFeatures.all);
Expand Down Expand Up @@ -89,6 +90,20 @@ connection.onInitialized(() => {

type ConfigurationSettings = {
configurationFilePath: string;
debug: boolean | null | undefined;
tabSize: number | null | undefined;
complementAlias: boolean | null | undefined;
trimBindParam: boolean | null | undefined;
keywordCase: string | null | undefined;
identifierCase: string | null | undefined;
maxCharPerLine: number | null | undefined;
complementOuterKeyword: boolean | null | undefined;
complementColumnAsKeyword: boolean | null | undefined;
removeTableAsKeyword: boolean | null | undefined;
removeRedundantNest: boolean | null | undefined;
complementSqlId: boolean | null | undefined;
convertDoubleColonCast: boolean | null | undefined;
unifyNotEqual: boolean | null | undefined;
};

function getSettings(resource: string): Thenable<ConfigurationSettings> {
Expand Down Expand Up @@ -129,21 +144,38 @@ async function getWorkspaceFolder(
return undefined;
}

async function determineConfigPath(
uri: string,
textDocument: TextDocument,
): Promise<string | null> {
const workspaceFolder: string | undefined =
await getWorkspaceFolder(textDocument);
function getVSCodeOptions(
settings: ConfigurationSettings,
workspaceFolder: string | undefined,
): Partial<ConfigurationSettings> | null {
if (!workspaceFolder) {
return null;
}

// remove configurationFilePath
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { configurationFilePath, ...restConfiguration } = settings;

// translate null (that means unsupecified option) to undefined
const removedNullSettings = Object.fromEntries(
Object.entries(restConfiguration).filter(([, value]) => value != null),
);

// to snake case for uroborosql-fmt
return objectToSnake(removedNullSettings);
}

function determineConfigPath(
settings: ConfigurationSettings,
workspaceFolder: string | undefined,
): string | null {
if (!workspaceFolder) {
return null;
}

// remove scheme
const workspaceFolderPath = URI.parse(workspaceFolder).fsPath;

const settings: ConfigurationSettings = await getSettings(uri);
if (!settings.configurationFilePath) {
const defaultConfigPath = path.join(
workspaceFolderPath,
Expand Down Expand Up @@ -179,10 +211,15 @@ async function formatText(
version: number,
selections: Range[],
): Promise<TextEdit[]> {
const workspaceFolder: string | undefined =
await getWorkspaceFolder(textDocument);

const settings: ConfigurationSettings = await getSettings(uri);

let configPath: string | null;

try {
configPath = await determineConfigPath(uri, textDocument);
configPath = determineConfigPath(settings, workspaceFolder);
} catch (e) {
if (e instanceof Error) {
connection.window.showErrorMessage(e.message);
Expand All @@ -196,6 +233,12 @@ async function formatText(
return [];
}

// settings specified by vscode ui
const specifiedSettings = getVSCodeOptions(settings, workspaceFolder);
const settingsString = specifiedSettings
? JSON.stringify(specifiedSettings)
: "{}";
console.log(settingsString);
const changes: TextEdit[] = [];

// 全ての選択範囲に対して実行
Expand All @@ -209,7 +252,7 @@ async function formatText(
let formattedText: string;

try {
formattedText = runfmt(text, configPath);
formattedText = runfmtWithSettings(text, settingsString, configPath);
// ステータスバーの背景を通常色に変更
connection.sendRequest("custom/normal", []);
} catch (e) {
Expand All @@ -230,7 +273,7 @@ async function formatText(
let formattedText: string;
const startTime = performance.now();
try {
formattedText = runfmt(text, configPath);
formattedText = runfmtWithSettings(text, settingsString, configPath);
// ステータスバーの背景を通常色に変更
connection.sendRequest("custom/normal", []);
} catch (e) {
Expand Down
Loading