diff --git a/vscode-extensions/vscode-spring-cli/package-lock.json b/vscode-extensions/vscode-spring-cli/package-lock.json index ebb2ffd20..0fc285f36 100644 --- a/vscode-extensions/vscode-spring-cli/package-lock.json +++ b/vscode-extensions/vscode-spring-cli/package-lock.json @@ -10,7 +10,8 @@ "license": "EPL-1.0", "dependencies": { "js-yaml": "^4.1.0", - "lodash.debounce": "^4.0.8" + "lodash.debounce": "^4.0.8", + "vscode-languageclient": "^9.0.1" }, "devDependencies": { "@types/js-yaml": "^4.0.9", @@ -156,8 +157,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -792,7 +792,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -1387,6 +1386,74 @@ "dev": true, "optional": true }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageclient/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1405,8 +1472,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yauzl": { "version": "2.10.0", @@ -1542,8 +1608,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -2008,7 +2073,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -2453,6 +2517,61 @@ "dev": true, "optional": true }, + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==" + }, + "vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "requires": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2468,8 +2587,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yauzl": { "version": "2.10.0", diff --git a/vscode-extensions/vscode-spring-cli/package.json b/vscode-extensions/vscode-spring-cli/package.json index 8c949baee..364119ce2 100644 --- a/vscode-extensions/vscode-spring-cli/package.json +++ b/vscode-extensions/vscode-spring-cli/package.json @@ -36,6 +36,11 @@ "when": "resourceFilename =~ /README-\\S+.md/", "command": "vscode-spring-cli.guide.apply", "group": "Spring-CLI" + }, + { + "when": "resourceFilename =~ /README-\\S+.md/", + "command": "vscode-spring-cli.guide.run", + "group": "Spring-CLI" } ], "explorer/context": [ @@ -48,6 +53,11 @@ "when": "resourceFilename =~ /README-\\S+.md/", "command": "vscode-spring-cli.guide.apply", "group": "Spring-CLI" + }, + { + "when": "resourceFilename =~ /README-\\S+.md/", + "command": "vscode-spring-cli.guide.run", + "group": "Spring-CLI" } ] }, @@ -111,6 +121,11 @@ "command": "vscode-spring-cli.guide.apply", "title": "Apply Guide", "category": "Spring CLI" + }, + { + "command": "vscode-spring-cli.guide.run", + "title": "Run Guide", + "category": "Spring CLI" } ], "configuration": { @@ -158,6 +173,7 @@ "vsce-pre-release-package": "vsce package --pre-release" }, "dependencies": { + "vscode-languageclient": "^9.0.1", "lodash.debounce": "^4.0.8", "js-yaml": "^4.1.0" }, diff --git a/vscode-extensions/vscode-spring-cli/src/cli.ts b/vscode-extensions/vscode-spring-cli/src/cli.ts index 60ac2c117..256dc7ead 100644 --- a/vscode-extensions/vscode-spring-cli/src/cli.ts +++ b/vscode-extensions/vscode-spring-cli/src/cli.ts @@ -6,6 +6,7 @@ import { getWorkspaceRoot } from "./utils"; import path from "path"; import fs from "fs"; import yaml from "js-yaml"; +import { WorkspaceEdit } from "vscode-languageclient"; export const SPRING_CLI_TASK_TYPE = 'spring-cli'; @@ -16,15 +17,15 @@ export class Cli { } projectList() : Promise { - return this.fetchJson("Fetching projects...", undefined, ["project", "list"]); + return this.fetchJson("Fetching projects...", undefined, ["project", "list", "--json"]); } projectCatalogList(): Promise { - return this.fetchJson("Fetching Catalogs...", undefined, ["project-catalog", "list"]); + return this.fetchJson("Fetching Catalogs...", undefined, ["project-catalog", "list", "--json"]); } projectCatalogListAvailable(): Promise { - return this.fetchJson("Fetching Available Catalogs...", undefined, ["project-catalog", "list-available"]); + return this.fetchJson("Fetching Available Catalogs...", undefined, ["project-catalog", "list-available", "--json"]); } guideApply(uri: Uri, cwd?: string) { @@ -37,6 +38,17 @@ export class Cli { return this.exec("Applying guide", uri.fsPath, args, cwd || path.dirname(uri.fsPath)); } + guideLspEdit(uri: Uri, cwd?: string): Promise { + const args = [ + "guide", + "apply", + "--lsp-edit", + "--file", + uri.fsPath + ]; + return this.fetchJson("Running guide", uri.fsPath, args, cwd || path.dirname(uri.fsPath)); + } + aiAdd(question: string, cwd: string): Thenable { const args = [ @@ -314,7 +326,7 @@ export class Cli { reject("Cancelled"); } const processOpts = { cwd: cwd || getWorkspaceRoot()?.fsPath || homedir() }; - const process = this.executable.endsWith(".jar") ? await cp.exec(`java -jar ${this.executable} ${args.join(" ")} --json`, processOpts) : await cp.exec(`${this.executable} ${args.join(" ")} --json`, processOpts); + const process = this.executable.endsWith(".jar") ? await cp.exec(`java -jar ${this.executable} ${args.join(" ")}`, processOpts) : await cp.exec(`${this.executable} ${args.join(" ")} --json`, processOpts); cancellation.onCancellationRequested(() => process.kill()); const dataChunks: string[] = []; process.stdout.on("data", s => dataChunks.push(s)); diff --git a/vscode-extensions/vscode-spring-cli/src/extension.ts b/vscode-extensions/vscode-spring-cli/src/extension.ts index cd3d36012..890bad08f 100644 --- a/vscode-extensions/vscode-spring-cli/src/extension.ts +++ b/vscode-extensions/vscode-spring-cli/src/extension.ts @@ -6,7 +6,7 @@ import { handleProjectAdd, handleProjectRemove } from "./project"; import { handleCommandAdd, handleCommandExecute, handleCommandNew, handleCommandRemove } from "./command"; import { ExtensionContext, commands, tasks } from "vscode"; import { handleAiAdd } from "./ai"; -import { handleGuideApply } from "./guide"; +import { handleGuideApply, handleGuideRun } from "./guide"; export const CLI = new Cli(); @@ -30,6 +30,7 @@ export async function activate(context: ExtensionContext): Promise { commands.registerCommand('vscode-spring-cli.ai.add', handleAiAdd), commands.registerCommand('vscode-spring-cli.guide.apply', handleGuideApply), + commands.registerCommand('vscode-spring-cli.guide.run', handleGuideRun), tasks.registerTaskProvider(SPRING_CLI_TASK_TYPE, new CliTaskProvider(CLI)) ); diff --git a/vscode-extensions/vscode-spring-cli/src/guide.ts b/vscode-extensions/vscode-spring-cli/src/guide.ts index 8bc180785..f38babfd5 100644 --- a/vscode-extensions/vscode-spring-cli/src/guide.ts +++ b/vscode-extensions/vscode-spring-cli/src/guide.ts @@ -1,10 +1,34 @@ -import { Uri } from "vscode"; +import { Uri, window, workspace } from "vscode"; import { getTargetGuideMardown } from "./utils"; import { CLI } from "./extension"; +import { createConverter } from "vscode-languageclient/lib/common/protocolConverter"; +import fs from "fs"; +const CONVERTER = createConverter(undefined, true, true); export async function handleGuideApply(uri: Uri) { if (!uri) { uri = await getTargetGuideMardown(); } return CLI.guideApply(uri); +} + +export async function handleGuideRun(uri: Uri) { + if (!uri) { + uri = await getTargetGuideMardown(); + } + const lspEdit = await CLI.guideLspEdit(uri); + const workspaceEdit = await CONVERTER.asWorkspaceEdit(lspEdit); + + // This is some sort of workaround for undo + // If editors for existing doc not opened then undo isn't properly working + await Promise.all(workspaceEdit.entries().map(async ([uri, edits]) => { + if (fs.existsSync(uri.fsPath)) { + const doc = await workspace.openTextDocument(uri.fsPath); + await window.showTextDocument(doc); + } + })); + + return await workspace.applyEdit(workspaceEdit, { + isRefactoring: true + }); } \ No newline at end of file