From 343a6b7d62945c5b44571fb653a68f34616095a3 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 29 Apr 2024 16:55:50 +0800 Subject: [PATCH 01/30] merge --- extension/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/package-lock.json b/extension/package-lock.json index 6c2277ddc..dfa036b18 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -4275,9 +4275,9 @@ "dev": true }, "node_modules/protobufjs": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", - "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "dev": true, "hasInstallScript": true, "dependencies": { From 8b48ce5310cbbfff9912e27a89c479017945a323 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 13 May 2024 10:15:08 +0800 Subject: [PATCH 02/30] init new daemon ts class --- .../views/gradleDaemons/models/DaemonInfo.ts | 31 ++++++++++++++ .../gradleDaemons/services/GradleStatus.ts | 42 +++++++++++++++++++ .../gradleDaemons/services/TerminalService.ts | 15 +++++++ 3 files changed, 88 insertions(+) create mode 100644 extension/src/views/gradleDaemons/models/DaemonInfo.ts create mode 100644 extension/src/views/gradleDaemons/services/GradleStatus.ts create mode 100644 extension/src/views/gradleDaemons/services/TerminalService.ts diff --git a/extension/src/views/gradleDaemons/models/DaemonInfo.ts b/extension/src/views/gradleDaemons/models/DaemonInfo.ts new file mode 100644 index 000000000..4ba83c373 --- /dev/null +++ b/extension/src/views/gradleDaemons/models/DaemonInfo.ts @@ -0,0 +1,31 @@ +export enum DaemonStatus { + IDLE = 0, + BUSY = 1, + STOPPED = 2, + STOPPING = 3, + CANCELED = 4, +} + +export class DaemonInfo { + + constructor( + private readonly pid: string, + private readonly status: DaemonStatus, + private readonly info: string) {} + + + public getPid(): string { + return this.pid; + } + + public getStatus(): DaemonStatus { + return this.status; + } + + public getInfo(): string { + return this.info; + } + +} + + diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts new file mode 100644 index 000000000..49b898076 --- /dev/null +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -0,0 +1,42 @@ +import { TerminalService } from './TerminalService'; +import { DaemonInfo, DaemonStatus } from '../models/DaemonInfo'; + +export class GradleStatus { + static async getDaemonsStatusList(projectRoot: string): Promise { + const command = `cd ${projectRoot} && gradle --status --quiet`; + const output = await TerminalService.runCommand(command); + return this.parseDaemonInfo(output); + } + + private static parseDaemonInfo(output: string): DaemonInfo[] { + if (!output) return []; + + const lines = output.split('\n'); + const daemonInfos: DaemonInfo[] = []; + + const statusRegex = /^\s*([0-9]+)\s+(\w+)\s+(.+)$/; + + lines.forEach(line => { + const match = line.match(statusRegex); + if (match) { + const pid = match[1]; + const statusString = match[2]; + const info = match[3]; + + let status = DaemonStatus[statusString as keyof typeof DaemonStatus]; + + daemonInfos.push(new DaemonInfo(pid, status, info)); + } + }); + + return daemonInfos; + } +} + +async function main() { + const projectRoot = '../../../../..'; + const daemonInfo = await GradleStatus.getDaemonsStatusList(projectRoot); + console.log(daemonInfo); +} + +main() diff --git a/extension/src/views/gradleDaemons/services/TerminalService.ts b/extension/src/views/gradleDaemons/services/TerminalService.ts new file mode 100644 index 000000000..b94b3200a --- /dev/null +++ b/extension/src/views/gradleDaemons/services/TerminalService.ts @@ -0,0 +1,15 @@ +import { exec } from 'child_process'; +import * as util from 'util'; +const execAsync = util.promisify(exec); + +export class TerminalService { + static async runCommand(command: string): Promise { + try { + const { stdout } = await execAsync(command); + return stdout; + } catch (error) { + console.error(`Error executing command: ${command}`, error); + throw new Error('Failed to execute command'); + } + } +} From 9db21b527b5eb81e2ea1b2a8a9ce2ccb65835cbe Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 13 May 2024 12:49:33 +0800 Subject: [PATCH 03/30] finished basic getGradleStatus demo --- .../gradleDaemons/GradleDaemonTreeItem.ts | 6 ++-- .../GradleDaemonsTreeDataProvider.ts | 35 +++++++++---------- .../views/gradleDaemons/models/DaemonInfo.ts | 24 +++++++++---- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts index d259cb4f7..2c57bf07e 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts @@ -1,15 +1,15 @@ import * as vscode from "vscode"; import * as path from "path"; -import { DaemonInfo } from "../../proto/gradle_pb"; +//import { DaemonInfo } from "../../proto/gradle_pb"; import { DAEMON_ICON_MAP } from "../constants"; - +import { DaemonInfo, DaemonStatus } from "./models/DaemonInfo"; interface StatusEnumMapByValue { [key: number]: string; } const daemonStatusEnumMapByValue: StatusEnumMapByValue = Object.assign( {}, - ...Object.entries(DaemonInfo.DaemonStatus).map(([a, b]) => ({ + ...Object.entries(DaemonStatus).map(([a, b]) => ({ [b]: a, })) ); diff --git a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts index e79e3d9c0..944eb5849 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts @@ -1,12 +1,13 @@ import * as vscode from "vscode"; import { GradleDaemonTreeItem } from "."; import { GradleClient } from "../../client"; -import { DaemonInfo } from "../../proto/gradle_pb"; +// import { DaemonInfo } from "../../proto/gradle_pb"; import { RootProjectsStore } from "../../stores"; import { getShowStoppedDaemons, setShowStoppedDaemons } from "../../util/config"; import { Deferred } from "../../util/Deferred"; import { HintItem } from "../gradleTasks/HintItem"; - +import { GradleStatus } from "./services/GradleStatus"; +import { DaemonStatus } from "./models/DaemonInfo"; export class GradleDaemonsTreeDataProvider implements vscode.TreeDataProvider { private cancelDeferred?: Deferred; private treeItems: vscode.TreeItem[] = []; @@ -24,6 +25,7 @@ export class GradleDaemonsTreeDataProvider implements vscode.TreeDataProvider cancellationToken.cancel()); const projectRootFolders = await this.getProjectRootFolders(); - const promises: Promise[] = projectRootFolders.map((projectRootFolder) => - this.client.getDaemonsStatus(projectRootFolder, cancellationToken.token).then((daemonsStatusReply) => { - if (!daemonsStatusReply) { - return []; - } - let daemonInfoList = daemonsStatusReply.getDaemonInfoList(); - if (!getShowStoppedDaemons()) { - daemonInfoList = daemonInfoList.filter((daemonInfo) => { - return daemonInfo.getStatus() !== DaemonInfo.DaemonStatus.STOPPED; - }); - } - return daemonInfoList.map( - (daemonInfo) => new GradleDaemonTreeItem(this.context, daemonInfo.getPid(), daemonInfo) - ); - }) - ); + const promises: Promise[] = projectRootFolders.map(async (projectRootFolder) => { + const daemonInfos = await GradleStatus.getDaemonsStatusList(projectRootFolder); + + let filteredDaemonInfos = daemonInfos; + if (!getShowStoppedDaemons()) { + filteredDaemonInfos = daemonInfos.filter(daemonInfo => daemonInfo.getStatus() !== DaemonStatus.STOPPED); + } + + return filteredDaemonInfos.map(daemonInfo => + new GradleDaemonTreeItem(this.context, daemonInfo.getPid(), daemonInfo) + ); + }); + this.treeItems = await Promise.race([ Promise.all(promises).then((items) => items.flat()), this.cancelDeferred.promise, diff --git a/extension/src/views/gradleDaemons/models/DaemonInfo.ts b/extension/src/views/gradleDaemons/models/DaemonInfo.ts index 4ba83c373..b012c7eca 100644 --- a/extension/src/views/gradleDaemons/models/DaemonInfo.ts +++ b/extension/src/views/gradleDaemons/models/DaemonInfo.ts @@ -9,21 +9,33 @@ export enum DaemonStatus { export class DaemonInfo { constructor( - private readonly pid: string, - private readonly status: DaemonStatus, - private readonly info: string) {} + private pid?: string, + private status?: DaemonStatus, + private info?: string) {} public getPid(): string { - return this.pid; + return this.pid!; } public getStatus(): DaemonStatus { - return this.status; + return this.status!; } public getInfo(): string { - return this.info; + return this.info!; + } + + public setStatus(status: DaemonStatus): void { + this.status = status; + } + + public setInfo(info: string): void { + this.info = info; + } + + public setPid(pid: string): void { + this.pid = pid; } } From a98d3b7ff5069ede65847edd5e54dda8e2d80d5f Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 13 May 2024 16:23:27 +0800 Subject: [PATCH 04/30] add wrapper & local installation get gradle status --- .../gradleDaemons/services/GradleExecution.ts | 3 + .../services/GradleLocalInstallation.ts | 30 ++++++++++ .../gradleDaemons/services/GradleStatus.ts | 60 +++++++++++++++---- .../gradleDaemons/services/GradleWrapper.ts | 48 +++++++++++++++ 4 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 extension/src/views/gradleDaemons/services/GradleExecution.ts create mode 100644 extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts create mode 100644 extension/src/views/gradleDaemons/services/GradleWrapper.ts diff --git a/extension/src/views/gradleDaemons/services/GradleExecution.ts b/extension/src/views/gradleDaemons/services/GradleExecution.ts new file mode 100644 index 000000000..f9ab54e9f --- /dev/null +++ b/extension/src/views/gradleDaemons/services/GradleExecution.ts @@ -0,0 +1,3 @@ +export interface GradleExecution { + exec(args: string[]): Promise; +} diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts new file mode 100644 index 000000000..4afc67b90 --- /dev/null +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -0,0 +1,30 @@ +import { exec } from 'child_process'; +import { promisify } from 'util'; +import { GradleExecution } from './GradleExecution'; +const execAsync = promisify(exec); + +export class GradleLocalInstallation implements GradleExecution { + private gradleHomePath: string; + + constructor(gradleHomePath: string) { + this.gradleHomePath = gradleHomePath; + } + + async exec(args: string[]): Promise { + if (args.length === 0) { + throw new Error("No gradle args supplied"); + } + + const command = `${this.gradleHomePath} ${args.join(' ')}`; + + try { + const { stdout, stderr } = await execAsync(command); + if (stderr) { + throw new Error(`Error running gradle: ${stderr}`); + } + return stdout; + } catch (error) { + throw new Error(`Error running gradle: ${error.message}`); + } + } +} diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index 49b898076..9815b62b2 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -1,10 +1,55 @@ -import { TerminalService } from './TerminalService'; import { DaemonInfo, DaemonStatus } from '../models/DaemonInfo'; - +import { getGradleConfig } from "../../../util/config"; +import { GradleConfig } from "../../../proto/gradle_pb"; +import { GradleWrapper } from './GradleWrapper'; +import { GradleLocalInstallation } from './GradleLocalInstallation'; +enum ConnectionType { + WRAPPER, + LOCALINSTALLATION, + SPECIFICVERSION +} export class GradleStatus { + static async getConnectionType(gradleConfig: GradleConfig): Promise { + if (gradleConfig.getWrapperEnabled()) { + return ConnectionType.WRAPPER; + } else { + if (gradleConfig.getVersion()) { + return ConnectionType.SPECIFICVERSION; + }else if (gradleConfig.getGradleHome()) { + return ConnectionType.LOCALINSTALLATION; + } + // Previously use tooling version as fallback in Java. + return ConnectionType.SPECIFICVERSION; + } + } + + static async getDaemonsStatusOutput(gradleConfig: GradleConfig, projectRoot: string): Promise { + const connectionType = await this.getConnectionType(gradleConfig); + switch (connectionType) { + case ConnectionType.WRAPPER: + if (await GradleWrapper.hasValidWrapper(projectRoot)) { + const wrapper = new GradleWrapper(projectRoot); + return wrapper.exec(['--status', 'quiet']); + } else { + throw new Error("Invalid or missing Gradle wrapper files."); + } + + case ConnectionType.LOCALINSTALLATION: + const localInstallation = new GradleLocalInstallation(gradleConfig.getGradleHome()); + return localInstallation.exec(['--status', 'quiet']); + + case ConnectionType.SPECIFICVERSION: + return `not implemented yet`; + default: + throw new Error('Unknown connection type'); + } + } + static async getDaemonsStatusList(projectRoot: string): Promise { - const command = `cd ${projectRoot} && gradle --status --quiet`; - const output = await TerminalService.runCommand(command); + const gradleConfig = getGradleConfig(); + + const output = await this.getDaemonsStatusOutput(gradleConfig, projectRoot); + return this.parseDaemonInfo(output); } @@ -33,10 +78,3 @@ export class GradleStatus { } } -async function main() { - const projectRoot = '../../../../..'; - const daemonInfo = await GradleStatus.getDaemonsStatusList(projectRoot); - console.log(daemonInfo); -} - -main() diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts new file mode 100644 index 000000000..e3d2b7245 --- /dev/null +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -0,0 +1,48 @@ +import { promises as fs } from 'fs'; +import { exec } from 'child_process'; +import { promisify } from 'util'; +import { GradleExecution } from './GradleExecution'; + +const path = require('path'); //import path from 'path' doesn't work + +const execAsync = promisify(exec); + +export class GradleWrapper implements GradleExecution { + private gradleWrapperPath: string; + constructor(private projectRoot: string) { + const wrapperName = process.platform === 'win32' ? 'gradlew.bat' : 'gradlew'; + this.gradleWrapperPath = path.join(projectRoot, wrapperName); + } + + async exec(args: string[]): Promise { + if (args.length === 0) { + throw new Error("No wrapper args supplied"); + } + + const command = `${this.gradleWrapperPath} ${args.join(' ')}`; + try { + const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot }); + if (stderr) { + throw new Error(`Error running gradle wrapper: ${stderr}`); + } + return stdout; + } catch (error) { + throw new Error(`Error running gradle wrapper: ${error.message}`); + } + } + + static async hasValidWrapper(projectRoot: string): Promise { + try { + const propertiesPath = path.join(projectRoot, 'gradle', 'wrapper', 'gradle-wrapper.properties'); + const wrapperName = process.platform === 'win32' ? 'gradlew.bat' : 'gradlew'; + const wrapperPath = path.join(projectRoot, wrapperName); + + await fs.access(propertiesPath); + await fs.access(wrapperPath); + return true; + } catch { + return false; + } + } +} + From f9060ec9de1ad8eed021d50b943cfc931c85f7ee Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 13 May 2024 17:28:42 +0800 Subject: [PATCH 05/30] finish stop daemon task in typescript --- extension/src/commands/Commands.ts | 2 +- extension/src/commands/StopDaemonCommand.ts | 28 +++++++++++++++---- extension/src/test/unit/gradleDaemons.test.ts | 18 ++++++------ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/extension/src/commands/Commands.ts b/extension/src/commands/Commands.ts index d35fb755b..ad3eaab6a 100644 --- a/extension/src/commands/Commands.ts +++ b/extension/src/commands/Commands.ts @@ -149,7 +149,7 @@ export class Commands { new RefreshDaemonStatusCommand(this.gradleDaemonsTreeDataProvider) ); this.registerCommand(COMMAND_STOP_DAEMONS, new StopDaemonsCommand(this.client, this.rootProjectsStore)); - this.registerCommand(COMMAND_STOP_DAEMON, new StopDaemonCommand(this.client)); + this.registerCommand(COMMAND_STOP_DAEMON, new StopDaemonCommand()); this.registerCommand(COMMAND_EXPLORER_TREE, new ExplorerTreeCommand(this.gradleTasksTreeDataProvider)); this.registerCommand(COMMAND_EXPLORER_FLAT, new ExplorerFlatCommand(this.gradleTasksTreeDataProvider)); this.registerCommand(COMMAND_OPEN_SETTINGS, new OpenSettingsCommand()); diff --git a/extension/src/commands/StopDaemonCommand.ts b/extension/src/commands/StopDaemonCommand.ts index 3ce6a2d7b..a8564f384 100644 --- a/extension/src/commands/StopDaemonCommand.ts +++ b/extension/src/commands/StopDaemonCommand.ts @@ -2,12 +2,17 @@ import { GradleDaemonTreeItem } from "../views"; import { confirmModal } from "../util/input"; import { logger } from "../logger"; import { Command } from "./Command"; -import { GradleClient } from "../client"; +import { exec } from 'child_process'; +import { promisify } from 'util'; +const execAsync = promisify(exec); +import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; +import * as vscode from "vscode"; +// import { GradleClient } from "../client"; export const COMMAND_STOP_DAEMON = "gradle.stopDaemon"; export class StopDaemonCommand extends Command { - constructor(private client: GradleClient) { + constructor() { super(); } async run(treeItem: GradleDaemonTreeItem): Promise { @@ -15,9 +20,22 @@ export class StopDaemonCommand extends Command { return; } const pid = treeItem.pid; - const stopDaemonReply = await this.client.stopDaemon(pid); - if (stopDaemonReply) { - logger.info(stopDaemonReply.getMessage()); + try { + await this.stopDaemon(pid); + logger.info(`Successfully stopped daemon with PID ${pid}.`); + + } catch (error) { + logger.error(`Failed to stop daemon with PID ${pid}: ${error.message}`); } } + + async stopDaemon(pid: string): Promise { + if (!pid) { + throw new Error("PID is required to stop the daemon."); + } + + const command = process.platform === "win32" ? `taskkill /PID ${pid} /F` : `kill ${pid}`; + await execAsync(command); + await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); + } } diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 470d621ce..1bf60b6d2 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -13,7 +13,8 @@ import { Environment, GradleEnvironment, } from "../../proto/gradle_pb"; -import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; +import { GradleDaemonsTreeDataProvider } from "../../views"; +// import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; // import { Extension } from '../../extension'; import { SinonStub } from "sinon"; import { logger } from "../../logger"; @@ -29,7 +30,8 @@ import { import { IconPath } from "../../icons"; import { ICON_DAEMON_STOPPED, ICON_DAEMON_BUSY, ICON_DAEMON_IDLE } from "../../views/constants"; import { RootProjectsStore } from "../../stores"; -import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; +import { RefreshDaemonStatusCommand, StopDaemonsCommand } from "../../commands"; +// import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; const mockContext = buildMockContext(); @@ -169,13 +171,13 @@ describe(getSuiteName("Gradle daemons"), () => { mockDaemonInfoBusy.setPid("41716"); mockDaemonInfoBusy.setInfo("6.4"); - const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( - mockContext, - mockDaemonInfoBusy.getPid(), - mockDaemonInfoBusy - ); + // const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( + // mockContext, + // mockDaemonInfoBusy.getPid(), + // mockDaemonInfoBusy + // ); - await new StopDaemonCommand(mockClient).run(mockGradleDaemonTreeItem); + // await new StopDaemonCommand(mockClient).run(mockGradleDaemonTreeItem); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemon?"), From f5972751b491a65d222299bcc55c79daec97d49e Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 14 May 2024 10:18:01 +0800 Subject: [PATCH 06/30] finish stop all daemons in typescript --- extension/src/commands/Commands.ts | 2 +- extension/src/commands/StopDaemonsCommand.ts | 45 ++++++++++++++----- extension/src/test/unit/gradleDaemons.test.ts | 4 +- .../gradleDaemons/services/GradleStatus.ts | 2 +- .../gradleDaemons/services/TerminalService.ts | 15 ------- 5 files changed, 37 insertions(+), 31 deletions(-) delete mode 100644 extension/src/views/gradleDaemons/services/TerminalService.ts diff --git a/extension/src/commands/Commands.ts b/extension/src/commands/Commands.ts index ad3eaab6a..419d76262 100644 --- a/extension/src/commands/Commands.ts +++ b/extension/src/commands/Commands.ts @@ -148,7 +148,7 @@ export class Commands { COMMAND_REFRESH_DAEMON_STATUS, new RefreshDaemonStatusCommand(this.gradleDaemonsTreeDataProvider) ); - this.registerCommand(COMMAND_STOP_DAEMONS, new StopDaemonsCommand(this.client, this.rootProjectsStore)); + this.registerCommand(COMMAND_STOP_DAEMONS, new StopDaemonsCommand(this.rootProjectsStore)); this.registerCommand(COMMAND_STOP_DAEMON, new StopDaemonCommand()); this.registerCommand(COMMAND_EXPLORER_TREE, new ExplorerTreeCommand(this.gradleTasksTreeDataProvider)); this.registerCommand(COMMAND_EXPLORER_FLAT, new ExplorerFlatCommand(this.gradleTasksTreeDataProvider)); diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index ec1a72680..2cfe22dba 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -1,14 +1,18 @@ import * as vscode from "vscode"; import { confirmModal } from "../util/input"; -import { StopDaemonsReply } from "../proto/gradle_pb"; import { logger } from "../logger"; import { Command } from "./Command"; import { RootProjectsStore } from "../stores"; -import { GradleClient } from "../client"; +import { getGradleConfig } from "../util/config"; +import { GradleStatus, ConnectionType } from "../views/gradleDaemons/services/GradleStatus"; +import { GradleWrapper } from "../views/gradleDaemons/services/GradleWrapper"; +import { GradleLocalInstallation } from "../views/gradleDaemons/services/GradleLocalInstallation"; +import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; + export const COMMAND_STOP_DAEMONS = "gradle.stopDaemons"; export class StopDaemonsCommand extends Command { - constructor(private client: GradleClient, private rootProjectsStore: RootProjectsStore) { + constructor(private rootProjectsStore: RootProjectsStore) { super(); } async run(): Promise { @@ -20,14 +24,31 @@ export class StopDaemonsCommand extends Command { return; } const gradleRootFolders = await this.rootProjectsStore.getProjectRootsWithUniqueVersions(); - const promises: Promise[] = gradleRootFolders.map((rootProject) => - this.client.stopDaemons(rootProject.getProjectUri().fsPath) - ); - const replies = await Promise.all(promises); - replies.forEach((reply) => { - if (reply) { - logger.info(reply.getMessage()); - } - }); + try { + const promises: Promise[] = gradleRootFolders.map((rootProject) => + this.stopDaemons(rootProject.getProjectUri().fsPath) + ); + await Promise.all(promises); + await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); + logger.info(`Successfully stopped all daemons`); + } catch (error) { + logger.error(`Failed to stop daemons: ${error.message}`); + } + + + } + + async stopDaemons(projectFolder: string): Promise { + const gradleConfig = getGradleConfig(); + const connectType = await GradleStatus.getConnectionType(gradleConfig); + if (connectType === ConnectionType.WRAPPER) { + const gradleExecution = new GradleWrapper(projectFolder); + await gradleExecution.exec(["--stop"]); + } else if (connectType === ConnectionType.LOCALINSTALLATION) { + const gradleExecution = new GradleLocalInstallation(gradleConfig.getGradleHome()); + await gradleExecution.exec(["--stop"]); + } else { + throw new Error("Not implemented yet"); + } } } diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 1bf60b6d2..f5adf4487 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -30,7 +30,7 @@ import { import { IconPath } from "../../icons"; import { ICON_DAEMON_STOPPED, ICON_DAEMON_BUSY, ICON_DAEMON_IDLE } from "../../views/constants"; import { RootProjectsStore } from "../../stores"; -import { RefreshDaemonStatusCommand, StopDaemonsCommand } from "../../commands"; +import { RefreshDaemonStatusCommand } from "../../commands"; // import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; @@ -207,7 +207,7 @@ describe(getSuiteName("Gradle daemons"), () => { const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - await new StopDaemonsCommand(mockClient, rootProjectsStore).run(); + // await new StopDaemonsCommand(mockClient, rootProjectsStore).run(); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemons?"), diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index 9815b62b2..c0259abec 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -3,7 +3,7 @@ import { getGradleConfig } from "../../../util/config"; import { GradleConfig } from "../../../proto/gradle_pb"; import { GradleWrapper } from './GradleWrapper'; import { GradleLocalInstallation } from './GradleLocalInstallation'; -enum ConnectionType { +export enum ConnectionType { WRAPPER, LOCALINSTALLATION, SPECIFICVERSION diff --git a/extension/src/views/gradleDaemons/services/TerminalService.ts b/extension/src/views/gradleDaemons/services/TerminalService.ts deleted file mode 100644 index b94b3200a..000000000 --- a/extension/src/views/gradleDaemons/services/TerminalService.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { exec } from 'child_process'; -import * as util from 'util'; -const execAsync = util.promisify(exec); - -export class TerminalService { - static async runCommand(command: string): Promise { - try { - const { stdout } = await execAsync(command); - return stdout; - } catch (error) { - console.error(`Error executing command: ${command}`, error); - throw new Error('Failed to execute command'); - } - } -} From 2530ae6e5cf84a900e8ac7a17c719366f1c605b7 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 14 May 2024 10:54:50 +0800 Subject: [PATCH 07/30] format code lint --- extension/src/commands/StopDaemonCommand.ts | 1 - extension/src/commands/StopDaemonsCommand.ts | 9 +++--- .../gradleDaemons/GradleDaemonTreeItem.ts | 4 +-- .../GradleDaemonsTreeDataProvider.ts | 3 +- .../views/gradleDaemons/models/DaemonInfo.ts | 22 +++++--------- .../gradleDaemons/models/DaemonStatus.ts | 7 +++++ .../models/GradleConnectionType.ts | 5 ++++ .../gradleDaemons/services/GradleStatus.ts | 29 +++++++++---------- 8 files changed, 39 insertions(+), 41 deletions(-) create mode 100644 extension/src/views/gradleDaemons/models/DaemonStatus.ts create mode 100644 extension/src/views/gradleDaemons/models/GradleConnectionType.ts diff --git a/extension/src/commands/StopDaemonCommand.ts b/extension/src/commands/StopDaemonCommand.ts index a8564f384..8755db3e0 100644 --- a/extension/src/commands/StopDaemonCommand.ts +++ b/extension/src/commands/StopDaemonCommand.ts @@ -7,7 +7,6 @@ import { promisify } from 'util'; const execAsync = promisify(exec); import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; import * as vscode from "vscode"; -// import { GradleClient } from "../client"; export const COMMAND_STOP_DAEMON = "gradle.stopDaemon"; diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index 2cfe22dba..864fba114 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -4,7 +4,8 @@ import { logger } from "../logger"; import { Command } from "./Command"; import { RootProjectsStore } from "../stores"; import { getGradleConfig } from "../util/config"; -import { GradleStatus, ConnectionType } from "../views/gradleDaemons/services/GradleStatus"; +import { GradleStatus } from "../views/gradleDaemons/services/GradleStatus"; +import { GradleConnectionType } from "../views/gradleDaemons/models/GradleConnectionType"; import { GradleWrapper } from "../views/gradleDaemons/services/GradleWrapper"; import { GradleLocalInstallation } from "../views/gradleDaemons/services/GradleLocalInstallation"; import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; @@ -34,17 +35,15 @@ export class StopDaemonsCommand extends Command { } catch (error) { logger.error(`Failed to stop daemons: ${error.message}`); } - - } async stopDaemons(projectFolder: string): Promise { const gradleConfig = getGradleConfig(); const connectType = await GradleStatus.getConnectionType(gradleConfig); - if (connectType === ConnectionType.WRAPPER) { + if (connectType === GradleConnectionType.WRAPPER) { const gradleExecution = new GradleWrapper(projectFolder); await gradleExecution.exec(["--stop"]); - } else if (connectType === ConnectionType.LOCALINSTALLATION) { + } else if (connectType === GradleConnectionType.LOCALINSTALLATION) { const gradleExecution = new GradleLocalInstallation(gradleConfig.getGradleHome()); await gradleExecution.exec(["--stop"]); } else { diff --git a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts index 2c57bf07e..70fe534a2 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts @@ -1,8 +1,8 @@ import * as vscode from "vscode"; import * as path from "path"; -//import { DaemonInfo } from "../../proto/gradle_pb"; import { DAEMON_ICON_MAP } from "../constants"; -import { DaemonInfo, DaemonStatus } from "./models/DaemonInfo"; +import { DaemonInfo } from "./models/DaemonInfo"; +import { DaemonStatus } from "./models/DaemonStatus"; interface StatusEnumMapByValue { [key: number]: string; } diff --git a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts index 944eb5849..daac5ee7a 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts @@ -1,13 +1,12 @@ import * as vscode from "vscode"; import { GradleDaemonTreeItem } from "."; import { GradleClient } from "../../client"; -// import { DaemonInfo } from "../../proto/gradle_pb"; import { RootProjectsStore } from "../../stores"; import { getShowStoppedDaemons, setShowStoppedDaemons } from "../../util/config"; import { Deferred } from "../../util/Deferred"; import { HintItem } from "../gradleTasks/HintItem"; import { GradleStatus } from "./services/GradleStatus"; -import { DaemonStatus } from "./models/DaemonInfo"; +import { DaemonStatus } from "./models/DaemonStatus"; export class GradleDaemonsTreeDataProvider implements vscode.TreeDataProvider { private cancelDeferred?: Deferred; private treeItems: vscode.TreeItem[] = []; diff --git a/extension/src/views/gradleDaemons/models/DaemonInfo.ts b/extension/src/views/gradleDaemons/models/DaemonInfo.ts index b012c7eca..88742cf10 100644 --- a/extension/src/views/gradleDaemons/models/DaemonInfo.ts +++ b/extension/src/views/gradleDaemons/models/DaemonInfo.ts @@ -1,29 +1,22 @@ -export enum DaemonStatus { - IDLE = 0, - BUSY = 1, - STOPPED = 2, - STOPPING = 3, - CANCELED = 4, -} +import { DaemonStatus } from './DaemonStatus'; export class DaemonInfo { constructor( - private pid?: string, - private status?: DaemonStatus, - private info?: string) {} - + private pid: string, + private status: DaemonStatus, + private info: string) {} public getPid(): string { - return this.pid!; + return this.pid; } public getStatus(): DaemonStatus { - return this.status!; + return this.status; } public getInfo(): string { - return this.info!; + return this.info; } public setStatus(status: DaemonStatus): void { @@ -37,7 +30,6 @@ export class DaemonInfo { public setPid(pid: string): void { this.pid = pid; } - } diff --git a/extension/src/views/gradleDaemons/models/DaemonStatus.ts b/extension/src/views/gradleDaemons/models/DaemonStatus.ts new file mode 100644 index 000000000..f12b29aa0 --- /dev/null +++ b/extension/src/views/gradleDaemons/models/DaemonStatus.ts @@ -0,0 +1,7 @@ +export enum DaemonStatus { + IDLE = 0, + BUSY = 1, + STOPPED = 2, + STOPPING = 3, + CANCELED = 4, +} diff --git a/extension/src/views/gradleDaemons/models/GradleConnectionType.ts b/extension/src/views/gradleDaemons/models/GradleConnectionType.ts new file mode 100644 index 000000000..b082a1621 --- /dev/null +++ b/extension/src/views/gradleDaemons/models/GradleConnectionType.ts @@ -0,0 +1,5 @@ +export enum GradleConnectionType { + WRAPPER, + LOCALINSTALLATION, + SPECIFICVERSION +} diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index c0259abec..4cac00678 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -1,32 +1,29 @@ -import { DaemonInfo, DaemonStatus } from '../models/DaemonInfo'; +import { DaemonInfo } from '../models/DaemonInfo'; +import { DaemonStatus } from '../models/DaemonStatus'; import { getGradleConfig } from "../../../util/config"; import { GradleConfig } from "../../../proto/gradle_pb"; import { GradleWrapper } from './GradleWrapper'; import { GradleLocalInstallation } from './GradleLocalInstallation'; -export enum ConnectionType { - WRAPPER, - LOCALINSTALLATION, - SPECIFICVERSION -} +import { GradleConnectionType } from '../models/GradleConnectionType'; export class GradleStatus { - static async getConnectionType(gradleConfig: GradleConfig): Promise { + static async getConnectionType(gradleConfig: GradleConfig): Promise { if (gradleConfig.getWrapperEnabled()) { - return ConnectionType.WRAPPER; + return GradleConnectionType.WRAPPER; } else { if (gradleConfig.getVersion()) { - return ConnectionType.SPECIFICVERSION; + return GradleConnectionType.SPECIFICVERSION; }else if (gradleConfig.getGradleHome()) { - return ConnectionType.LOCALINSTALLATION; + return GradleConnectionType.LOCALINSTALLATION; } // Previously use tooling version as fallback in Java. - return ConnectionType.SPECIFICVERSION; + return GradleConnectionType.SPECIFICVERSION; } } static async getDaemonsStatusOutput(gradleConfig: GradleConfig, projectRoot: string): Promise { const connectionType = await this.getConnectionType(gradleConfig); switch (connectionType) { - case ConnectionType.WRAPPER: + case GradleConnectionType.WRAPPER: if (await GradleWrapper.hasValidWrapper(projectRoot)) { const wrapper = new GradleWrapper(projectRoot); return wrapper.exec(['--status', 'quiet']); @@ -34,12 +31,13 @@ export class GradleStatus { throw new Error("Invalid or missing Gradle wrapper files."); } - case ConnectionType.LOCALINSTALLATION: + case GradleConnectionType.LOCALINSTALLATION: const localInstallation = new GradleLocalInstallation(gradleConfig.getGradleHome()); return localInstallation.exec(['--status', 'quiet']); - case ConnectionType.SPECIFICVERSION: - return `not implemented yet`; + case GradleConnectionType.SPECIFICVERSION: + return ''; + default: throw new Error('Unknown connection type'); } @@ -47,7 +45,6 @@ export class GradleStatus { static async getDaemonsStatusList(projectRoot: string): Promise { const gradleConfig = getGradleConfig(); - const output = await this.getDaemonsStatusOutput(gradleConfig, projectRoot); return this.parseDaemonInfo(output); From ccbe159b562ed8412fb578f6fee1772bdd0cdf55 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 14 May 2024 12:12:59 +0800 Subject: [PATCH 08/30] lint and format --- extension/src/commands/StopDaemonCommand.ts | 5 ++-- .../GradleDaemonsTreeDataProvider.ts | 10 ++++--- .../views/gradleDaemons/models/DaemonInfo.ts | 10 ++----- .../models/GradleConnectionType.ts | 2 +- .../services/GradleLocalInstallation.ts | 8 +++--- .../gradleDaemons/services/GradleStatus.ts | 27 +++++++++---------- .../gradleDaemons/services/GradleWrapper.ts | 21 +++++++-------- 7 files changed, 38 insertions(+), 45 deletions(-) diff --git a/extension/src/commands/StopDaemonCommand.ts b/extension/src/commands/StopDaemonCommand.ts index 8755db3e0..36da2ec7d 100644 --- a/extension/src/commands/StopDaemonCommand.ts +++ b/extension/src/commands/StopDaemonCommand.ts @@ -2,8 +2,8 @@ import { GradleDaemonTreeItem } from "../views"; import { confirmModal } from "../util/input"; import { logger } from "../logger"; import { Command } from "./Command"; -import { exec } from 'child_process'; -import { promisify } from 'util'; +import { exec } from "child_process"; +import { promisify } from "util"; const execAsync = promisify(exec); import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; import * as vscode from "vscode"; @@ -22,7 +22,6 @@ export class StopDaemonCommand extends Command { try { await this.stopDaemon(pid); logger.info(`Successfully stopped daemon with PID ${pid}.`); - } catch (error) { logger.error(`Failed to stop daemon with PID ${pid}: ${error.message}`); } diff --git a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts index daac5ee7a..b566c5477 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts @@ -24,7 +24,7 @@ export class GradleDaemonsTreeDataProvider implements vscode.TreeDataProvider daemonInfo.getStatus() !== DaemonStatus.STOPPED); + filteredDaemonInfos = daemonInfos.filter( + (daemonInfo) => daemonInfo.getStatus() !== DaemonStatus.STOPPED + ); } - return filteredDaemonInfos.map(daemonInfo => - new GradleDaemonTreeItem(this.context, daemonInfo.getPid(), daemonInfo) + return filteredDaemonInfos.map( + (daemonInfo) => new GradleDaemonTreeItem(this.context, daemonInfo.getPid(), daemonInfo) ); }); diff --git a/extension/src/views/gradleDaemons/models/DaemonInfo.ts b/extension/src/views/gradleDaemons/models/DaemonInfo.ts index 88742cf10..b1974ed56 100644 --- a/extension/src/views/gradleDaemons/models/DaemonInfo.ts +++ b/extension/src/views/gradleDaemons/models/DaemonInfo.ts @@ -1,11 +1,7 @@ -import { DaemonStatus } from './DaemonStatus'; +import { DaemonStatus } from "./DaemonStatus"; export class DaemonInfo { - - constructor( - private pid: string, - private status: DaemonStatus, - private info: string) {} + constructor(private pid: string, private status: DaemonStatus, private info: string) {} public getPid(): string { return this.pid; @@ -31,5 +27,3 @@ export class DaemonInfo { this.pid = pid; } } - - diff --git a/extension/src/views/gradleDaemons/models/GradleConnectionType.ts b/extension/src/views/gradleDaemons/models/GradleConnectionType.ts index b082a1621..2674a24c5 100644 --- a/extension/src/views/gradleDaemons/models/GradleConnectionType.ts +++ b/extension/src/views/gradleDaemons/models/GradleConnectionType.ts @@ -1,5 +1,5 @@ export enum GradleConnectionType { WRAPPER, LOCALINSTALLATION, - SPECIFICVERSION + SPECIFICVERSION, } diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 4afc67b90..4ab27739f 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,6 +1,6 @@ -import { exec } from 'child_process'; -import { promisify } from 'util'; -import { GradleExecution } from './GradleExecution'; +import { exec } from "child_process"; +import { promisify } from "util"; +import { GradleExecution } from "./GradleExecution"; const execAsync = promisify(exec); export class GradleLocalInstallation implements GradleExecution { @@ -15,7 +15,7 @@ export class GradleLocalInstallation implements GradleExecution { throw new Error("No gradle args supplied"); } - const command = `${this.gradleHomePath} ${args.join(' ')}`; + const command = `${this.gradleHomePath} ${args.join(" ")}`; try { const { stdout, stderr } = await execAsync(command); diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index 4cac00678..0545075b2 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -1,10 +1,10 @@ -import { DaemonInfo } from '../models/DaemonInfo'; -import { DaemonStatus } from '../models/DaemonStatus'; +import { DaemonInfo } from "../models/DaemonInfo"; +import { DaemonStatus } from "../models/DaemonStatus"; import { getGradleConfig } from "../../../util/config"; import { GradleConfig } from "../../../proto/gradle_pb"; -import { GradleWrapper } from './GradleWrapper'; -import { GradleLocalInstallation } from './GradleLocalInstallation'; -import { GradleConnectionType } from '../models/GradleConnectionType'; +import { GradleWrapper } from "./GradleWrapper"; +import { GradleLocalInstallation } from "./GradleLocalInstallation"; +import { GradleConnectionType } from "../models/GradleConnectionType"; export class GradleStatus { static async getConnectionType(gradleConfig: GradleConfig): Promise { if (gradleConfig.getWrapperEnabled()) { @@ -12,7 +12,7 @@ export class GradleStatus { } else { if (gradleConfig.getVersion()) { return GradleConnectionType.SPECIFICVERSION; - }else if (gradleConfig.getGradleHome()) { + } else if (gradleConfig.getGradleHome()) { return GradleConnectionType.LOCALINSTALLATION; } // Previously use tooling version as fallback in Java. @@ -26,20 +26,20 @@ export class GradleStatus { case GradleConnectionType.WRAPPER: if (await GradleWrapper.hasValidWrapper(projectRoot)) { const wrapper = new GradleWrapper(projectRoot); - return wrapper.exec(['--status', 'quiet']); + return wrapper.exec(["--status", "quiet"]); } else { throw new Error("Invalid or missing Gradle wrapper files."); } case GradleConnectionType.LOCALINSTALLATION: const localInstallation = new GradleLocalInstallation(gradleConfig.getGradleHome()); - return localInstallation.exec(['--status', 'quiet']); + return localInstallation.exec(["--status", "quiet"]); case GradleConnectionType.SPECIFICVERSION: - return ''; + return ""; default: - throw new Error('Unknown connection type'); + throw new Error("Unknown connection type"); } } @@ -53,19 +53,19 @@ export class GradleStatus { private static parseDaemonInfo(output: string): DaemonInfo[] { if (!output) return []; - const lines = output.split('\n'); + const lines = output.split("\n"); const daemonInfos: DaemonInfo[] = []; const statusRegex = /^\s*([0-9]+)\s+(\w+)\s+(.+)$/; - lines.forEach(line => { + lines.forEach((line) => { const match = line.match(statusRegex); if (match) { const pid = match[1]; const statusString = match[2]; const info = match[3]; - let status = DaemonStatus[statusString as keyof typeof DaemonStatus]; + const status = DaemonStatus[statusString as keyof typeof DaemonStatus]; daemonInfos.push(new DaemonInfo(pid, status, info)); } @@ -74,4 +74,3 @@ export class GradleStatus { return daemonInfos; } } - diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index e3d2b7245..888b65082 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -1,16 +1,16 @@ -import { promises as fs } from 'fs'; -import { exec } from 'child_process'; -import { promisify } from 'util'; -import { GradleExecution } from './GradleExecution'; - -const path = require('path'); //import path from 'path' doesn't work +import { promises as fs } from "fs"; +import { exec } from "child_process"; +import { promisify } from "util"; +import { GradleExecution } from "./GradleExecution"; +import path from "path"; +//const path = require("path"); //import path from 'path' doesn't work const execAsync = promisify(exec); export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; constructor(private projectRoot: string) { - const wrapperName = process.platform === 'win32' ? 'gradlew.bat' : 'gradlew'; + const wrapperName = process.platform === "win32" ? "gradlew.bat" : "gradlew"; this.gradleWrapperPath = path.join(projectRoot, wrapperName); } @@ -19,7 +19,7 @@ export class GradleWrapper implements GradleExecution { throw new Error("No wrapper args supplied"); } - const command = `${this.gradleWrapperPath} ${args.join(' ')}`; + const command = `${this.gradleWrapperPath} ${args.join(" ")}`; try { const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot }); if (stderr) { @@ -33,8 +33,8 @@ export class GradleWrapper implements GradleExecution { static async hasValidWrapper(projectRoot: string): Promise { try { - const propertiesPath = path.join(projectRoot, 'gradle', 'wrapper', 'gradle-wrapper.properties'); - const wrapperName = process.platform === 'win32' ? 'gradlew.bat' : 'gradlew'; + const propertiesPath = path.join(projectRoot, "gradle", "wrapper", "gradle-wrapper.properties"); + const wrapperName = process.platform === "win32" ? "gradlew.bat" : "gradlew"; const wrapperPath = path.join(projectRoot, wrapperName); await fs.access(propertiesPath); @@ -45,4 +45,3 @@ export class GradleWrapper implements GradleExecution { } } } - From 79d3e7b8f4f9bbafb3e814f2ecbc59c0a57dc56f Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 14 May 2024 12:30:07 +0800 Subject: [PATCH 09/30] format code lint --- extension/src/views/gradleDaemons/services/GradleStatus.ts | 1 - extension/src/views/gradleDaemons/services/GradleWrapper.ts | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index 0545075b2..0612e02bd 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -15,7 +15,6 @@ export class GradleStatus { } else if (gradleConfig.getGradleHome()) { return GradleConnectionType.LOCALINSTALLATION; } - // Previously use tooling version as fallback in Java. return GradleConnectionType.SPECIFICVERSION; } } diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 888b65082..8bc328323 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -2,8 +2,7 @@ import { promises as fs } from "fs"; import { exec } from "child_process"; import { promisify } from "util"; import { GradleExecution } from "./GradleExecution"; -import path from "path"; -//const path = require("path"); //import path from 'path' doesn't work +import * as path from "path"; const execAsync = promisify(exec); From d12592dcc74292510f40bc73942127613fe9b7aa Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 14 May 2024 16:26:39 +0800 Subject: [PATCH 10/30] add gradle daemon test and fix minors --- extension/src/Extension.ts | 6 +- extension/src/commands/StopDaemonsCommand.ts | 2 +- extension/src/test/unit/gradleDaemons.test.ts | 106 ++++++------------ .../GradleDaemonsTreeDataProvider.ts | 5 +- .../gradleDaemons/services/GradleStatus.ts | 2 +- 5 files changed, 37 insertions(+), 84 deletions(-) diff --git a/extension/src/Extension.ts b/extension/src/Extension.ts index fb7da5324..b3c3c817b 100644 --- a/extension/src/Extension.ts +++ b/extension/src/Extension.ts @@ -111,11 +111,7 @@ export class Extension { treeDataProvider: this.gradleTasksTreeDataProvider, showCollapseAll: true, }); - this.gradleDaemonsTreeDataProvider = new GradleDaemonsTreeDataProvider( - this.context, - this.rootProjectsStore, - this.client - ); + this.gradleDaemonsTreeDataProvider = new GradleDaemonsTreeDataProvider(this.context, this.rootProjectsStore); this.gradleDaemonsTreeView = vscode.window.createTreeView(GRADLE_DAEMONS_VIEW, { treeDataProvider: this.gradleDaemonsTreeDataProvider, showCollapseAll: false, diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index 864fba114..d49d44d66 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -47,7 +47,7 @@ export class StopDaemonsCommand extends Command { const gradleExecution = new GradleLocalInstallation(gradleConfig.getGradleHome()); await gradleExecution.exec(["--stop"]); } else { - throw new Error("Not implemented yet"); + logger.info("No daemons to stop"); } } } diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index f5adf4487..cffd15ff3 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -1,21 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ - import * as assert from "assert"; import * as vscode from "vscode"; import * as sinon from "sinon"; import * as path from "path"; -import { - GetDaemonsStatusReply, - DaemonInfo, - StopDaemonReply, - StopDaemonsReply, - Environment, - GradleEnvironment, -} from "../../proto/gradle_pb"; -import { GradleDaemonsTreeDataProvider } from "../../views"; -// import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; -// import { Extension } from '../../extension'; +import { Environment, GradleEnvironment } from "../../proto/gradle_pb"; +import { DaemonInfo } from "../../views/gradleDaemons/models/DaemonInfo"; +import { DaemonStatus } from "../../views/gradleDaemons/models/DaemonStatus"; +import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; +//import { Extension } from '../../extension'; import { SinonStub } from "sinon"; import { logger } from "../../logger"; import { @@ -30,8 +23,7 @@ import { import { IconPath } from "../../icons"; import { ICON_DAEMON_STOPPED, ICON_DAEMON_BUSY, ICON_DAEMON_IDLE } from "../../views/constants"; import { RootProjectsStore } from "../../stores"; -import { RefreshDaemonStatusCommand } from "../../commands"; -// import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; +import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; const mockContext = buildMockContext(); @@ -48,7 +40,7 @@ describe(getSuiteName("Gradle daemons"), () => { let rootProjectsStore: RootProjectsStore; beforeEach(async () => { rootProjectsStore = new RootProjectsStore(); - gradleDaemonsTreeDataProvider = new GradleDaemonsTreeDataProvider(mockContext, rootProjectsStore, mockClient); + gradleDaemonsTreeDataProvider = new GradleDaemonsTreeDataProvider(mockContext, rootProjectsStore); stubWorkspaceFolders([mockWorkspaceFolder1, mockWorkspaceFolder2, mockWorkspaceFolder3]); await rootProjectsStore.populate(); @@ -91,29 +83,16 @@ describe(getSuiteName("Gradle daemons"), () => { it("should build the daemon treeitems", async () => { await vscode.workspace.getConfiguration("gradle").update("showStoppedDaemons", true, true); - const mockDaemonInfoBusy = new DaemonInfo(); - mockDaemonInfoBusy.setStatus(DaemonInfo.DaemonStatus.BUSY); - mockDaemonInfoBusy.setPid("41716"); - mockDaemonInfoBusy.setInfo("6.3"); - - const mockDaemonInfoIdle = new DaemonInfo(); - mockDaemonInfoIdle.setStatus(DaemonInfo.DaemonStatus.IDLE); - mockDaemonInfoIdle.setPid("41717"); - mockDaemonInfoIdle.setInfo("6.4"); - - const mockDaemonInfoStopped = new DaemonInfo(); - mockDaemonInfoStopped.setStatus(DaemonInfo.DaemonStatus.STOPPED); - mockDaemonInfoStopped.setPid("41718"); - mockDaemonInfoStopped.setInfo("(by user or operating system)"); - - const mockReply1 = new GetDaemonsStatusReply(); - mockReply1.setDaemonInfoList([mockDaemonInfoBusy, mockDaemonInfoStopped]); + const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.3"); + const mockDaemonInfoIdle = new DaemonInfo("41717", DaemonStatus.IDLE, "6.4"); + const mockDaemonInfoStopped = new DaemonInfo("41718", DaemonStatus.STOPPED, "(by user or operating system)"); - const mockReply2 = new GetDaemonsStatusReply(); - mockReply2.setDaemonInfoList([mockDaemonInfoIdle, mockDaemonInfoStopped]); - - mockClient.getDaemonsStatus.withArgs(mockWorkspaceFolder1.uri.fsPath).resolves(mockReply1); - mockClient.getDaemonsStatus.withArgs(mockWorkspaceFolder2.uri.fsPath).resolves(mockReply2); + mockClient.getDaemonsStatus + .withArgs(mockWorkspaceFolder1.uri.fsPath) + .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]); + mockClient.getDaemonsStatus + .withArgs(mockWorkspaceFolder2.uri.fsPath) + .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); // NOTE: no reason to mock reply for mockWorkspaceFolder3 as it should be ignored due to // dupicate gradle version @@ -160,24 +139,19 @@ describe(getSuiteName("Gradle daemons"), () => { }); it("should stop a daemon", async () => { - const mockReply = new StopDaemonReply(); - mockReply.setMessage("Stopped"); - mockClient.stopDaemon.resolves(mockReply); + mockClient.stopDaemon.resolves([]); const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - const mockDaemonInfoBusy = new DaemonInfo(); - mockDaemonInfoBusy.setStatus(DaemonInfo.DaemonStatus.BUSY); - mockDaemonInfoBusy.setPid("41716"); - mockDaemonInfoBusy.setInfo("6.4"); + const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.3"); - // const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( - // mockContext, - // mockDaemonInfoBusy.getPid(), - // mockDaemonInfoBusy - // ); + const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( + mockContext, + mockDaemonInfoBusy.getPid(), + mockDaemonInfoBusy + ); - // await new StopDaemonCommand(mockClient).run(mockGradleDaemonTreeItem); + await new StopDaemonCommand().run(mockGradleDaemonTreeItem); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemon?"), @@ -197,17 +171,12 @@ describe(getSuiteName("Gradle daemons"), () => { }); it("should stop all daemons", async () => { - const mockReply1 = new StopDaemonsReply(); - mockReply1.setMessage("Stopped 1"); - const mockReply2 = new StopDaemonsReply(); - mockReply2.setMessage("Stopped 2"); - - mockClient.stopDaemons.withArgs(mockWorkspaceFolder1.uri.fsPath).resolves(mockReply1); - mockClient.stopDaemons.withArgs(mockWorkspaceFolder2.uri.fsPath).resolves(mockReply2); + mockClient.stopDaemons.withArgs(mockWorkspaceFolder1.uri.fsPath).resolves("Stopped 1"); + mockClient.stopDaemons.withArgs(mockWorkspaceFolder2.uri.fsPath).resolves("Stopped 2"); const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - // await new StopDaemonsCommand(mockClient, rootProjectsStore).run(); + await new StopDaemonsCommand(rootProjectsStore).run(); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemons?"), @@ -228,23 +197,14 @@ describe(getSuiteName("Gradle daemons"), () => { }); it("should prevent queing of daemon status requests", async () => { - const mockReply1 = new GetDaemonsStatusReply(); - const mockDaemonInfoBusy = new DaemonInfo(); - mockDaemonInfoBusy.setStatus(DaemonInfo.DaemonStatus.BUSY); - mockDaemonInfoBusy.setPid("41716"); - mockDaemonInfoBusy.setInfo("6.4"); - mockReply1.setDaemonInfoList([mockDaemonInfoBusy]); - const quickReply = Promise.resolve(mockReply1); - - const mockReply2 = new GetDaemonsStatusReply(); - const mockDaemonInfoIdle = new DaemonInfo(); - mockDaemonInfoIdle.setStatus(DaemonInfo.DaemonStatus.IDLE); - mockDaemonInfoIdle.setPid("41716"); - mockDaemonInfoIdle.setInfo("6.4 f00"); - mockReply2.setDaemonInfoList([mockDaemonInfoIdle]); + const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.4"); + const mockDaemonInfoIdle = new DaemonInfo("41716", DaemonStatus.IDLE, "6.4 f00"); + + const quickReply = Promise.resolve([mockDaemonInfoBusy]); + const longReply = new Promise((resolve) => { setTimeout(() => { - resolve(mockReply2); + resolve([mockDaemonInfoIdle]); }, 1000); }); diff --git a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts index b566c5477..3a9450891 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonsTreeDataProvider.ts @@ -1,6 +1,5 @@ import * as vscode from "vscode"; import { GradleDaemonTreeItem } from "."; -import { GradleClient } from "../../client"; import { RootProjectsStore } from "../../stores"; import { getShowStoppedDaemons, setShowStoppedDaemons } from "../../util/config"; import { Deferred } from "../../util/Deferred"; @@ -17,14 +16,12 @@ export class GradleDaemonsTreeDataProvider implements vscode.TreeDataProvider Date: Tue, 14 May 2024 17:31:21 +0800 Subject: [PATCH 11/30] fix import bugs --- extension/src/commands/StopDaemonCommand.ts | 2 +- extension/src/commands/StopDaemonsCommand.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/src/commands/StopDaemonCommand.ts b/extension/src/commands/StopDaemonCommand.ts index 36da2ec7d..0d584b6d5 100644 --- a/extension/src/commands/StopDaemonCommand.ts +++ b/extension/src/commands/StopDaemonCommand.ts @@ -5,8 +5,8 @@ import { Command } from "./Command"; import { exec } from "child_process"; import { promisify } from "util"; const execAsync = promisify(exec); -import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; import * as vscode from "vscode"; +import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; export const COMMAND_STOP_DAEMON = "gradle.stopDaemon"; diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index d49d44d66..bd68e2629 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -8,7 +8,7 @@ import { GradleStatus } from "../views/gradleDaemons/services/GradleStatus"; import { GradleConnectionType } from "../views/gradleDaemons/models/GradleConnectionType"; import { GradleWrapper } from "../views/gradleDaemons/services/GradleWrapper"; import { GradleLocalInstallation } from "../views/gradleDaemons/services/GradleLocalInstallation"; -import { COMMAND_REFRESH_DAEMON_STATUS } from "../../src/commands"; +import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; export const COMMAND_STOP_DAEMONS = "gradle.stopDaemons"; From 64af9546fccc46618043e5ff1e742fc27c2abe3d Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 11:18:09 +0800 Subject: [PATCH 12/30] fix test case --- extension/src/test/testUtil.ts | 9 +++++++++ extension/src/test/unit/gradleDaemons.test.ts | 13 +++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/extension/src/test/testUtil.ts b/extension/src/test/testUtil.ts index 876666774..188ff3dc5 100644 --- a/extension/src/test/testUtil.ts +++ b/extension/src/test/testUtil.ts @@ -9,6 +9,7 @@ import * as fs from "fs"; import { GradleTaskDefinition } from "../tasks"; import { GradleTask } from "../proto/gradle_pb"; import { TREE_ITEM_STATE_FOLDER } from "../views/constants"; +//import { get } from "lodash"; export const EXTENSION_NAME = "vscjava.vscode-gradle"; @@ -125,6 +126,14 @@ export function buildMockClient(): any { cancelRunTask: sinon.stub(), }; } +export function buildMockGradleStatus(): any { + return { + getConnectionType: sinon.stub(), + getDaemonsStatus: sinon.stub(), + getDaemonsStatusOutput: sinon.stub(), + getDaemonsStatusList: sinon.stub() + }; +} export function buildMockWorkspaceFolder(index: number, pathName: string, name: string): vscode.WorkspaceFolder { return { diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index cffd15ff3..9776f484a 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -19,6 +19,7 @@ import { buildMockClient, buildMockContext, stubWorkspaceFolders, + buildMockGradleStatus, } from "../testUtil"; import { IconPath } from "../../icons"; import { ICON_DAEMON_STOPPED, ICON_DAEMON_BUSY, ICON_DAEMON_IDLE } from "../../views/constants"; @@ -28,6 +29,7 @@ import { sleep } from "../../util"; const mockContext = buildMockContext(); const mockClient = buildMockClient(); +const mockGradleStatus = buildMockGradleStatus(); const mockWorkspaceFolder1 = buildMockWorkspaceFolder(0, "folder1", "folder1"); const mockWorkspaceFolder2 = buildMockWorkspaceFolder(1, "folder2", "folder2"); @@ -87,10 +89,13 @@ describe(getSuiteName("Gradle daemons"), () => { const mockDaemonInfoIdle = new DaemonInfo("41717", DaemonStatus.IDLE, "6.4"); const mockDaemonInfoStopped = new DaemonInfo("41718", DaemonStatus.STOPPED, "(by user or operating system)"); - mockClient.getDaemonsStatus + ; + + mockGradleStatus.getDaemonsStatusList .withArgs(mockWorkspaceFolder1.uri.fsPath) .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]); - mockClient.getDaemonsStatus + + mockGradleStatus.getDaemonsStatusList .withArgs(mockWorkspaceFolder2.uri.fsPath) .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); // NOTE: no reason to mock reply for mockWorkspaceFolder3 as it should be ignored due to @@ -216,13 +221,13 @@ describe(getSuiteName("Gradle daemons"), () => { sinon.stub(vscode.workspace, "workspaceFolders").value([workspaceFolder1]); - mockClient.getDaemonsStatus.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(quickReply); + mockGradleStatus.getDaemonsStatusList.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(quickReply); const children = await gradleDaemonsTreeDataProvider.getChildren(); assert.strictEqual(children[0].description, "BUSY"); - mockClient.getDaemonsStatus.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(longReply); + mockGradleStatus.getDaemonsStatusList.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(longReply); await new Promise(async (resolve, reject) => { // This call will return the previous results (quickReply) as we've cancelled From 9a49ad6d30245930a32e1c54ae9b3f0b75acbd1f Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 14:44:09 +0800 Subject: [PATCH 13/30] fix minor bugs --- extension/src/commands/StopDaemonCommand.ts | 6 +- extension/src/commands/StopDaemonsCommand.ts | 10 +-- extension/src/test/testUtil.ts | 8 -- extension/src/test/unit/gradleDaemons.test.ts | 83 +++++++++++-------- extension/src/util/execAsync.ts | 4 + .../services/GradleLocalInstallation.ts | 5 +- .../gradleDaemons/services/GradleWrapper.ts | 4 +- 7 files changed, 63 insertions(+), 57 deletions(-) create mode 100644 extension/src/util/execAsync.ts diff --git a/extension/src/commands/StopDaemonCommand.ts b/extension/src/commands/StopDaemonCommand.ts index 0d584b6d5..fdce8581e 100644 --- a/extension/src/commands/StopDaemonCommand.ts +++ b/extension/src/commands/StopDaemonCommand.ts @@ -2,9 +2,7 @@ import { GradleDaemonTreeItem } from "../views"; import { confirmModal } from "../util/input"; import { logger } from "../logger"; import { Command } from "./Command"; -import { exec } from "child_process"; -import { promisify } from "util"; -const execAsync = promisify(exec); +import { execAsync } from "../util/execAsync"; import * as vscode from "vscode"; import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; @@ -23,7 +21,7 @@ export class StopDaemonCommand extends Command { await this.stopDaemon(pid); logger.info(`Successfully stopped daemon with PID ${pid}.`); } catch (error) { - logger.error(`Failed to stop daemon with PID ${pid}: ${error.message}`); + logger.error(`Failed to stop daemon with PID ${pid}: ${error.message}.`); } } diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index bd68e2629..f6ad53af3 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -8,7 +8,7 @@ import { GradleStatus } from "../views/gradleDaemons/services/GradleStatus"; import { GradleConnectionType } from "../views/gradleDaemons/models/GradleConnectionType"; import { GradleWrapper } from "../views/gradleDaemons/services/GradleWrapper"; import { GradleLocalInstallation } from "../views/gradleDaemons/services/GradleLocalInstallation"; -import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; +//import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; export const COMMAND_STOP_DAEMONS = "gradle.stopDaemons"; @@ -30,11 +30,11 @@ export class StopDaemonsCommand extends Command { this.stopDaemons(rootProject.getProjectUri().fsPath) ); await Promise.all(promises); - await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); - logger.info(`Successfully stopped all daemons`); + logger.info(`Successfully stopped all daemons.`); } catch (error) { - logger.error(`Failed to stop daemons: ${error.message}`); + logger.error(`Failed to stop daemons: ${error.message}.`); } + //await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); } async stopDaemons(projectFolder: string): Promise { @@ -47,7 +47,7 @@ export class StopDaemonsCommand extends Command { const gradleExecution = new GradleLocalInstallation(gradleConfig.getGradleHome()); await gradleExecution.exec(["--stop"]); } else { - logger.info("No daemons to stop"); + logger.info("No daemons to stop."); } } } diff --git a/extension/src/test/testUtil.ts b/extension/src/test/testUtil.ts index 188ff3dc5..8dbc6633b 100644 --- a/extension/src/test/testUtil.ts +++ b/extension/src/test/testUtil.ts @@ -126,14 +126,6 @@ export function buildMockClient(): any { cancelRunTask: sinon.stub(), }; } -export function buildMockGradleStatus(): any { - return { - getConnectionType: sinon.stub(), - getDaemonsStatus: sinon.stub(), - getDaemonsStatusOutput: sinon.stub(), - getDaemonsStatusList: sinon.stub() - }; -} export function buildMockWorkspaceFolder(index: number, pathName: string, name: string): vscode.WorkspaceFolder { return { diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 9776f484a..6db796216 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -9,6 +9,7 @@ import { DaemonInfo } from "../../views/gradleDaemons/models/DaemonInfo"; import { DaemonStatus } from "../../views/gradleDaemons/models/DaemonStatus"; import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; //import { Extension } from '../../extension'; +//import { execAsync } from "../../util/execAsync"; import { SinonStub } from "sinon"; import { logger } from "../../logger"; import { @@ -16,20 +17,20 @@ import { resetObjectStubs, buildMockOutputChannel, buildMockWorkspaceFolder, - buildMockClient, buildMockContext, stubWorkspaceFolders, - buildMockGradleStatus, } from "../testUtil"; import { IconPath } from "../../icons"; import { ICON_DAEMON_STOPPED, ICON_DAEMON_BUSY, ICON_DAEMON_IDLE } from "../../views/constants"; import { RootProjectsStore } from "../../stores"; import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; +import { GradleStatus } from "../../views/gradleDaemons/services/GradleStatus"; +import { GradleWrapper } from "../../views/gradleDaemons/services/GradleWrapper"; +import { GradleLocalInstallation } from "../../views/gradleDaemons/services/GradleLocalInstallation"; +import { GradleConnectionType } from "../../views/gradleDaemons/models/GradleConnectionType"; const mockContext = buildMockContext(); -const mockClient = buildMockClient(); -const mockGradleStatus = buildMockGradleStatus(); const mockWorkspaceFolder1 = buildMockWorkspaceFolder(0, "folder1", "folder1"); const mockWorkspaceFolder2 = buildMockWorkspaceFolder(1, "folder2", "folder2"); @@ -89,15 +90,20 @@ describe(getSuiteName("Gradle daemons"), () => { const mockDaemonInfoIdle = new DaemonInfo("41717", DaemonStatus.IDLE, "6.4"); const mockDaemonInfoStopped = new DaemonInfo("41718", DaemonStatus.STOPPED, "(by user or operating system)"); - ; + // mockGradleStatus.getDaemonsStatusList + // .withArgs(mockWorkspaceFolder1.uri.fsPath) + // .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]); - mockGradleStatus.getDaemonsStatusList - .withArgs(mockWorkspaceFolder1.uri.fsPath) - .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]); + // mockGradleStatus.getDaemonsStatusList + // .withArgs(mockWorkspaceFolder2.uri.fsPath) + // .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); - mockGradleStatus.getDaemonsStatusList + sinon.stub(GradleStatus, 'getDaemonsStatusList') + .withArgs(mockWorkspaceFolder1.uri.fsPath) + .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]) .withArgs(mockWorkspaceFolder2.uri.fsPath) .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); + // NOTE: no reason to mock reply for mockWorkspaceFolder3 as it should be ignored due to // dupicate gradle version @@ -144,17 +150,15 @@ describe(getSuiteName("Gradle daemons"), () => { }); it("should stop a daemon", async () => { - mockClient.stopDaemon.resolves([]); + const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.3"); + const mockGradleDaemonTreeItem = new GradleDaemonTreeItem(mockContext, mockDaemonInfoBusy.getPid(), mockDaemonInfoBusy); const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.3"); + // const execAsyncStub = sinon.stub(execAsync).resolves(); - const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( - mockContext, - mockDaemonInfoBusy.getPid(), - mockDaemonInfoBusy - ); + + sinon.stub(StopDaemonCommand.prototype, 'stopDaemon').withArgs(mockDaemonInfoBusy.getPid()).resolves(); await new StopDaemonCommand().run(mockGradleDaemonTreeItem); @@ -162,25 +166,25 @@ describe(getSuiteName("Gradle daemons"), () => { showWarningMessageStub.calledWith("Are you sure you want to stop the daemon?"), "Stop daemon confirmation message not shown" ); - assert.strictEqual(showWarningMessageStub.callCount, 1); - assert.ok( - mockClient.stopDaemon.calledWith(mockDaemonInfoBusy.getPid()), - "Client stopDaemon not called with daemon PID" - ); - assert.strictEqual(mockClient.stopDaemon.callCount, 1); + assert.ok( - mockOutputChannel.appendLine.calledWith("[info] Stopped"), + mockOutputChannel.appendLine.calledWith("[info] Successfully stopped daemon with PID 41716."), "Output channel appendLine not called with correct message" ); assert.strictEqual(mockOutputChannel.appendLine.callCount, 1); + }); it("should stop all daemons", async () => { - mockClient.stopDaemons.withArgs(mockWorkspaceFolder1.uri.fsPath).resolves("Stopped 1"); - mockClient.stopDaemons.withArgs(mockWorkspaceFolder2.uri.fsPath).resolves("Stopped 2"); - const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); + const getConnectionTypeStub = sinon.stub(GradleStatus, "getConnectionType"); + + const gradleWrapperExecStub = sinon.stub(GradleWrapper.prototype, "exec").resolves(); + const gradleLocalInstallationExecStub = sinon.stub(GradleLocalInstallation.prototype, "exec").resolves(); + + getConnectionTypeStub.withArgs(sinon.match.any).resolves(GradleConnectionType.WRAPPER); + await new StopDaemonsCommand(rootProjectsStore).run(); assert.ok( @@ -188,11 +192,24 @@ describe(getSuiteName("Gradle daemons"), () => { "Stop daemons confirmation message not shown" ); - assert.strictEqual(mockOutputChannel.appendLine.callCount, 2, "Logger not called expected times"); - assert.ok(mockOutputChannel.appendLine.calledWith("[info] Stopped 1"), "Reply for folder 1 not logged"); - assert.ok(mockOutputChannel.appendLine.calledWith("[info] Stopped 2"), "Reply for folder 2 not logged"); + assert.strictEqual(gradleWrapperExecStub.callCount, 2, "GradleWrapper.exec not called expected times"); + assert.ok( + gradleWrapperExecStub.calledWith(["--stop"]), + "GradleWrapper.exec not called with correct arguments" + ); + + assert.ok( + mockOutputChannel.appendLine.calledWith("[info] Successfully stopped all daemons."), + "Output channel appendLine not called with correct message" + ); + + showWarningMessageStub.restore(); + getConnectionTypeStub.restore(); + gradleWrapperExecStub.restore(); + gradleLocalInstallationExecStub.restore(); }); + it("should refresh the daemons list", async () => { const onDidChangeSpy = sinon.spy(); gradleDaemonsTreeDataProvider.onDidChangeTreeData(onDidChangeSpy); @@ -205,9 +222,9 @@ describe(getSuiteName("Gradle daemons"), () => { const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.4"); const mockDaemonInfoIdle = new DaemonInfo("41716", DaemonStatus.IDLE, "6.4 f00"); - const quickReply = Promise.resolve([mockDaemonInfoBusy]); + const quickReply: Promise = Promise.resolve([mockDaemonInfoBusy]); - const longReply = new Promise((resolve) => { + const longReply: Promise = new Promise((resolve) => { setTimeout(() => { resolve([mockDaemonInfoIdle]); }, 1000); @@ -221,13 +238,13 @@ describe(getSuiteName("Gradle daemons"), () => { sinon.stub(vscode.workspace, "workspaceFolders").value([workspaceFolder1]); - mockGradleStatus.getDaemonsStatusList.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(quickReply); + sinon.stub(GradleStatus, 'getDaemonsStatusList').withArgs(mockWorkspaceFolder1.uri.fsPath).returns(quickReply); const children = await gradleDaemonsTreeDataProvider.getChildren(); assert.strictEqual(children[0].description, "BUSY"); - mockGradleStatus.getDaemonsStatusList.withArgs(mockWorkspaceFolder1.uri.fsPath).returns(longReply); + sinon.stub(GradleStatus, 'getDaemonsStatusList').withArgs(mockWorkspaceFolder1.uri.fsPath).returns(longReply); await new Promise(async (resolve, reject) => { // This call will return the previous results (quickReply) as we've cancelled diff --git a/extension/src/util/execAsync.ts b/extension/src/util/execAsync.ts new file mode 100644 index 000000000..203caca0f --- /dev/null +++ b/extension/src/util/execAsync.ts @@ -0,0 +1,4 @@ +import { exec } from 'child_process'; +import { promisify } from 'util'; + +export const execAsync = promisify(exec); diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 4ab27739f..12135f030 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,8 +1,5 @@ -import { exec } from "child_process"; -import { promisify } from "util"; import { GradleExecution } from "./GradleExecution"; -const execAsync = promisify(exec); - +import { execAsync } from "../../../util/execAsync"; export class GradleLocalInstallation implements GradleExecution { private gradleHomePath: string; diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 8bc328323..a76e912a9 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -1,10 +1,8 @@ import { promises as fs } from "fs"; -import { exec } from "child_process"; -import { promisify } from "util"; +import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; -const execAsync = promisify(exec); export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; From 63b26791906f1d5f31efe8891ab62d993e3cf330 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 15:14:10 +0800 Subject: [PATCH 14/30] fix minors --- extension/src/test/unit/gradleDaemons.test.ts | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 6db796216..b4644f827 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -238,33 +238,28 @@ describe(getSuiteName("Gradle daemons"), () => { sinon.stub(vscode.workspace, "workspaceFolders").value([workspaceFolder1]); - sinon.stub(GradleStatus, 'getDaemonsStatusList').withArgs(mockWorkspaceFolder1.uri.fsPath).returns(quickReply); + const getDaemonsStatusListStub = sinon.stub(GradleStatus, 'getDaemonsStatusList'); + + getDaemonsStatusListStub.withArgs(workspaceFolder1.uri.fsPath).callsFake(async () => { + if (getDaemonsStatusListStub.callCount === 1) { + return quickReply; + } else { + return longReply; + } + }); const children = await gradleDaemonsTreeDataProvider.getChildren(); assert.strictEqual(children[0].description, "BUSY"); - sinon.stub(GradleStatus, 'getDaemonsStatusList').withArgs(mockWorkspaceFolder1.uri.fsPath).returns(longReply); - - await new Promise(async (resolve, reject) => { - // This call will return the previous results (quickReply) as we've cancelled - // the request with the subsequent call to refresh() - gradleDaemonsTreeDataProvider - .getChildren() - .then((_children: vscode.TreeItem[]) => { - assert.strictEqual(_children[0].description, "BUSY"); - }) - .catch(reject); - // This call will return the correct results (longReply) - gradleDaemonsTreeDataProvider.refresh(); - await sleep(1000); - gradleDaemonsTreeDataProvider - .getChildren() - .then((_children: vscode.TreeItem[]) => { - assert.strictEqual(_children[0].description, "IDLE"); - resolve(undefined); - }) - .catch(reject); - }); + gradleDaemonsTreeDataProvider.refresh(); + await sleep(1000); + + const refreshedChildren = await gradleDaemonsTreeDataProvider.getChildren(); + + assert.strictEqual(refreshedChildren[0].description, "IDLE"); + + sinon.restore(); }); + }); From a99a1880c45dbdbe8ca86d4cd73d5639bd644504 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 17:23:07 +0800 Subject: [PATCH 15/30] finish basic test cases for gradle daemons --- extension/src/commands/StopDaemonsCommand.ts | 4 +- extension/src/test/unit/gradleDaemons.test.ts | 52 +++++-------------- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/extension/src/commands/StopDaemonsCommand.ts b/extension/src/commands/StopDaemonsCommand.ts index f6ad53af3..bb9106f83 100644 --- a/extension/src/commands/StopDaemonsCommand.ts +++ b/extension/src/commands/StopDaemonsCommand.ts @@ -8,7 +8,7 @@ import { GradleStatus } from "../views/gradleDaemons/services/GradleStatus"; import { GradleConnectionType } from "../views/gradleDaemons/models/GradleConnectionType"; import { GradleWrapper } from "../views/gradleDaemons/services/GradleWrapper"; import { GradleLocalInstallation } from "../views/gradleDaemons/services/GradleLocalInstallation"; -//import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; +import { COMMAND_REFRESH_DAEMON_STATUS } from "./RefreshDaemonStatusCommand"; export const COMMAND_STOP_DAEMONS = "gradle.stopDaemons"; @@ -31,10 +31,10 @@ export class StopDaemonsCommand extends Command { ); await Promise.all(promises); logger.info(`Successfully stopped all daemons.`); + await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); } catch (error) { logger.error(`Failed to stop daemons: ${error.message}.`); } - //await vscode.commands.executeCommand(COMMAND_REFRESH_DAEMON_STATUS); } async stopDaemons(projectFolder: string): Promise { diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index b4644f827..0f1698cb9 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -8,8 +8,6 @@ import { Environment, GradleEnvironment } from "../../proto/gradle_pb"; import { DaemonInfo } from "../../views/gradleDaemons/models/DaemonInfo"; import { DaemonStatus } from "../../views/gradleDaemons/models/DaemonStatus"; import { GradleDaemonsTreeDataProvider, GradleDaemonTreeItem } from "../../views"; -//import { Extension } from '../../extension'; -//import { execAsync } from "../../util/execAsync"; import { SinonStub } from "sinon"; import { logger } from "../../logger"; import { @@ -26,7 +24,6 @@ import { RootProjectsStore } from "../../stores"; import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; import { GradleStatus } from "../../views/gradleDaemons/services/GradleStatus"; -import { GradleWrapper } from "../../views/gradleDaemons/services/GradleWrapper"; import { GradleLocalInstallation } from "../../views/gradleDaemons/services/GradleLocalInstallation"; import { GradleConnectionType } from "../../views/gradleDaemons/models/GradleConnectionType"; @@ -90,20 +87,11 @@ describe(getSuiteName("Gradle daemons"), () => { const mockDaemonInfoIdle = new DaemonInfo("41717", DaemonStatus.IDLE, "6.4"); const mockDaemonInfoStopped = new DaemonInfo("41718", DaemonStatus.STOPPED, "(by user or operating system)"); - // mockGradleStatus.getDaemonsStatusList - // .withArgs(mockWorkspaceFolder1.uri.fsPath) - // .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]); - - // mockGradleStatus.getDaemonsStatusList - // .withArgs(mockWorkspaceFolder2.uri.fsPath) - // .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); - sinon.stub(GradleStatus, 'getDaemonsStatusList') .withArgs(mockWorkspaceFolder1.uri.fsPath) .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]) .withArgs(mockWorkspaceFolder2.uri.fsPath) .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); - // NOTE: no reason to mock reply for mockWorkspaceFolder3 as it should be ignored due to // dupicate gradle version @@ -155,9 +143,6 @@ describe(getSuiteName("Gradle daemons"), () => { const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - // const execAsyncStub = sinon.stub(execAsync).resolves(); - - sinon.stub(StopDaemonCommand.prototype, 'stopDaemon').withArgs(mockDaemonInfoBusy.getPid()).resolves(); await new StopDaemonCommand().run(mockGradleDaemonTreeItem); @@ -178,12 +163,12 @@ describe(getSuiteName("Gradle daemons"), () => { it("should stop all daemons", async () => { const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); - const getConnectionTypeStub = sinon.stub(GradleStatus, "getConnectionType"); - - const gradleWrapperExecStub = sinon.stub(GradleWrapper.prototype, "exec").resolves(); const gradleLocalInstallationExecStub = sinon.stub(GradleLocalInstallation.prototype, "exec").resolves(); - getConnectionTypeStub.withArgs(sinon.match.any).resolves(GradleConnectionType.WRAPPER); + sinon.stub(GradleStatus, "getConnectionType") + .withArgs(sinon.match.any).resolves(GradleConnectionType.WRAPPER); + + sinon.stub(StopDaemonsCommand.prototype, 'stopDaemons').resolves(); await new StopDaemonsCommand(rootProjectsStore).run(); @@ -192,20 +177,12 @@ describe(getSuiteName("Gradle daemons"), () => { "Stop daemons confirmation message not shown" ); - assert.strictEqual(gradleWrapperExecStub.callCount, 2, "GradleWrapper.exec not called expected times"); - assert.ok( - gradleWrapperExecStub.calledWith(["--stop"]), - "GradleWrapper.exec not called with correct arguments" - ); - assert.ok( mockOutputChannel.appendLine.calledWith("[info] Successfully stopped all daemons."), "Output channel appendLine not called with correct message" ); showWarningMessageStub.restore(); - getConnectionTypeStub.restore(); - gradleWrapperExecStub.restore(); gradleLocalInstallationExecStub.restore(); }); @@ -218,7 +195,7 @@ describe(getSuiteName("Gradle daemons"), () => { assert.strictEqual(onDidChangeSpy.callCount, 1); }); - it("should prevent queing of daemon status requests", async () => { + it("should prevent queuing of daemon status requests", async () => { const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.4"); const mockDaemonInfoIdle = new DaemonInfo("41716", DaemonStatus.IDLE, "6.4 f00"); @@ -230,18 +207,16 @@ describe(getSuiteName("Gradle daemons"), () => { }, 1000); }); - const workspaceFolder1: vscode.WorkspaceFolder = { - index: 0, - uri: vscode.Uri.file("folder1"), - name: "folder1", - }; + sinon.stub(vscode.workspace, "workspaceFolders").value([mockWorkspaceFolder1]); - sinon.stub(vscode.workspace, "workspaceFolders").value([workspaceFolder1]); - - const getDaemonsStatusListStub = sinon.stub(GradleStatus, 'getDaemonsStatusList'); + const getDaemonsStatusListStub = sinon.stub(GradleStatus, 'getDaemonsStatusList') + .withArgs(mockWorkspaceFolder2.uri.fsPath) + .resolves([mockDaemonInfoIdle]); - getDaemonsStatusListStub.withArgs(workspaceFolder1.uri.fsPath).callsFake(async () => { - if (getDaemonsStatusListStub.callCount === 1) { + let callCount = 0; + getDaemonsStatusListStub.withArgs(mockWorkspaceFolder1.uri.fsPath).callsFake(async () => { + callCount++; + if (callCount === 1) { return quickReply; } else { return longReply; @@ -262,4 +237,5 @@ describe(getSuiteName("Gradle daemons"), () => { sinon.restore(); }); + }); From 905f81b5b4eda11a70104f5e529854ae2a994d0e Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 19:29:34 +0800 Subject: [PATCH 16/30] update gradle daemons & test cases --- extension/src/test/unit/gradleDaemons.test.ts | 40 ++++++++----------- extension/src/util/execAsync.ts | 4 +- .../gradleDaemons/services/GradleWrapper.ts | 1 - 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 0f1698cb9..9f98584ec 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -24,7 +24,6 @@ import { RootProjectsStore } from "../../stores"; import { RefreshDaemonStatusCommand, StopDaemonCommand, StopDaemonsCommand } from "../../commands"; import { sleep } from "../../util"; import { GradleStatus } from "../../views/gradleDaemons/services/GradleStatus"; -import { GradleLocalInstallation } from "../../views/gradleDaemons/services/GradleLocalInstallation"; import { GradleConnectionType } from "../../views/gradleDaemons/models/GradleConnectionType"; const mockContext = buildMockContext(); @@ -45,7 +44,6 @@ describe(getSuiteName("Gradle daemons"), () => { await rootProjectsStore.populate(); - // GradleClient.getBuild() sets the gradle versions once it receives the gradle environment const projectRoots = await rootProjectsStore.getProjectRoots(); const gradleEnvironment1 = new GradleEnvironment(); gradleEnvironment1.setGradleVersion("6.3"); @@ -87,13 +85,12 @@ describe(getSuiteName("Gradle daemons"), () => { const mockDaemonInfoIdle = new DaemonInfo("41717", DaemonStatus.IDLE, "6.4"); const mockDaemonInfoStopped = new DaemonInfo("41718", DaemonStatus.STOPPED, "(by user or operating system)"); - sinon.stub(GradleStatus, 'getDaemonsStatusList') + sinon + .stub(GradleStatus, "getDaemonsStatusList") .withArgs(mockWorkspaceFolder1.uri.fsPath) .resolves([mockDaemonInfoBusy, mockDaemonInfoStopped]) .withArgs(mockWorkspaceFolder2.uri.fsPath) .resolves([mockDaemonInfoIdle, mockDaemonInfoStopped]); - // NOTE: no reason to mock reply for mockWorkspaceFolder3 as it should be ignored due to - // dupicate gradle version let children = await gradleDaemonsTreeDataProvider.getChildren(); @@ -139,13 +136,17 @@ describe(getSuiteName("Gradle daemons"), () => { it("should stop a daemon", async () => { const mockDaemonInfoBusy = new DaemonInfo("41716", DaemonStatus.BUSY, "6.3"); - const mockGradleDaemonTreeItem = new GradleDaemonTreeItem(mockContext, mockDaemonInfoBusy.getPid(), mockDaemonInfoBusy); + const mockGradleDaemonTreeItem = new GradleDaemonTreeItem( + mockContext, + mockDaemonInfoBusy.getPid(), + mockDaemonInfoBusy + ); const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); + const mockStopDaemonCommand = new StopDaemonCommand(); + sinon.stub(mockStopDaemonCommand, "stopDaemon").withArgs(mockDaemonInfoBusy.getPid()).resolves(); - sinon.stub(StopDaemonCommand.prototype, 'stopDaemon').withArgs(mockDaemonInfoBusy.getPid()).resolves(); - - await new StopDaemonCommand().run(mockGradleDaemonTreeItem); + await mockStopDaemonCommand.run(mockGradleDaemonTreeItem); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemon?"), @@ -157,20 +158,16 @@ describe(getSuiteName("Gradle daemons"), () => { "Output channel appendLine not called with correct message" ); assert.strictEqual(mockOutputChannel.appendLine.callCount, 1); - }); it("should stop all daemons", async () => { const showWarningMessageStub = (sinon.stub(vscode.window, "showWarningMessage") as SinonStub).resolves("Yes"); + sinon.stub(GradleStatus, "getConnectionType").withArgs(sinon.match.any).resolves(GradleConnectionType.WRAPPER); - const gradleLocalInstallationExecStub = sinon.stub(GradleLocalInstallation.prototype, "exec").resolves(); - - sinon.stub(GradleStatus, "getConnectionType") - .withArgs(sinon.match.any).resolves(GradleConnectionType.WRAPPER); - - sinon.stub(StopDaemonsCommand.prototype, 'stopDaemons').resolves(); + const mockStopDaemonsCommand = new StopDaemonsCommand(rootProjectsStore); + sinon.stub(mockStopDaemonsCommand, "stopDaemons").resolves(); - await new StopDaemonsCommand(rootProjectsStore).run(); + await mockStopDaemonsCommand.run(); assert.ok( showWarningMessageStub.calledWith("Are you sure you want to stop the daemons?"), @@ -183,10 +180,8 @@ describe(getSuiteName("Gradle daemons"), () => { ); showWarningMessageStub.restore(); - gradleLocalInstallationExecStub.restore(); }); - it("should refresh the daemons list", async () => { const onDidChangeSpy = sinon.spy(); gradleDaemonsTreeDataProvider.onDidChangeTreeData(onDidChangeSpy); @@ -209,7 +204,8 @@ describe(getSuiteName("Gradle daemons"), () => { sinon.stub(vscode.workspace, "workspaceFolders").value([mockWorkspaceFolder1]); - const getDaemonsStatusListStub = sinon.stub(GradleStatus, 'getDaemonsStatusList') + const getDaemonsStatusListStub = sinon + .stub(GradleStatus, "getDaemonsStatusList") .withArgs(mockWorkspaceFolder2.uri.fsPath) .resolves([mockDaemonInfoIdle]); @@ -233,9 +229,5 @@ describe(getSuiteName("Gradle daemons"), () => { const refreshedChildren = await gradleDaemonsTreeDataProvider.getChildren(); assert.strictEqual(refreshedChildren[0].description, "IDLE"); - - sinon.restore(); }); - - }); diff --git a/extension/src/util/execAsync.ts b/extension/src/util/execAsync.ts index 203caca0f..2a33f9fab 100644 --- a/extension/src/util/execAsync.ts +++ b/extension/src/util/execAsync.ts @@ -1,4 +1,4 @@ -import { exec } from 'child_process'; -import { promisify } from 'util'; +import { exec } from "child_process"; +import { promisify } from "util"; export const execAsync = promisify(exec); diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index a76e912a9..b5c282bc8 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -3,7 +3,6 @@ import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; - export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; constructor(private projectRoot: string) { From 22e84c7ed1026ad49e439f31f1d9c45fc200c6c9 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Thu, 16 May 2024 19:39:59 +0800 Subject: [PATCH 17/30] update gradle daemons & test cases --- extension/src/test/testUtil.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/extension/src/test/testUtil.ts b/extension/src/test/testUtil.ts index 8dbc6633b..876666774 100644 --- a/extension/src/test/testUtil.ts +++ b/extension/src/test/testUtil.ts @@ -9,7 +9,6 @@ import * as fs from "fs"; import { GradleTaskDefinition } from "../tasks"; import { GradleTask } from "../proto/gradle_pb"; import { TREE_ITEM_STATE_FOLDER } from "../views/constants"; -//import { get } from "lodash"; export const EXTENSION_NAME = "vscjava.vscode-gradle"; From 2337a964e80b49ff49b8ae6c5deb390ecde60d62 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 20 May 2024 15:03:41 +0800 Subject: [PATCH 18/30] update task server impl --- extension/src/views/constants.ts | 12 ++++++------ .../views/gradleDaemons/GradleDaemonTreeItem.ts | 12 +----------- .../views/gradleDaemons/models/DaemonStatus.ts | 10 +++++----- .../views/gradleDaemons/services/GradleStatus.ts | 10 +++------- .../views/gradleDaemons/services/GradleWrapper.ts | 15 ++++----------- 5 files changed, 19 insertions(+), 40 deletions(-) diff --git a/extension/src/views/constants.ts b/extension/src/views/constants.ts index 4bb366ecb..b9d48b3b5 100644 --- a/extension/src/views/constants.ts +++ b/extension/src/views/constants.ts @@ -1,4 +1,4 @@ -import { DaemonInfo } from "../proto/gradle_pb"; +import { DaemonStatus } from "./gradleDaemons/models/DaemonStatus"; export const ICON_LOADING = "loading.svg"; export const ICON_GRADLE_TASK = "script.svg"; @@ -24,9 +24,9 @@ export const TREE_ITEM_STATE_FOLDER = "folder"; export const TASK_STATE_RUNNING_REGEX = new RegExp(`^${TREE_ITEM_STATE_TASK_RUNNING}`); export const DAEMON_ICON_MAP = { - [DaemonInfo.DaemonStatus.BUSY]: ICON_DAEMON_BUSY, - [DaemonInfo.DaemonStatus.IDLE]: ICON_DAEMON_IDLE, - [DaemonInfo.DaemonStatus.STOPPED]: ICON_DAEMON_STOPPED, - [DaemonInfo.DaemonStatus.STOPPING]: ICON_DAEMON_STOPPED, - [DaemonInfo.DaemonStatus.CANCELED]: ICON_DAEMON_STOPPED, + [DaemonStatus.BUSY]: ICON_DAEMON_BUSY, + [DaemonStatus.IDLE]: ICON_DAEMON_IDLE, + [DaemonStatus.STOPPED]: ICON_DAEMON_STOPPED, + [DaemonStatus.STOPPING]: ICON_DAEMON_STOPPED, + [DaemonStatus.CANCELED]: ICON_DAEMON_STOPPED, }; diff --git a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts index 70fe534a2..5b2295c7a 100644 --- a/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts +++ b/extension/src/views/gradleDaemons/GradleDaemonTreeItem.ts @@ -3,16 +3,6 @@ import * as path from "path"; import { DAEMON_ICON_MAP } from "../constants"; import { DaemonInfo } from "./models/DaemonInfo"; import { DaemonStatus } from "./models/DaemonStatus"; -interface StatusEnumMapByValue { - [key: number]: string; -} - -const daemonStatusEnumMapByValue: StatusEnumMapByValue = Object.assign( - {}, - ...Object.entries(DaemonStatus).map(([a, b]) => ({ - [b]: a, - })) -); export class GradleDaemonTreeItem extends vscode.TreeItem { private status: string; @@ -27,7 +17,7 @@ export class GradleDaemonTreeItem extends vscode.TreeItem { light: this.context.asAbsolutePath(path.join("resources", "light", iconName)), dark: this.context.asAbsolutePath(path.join("resources", "dark", iconName)), }; - this.status = daemonStatusEnumMapByValue[daemonInfo.getStatus()]; + this.status = DaemonStatus[daemonInfo.getStatus()]; this.description = this.status; this.contextValue = this.status.toLowerCase(); this.tooltip = `${this.status} - ${daemonInfo.getInfo()}`; diff --git a/extension/src/views/gradleDaemons/models/DaemonStatus.ts b/extension/src/views/gradleDaemons/models/DaemonStatus.ts index f12b29aa0..56a64c354 100644 --- a/extension/src/views/gradleDaemons/models/DaemonStatus.ts +++ b/extension/src/views/gradleDaemons/models/DaemonStatus.ts @@ -1,7 +1,7 @@ export enum DaemonStatus { - IDLE = 0, - BUSY = 1, - STOPPED = 2, - STOPPING = 3, - CANCELED = 4, + IDLE = "IDLE", + BUSY = "BUSY", + STOPPED = "STOPPED", + STOPPING = "STOPPING", + CANCELED = "CANCELED", } diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index bfd2bd910..2448d2627 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -15,7 +15,7 @@ export class GradleStatus { } else if (gradleConfig.getGradleHome()) { return GradleConnectionType.LOCALINSTALLATION; } - return GradleConnectionType.SPECIFICVERSION; + return GradleConnectionType.WRAPPER; } } @@ -26,17 +26,13 @@ export class GradleStatus { if (await GradleWrapper.hasValidWrapper(projectRoot)) { const wrapper = new GradleWrapper(projectRoot); return wrapper.exec(["--status", "quiet"]); - } else { - return ""; } - + return ""; case GradleConnectionType.LOCALINSTALLATION: const localInstallation = new GradleLocalInstallation(gradleConfig.getGradleHome()); return localInstallation.exec(["--status", "quiet"]); - case GradleConnectionType.SPECIFICVERSION: return ""; - default: throw new Error("Unknown connection type"); } @@ -64,7 +60,7 @@ export class GradleStatus { const statusString = match[2]; const info = match[3]; - const status = DaemonStatus[statusString as keyof typeof DaemonStatus]; + const status = statusString as DaemonStatus; daemonInfos.push(new DaemonInfo(pid, status, info)); } diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index b5c282bc8..53700410a 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -1,4 +1,4 @@ -import { promises as fs } from "fs"; +import fsExtra from "fs-extra"; import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; @@ -28,16 +28,9 @@ export class GradleWrapper implements GradleExecution { } static async hasValidWrapper(projectRoot: string): Promise { - try { - const propertiesPath = path.join(projectRoot, "gradle", "wrapper", "gradle-wrapper.properties"); - const wrapperName = process.platform === "win32" ? "gradlew.bat" : "gradlew"; - const wrapperPath = path.join(projectRoot, wrapperName); + const propertiesPath = path.join(projectRoot, "gradle", "wrapper", "gradle-wrapper.properties"); - await fs.access(propertiesPath); - await fs.access(wrapperPath); - return true; - } catch { - return false; - } + const hasProperties = await fsExtra.pathExists(propertiesPath); + return hasProperties; } } From 4fcf41fa02e1926295f180f4a5794a891626a083 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 20 May 2024 17:06:27 +0800 Subject: [PATCH 19/30] fix import error --- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 53700410a..64b9371da 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -1,4 +1,4 @@ -import fsExtra from "fs-extra"; +import * as fse from 'fs-extra' import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; @@ -30,7 +30,7 @@ export class GradleWrapper implements GradleExecution { static async hasValidWrapper(projectRoot: string): Promise { const propertiesPath = path.join(projectRoot, "gradle", "wrapper", "gradle-wrapper.properties"); - const hasProperties = await fsExtra.pathExists(propertiesPath); + const hasProperties = await fse.pathExists(propertiesPath); return hasProperties; } } From 88b645b7abf75919eeab22c43722b73831efb3f5 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 20 May 2024 18:21:22 +0800 Subject: [PATCH 20/30] fix lint --- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 64b9371da..26bd0e451 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -1,4 +1,4 @@ -import * as fse from 'fs-extra' +import * as fse from "fs-extra"; import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; From 7c7a9bb39316a00111d96762bf2275126f87aad7 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 21 May 2024 11:13:12 +0800 Subject: [PATCH 21/30] fix daemon status bugs and add test --- extension/src/test/unit/gradleDaemons.test.ts | 60 +++++++++++++++++++ .../services/GradleLocalInstallation.ts | 2 +- .../gradleDaemons/services/GradleStatus.ts | 10 ++-- .../gradleDaemons/services/GradleWrapper.ts | 4 +- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 9f98584ec..1dd8b95a3 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -230,4 +230,64 @@ describe(getSuiteName("Gradle daemons"), () => { assert.strictEqual(refreshedChildren[0].description, "IDLE"); }); + + it("test parseDaemonInfo with various inputs", () => { + // Windows-style input with \r\n + const windowsOutput = ` + 95141 IDLE 8.6\r\n + 12345 BUSY 7.5\r\n + 67890 STOPPED (by user or operating system)\r\n + malformed line\r\n + `; + + const windowsDaemonInfos = GradleStatus.parseDaemonInfo(windowsOutput); + + assert.strictEqual(windowsDaemonInfos.length, 3, "There should be 3 daemons parsed, ignoring malformed lines (Windows)"); + + const windowsDaemon1 = windowsDaemonInfos[0]; + assert.strictEqual(windowsDaemon1.getPid(), "95141"); + assert.strictEqual(windowsDaemon1.getStatus(), DaemonStatus.IDLE); + assert.strictEqual(windowsDaemon1.getInfo(), "8.6"); + + const windowsDaemon2 = windowsDaemonInfos[1]; + assert.strictEqual(windowsDaemon2.getPid(), "12345"); + assert.strictEqual(windowsDaemon2.getStatus(), DaemonStatus.BUSY); + assert.strictEqual(windowsDaemon2.getInfo(), "7.5"); + + const windowsDaemon3 = windowsDaemonInfos[2]; + assert.strictEqual(windowsDaemon3.getPid(), "67890"); + assert.strictEqual(windowsDaemon3.getStatus(), DaemonStatus.STOPPED); + assert.strictEqual(windowsDaemon3.getInfo(), "(by user or operating system)"); + + // Unix/Mac-style input with \n + const unixOutput = ` + 95141 IDLE 8.6\n + 12345 BUSY 7.5\n + 67890 STOPPED (by user or operating system)\n + malformed line\n + `; + + const unixDaemonInfos = GradleStatus.parseDaemonInfo(unixOutput); + + assert.strictEqual(unixDaemonInfos.length, 3, "There should be 3 daemons parsed, ignoring malformed lines (Unix/Mac)"); + + const unixDaemon1 = unixDaemonInfos[0]; + assert.strictEqual(unixDaemon1.getPid(), "95141"); + assert.strictEqual(unixDaemon1.getStatus(), DaemonStatus.IDLE); + assert.strictEqual(unixDaemon1.getInfo(), "8.6"); + + const unixDaemon2 = unixDaemonInfos[1]; + assert.strictEqual(unixDaemon2.getPid(), "12345"); + assert.strictEqual(unixDaemon2.getStatus(), DaemonStatus.BUSY); + assert.strictEqual(unixDaemon2.getInfo(), "7.5"); + + const unixDaemon3 = unixDaemonInfos[2]; + assert.strictEqual(unixDaemon3.getPid(), "67890"); + assert.strictEqual(unixDaemon3.getStatus(), DaemonStatus.STOPPED); + assert.strictEqual(unixDaemon3.getInfo(), "(by user or operating system)"); + + const emptyOutput = ""; + const emptyDaemonInfos = GradleStatus.parseDaemonInfo(emptyOutput); + assert.strictEqual(emptyDaemonInfos.length, 0, "There should be no daemons parsed for empty output"); + }); }); diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 12135f030..01080782c 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -7,7 +7,7 @@ export class GradleLocalInstallation implements GradleExecution { this.gradleHomePath = gradleHomePath; } - async exec(args: string[]): Promise { + public async exec(args: string[]): Promise { if (args.length === 0) { throw new Error("No gradle args supplied"); } diff --git a/extension/src/views/gradleDaemons/services/GradleStatus.ts b/extension/src/views/gradleDaemons/services/GradleStatus.ts index 2448d2627..46f7fa46a 100644 --- a/extension/src/views/gradleDaemons/services/GradleStatus.ts +++ b/extension/src/views/gradleDaemons/services/GradleStatus.ts @@ -6,7 +6,7 @@ import { GradleWrapper } from "./GradleWrapper"; import { GradleLocalInstallation } from "./GradleLocalInstallation"; import { GradleConnectionType } from "../models/GradleConnectionType"; export class GradleStatus { - static async getConnectionType(gradleConfig: GradleConfig): Promise { + public static async getConnectionType(gradleConfig: GradleConfig): Promise { if (gradleConfig.getWrapperEnabled()) { return GradleConnectionType.WRAPPER; } else { @@ -19,7 +19,7 @@ export class GradleStatus { } } - static async getDaemonsStatusOutput(gradleConfig: GradleConfig, projectRoot: string): Promise { + private static async getDaemonsStatusOutput(gradleConfig: GradleConfig, projectRoot: string): Promise { const connectionType = await this.getConnectionType(gradleConfig); switch (connectionType) { case GradleConnectionType.WRAPPER: @@ -38,17 +38,17 @@ export class GradleStatus { } } - static async getDaemonsStatusList(projectRoot: string): Promise { + public static async getDaemonsStatusList(projectRoot: string): Promise { const gradleConfig = getGradleConfig(); const output = await this.getDaemonsStatusOutput(gradleConfig, projectRoot); return this.parseDaemonInfo(output); } - private static parseDaemonInfo(output: string): DaemonInfo[] { + public static parseDaemonInfo(output: string): DaemonInfo[] { if (!output) return []; - const lines = output.split("\n"); + const lines = output.split(/\r?\n/); const daemonInfos: DaemonInfo[] = []; const statusRegex = /^\s*([0-9]+)\s+(\w+)\s+(.+)$/; diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 26bd0e451..210d48b61 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -10,7 +10,7 @@ export class GradleWrapper implements GradleExecution { this.gradleWrapperPath = path.join(projectRoot, wrapperName); } - async exec(args: string[]): Promise { + public async exec(args: string[]): Promise { if (args.length === 0) { throw new Error("No wrapper args supplied"); } @@ -27,7 +27,7 @@ export class GradleWrapper implements GradleExecution { } } - static async hasValidWrapper(projectRoot: string): Promise { + public static async hasValidWrapper(projectRoot: string): Promise { const propertiesPath = path.join(projectRoot, "gradle", "wrapper", "gradle-wrapper.properties"); const hasProperties = await fse.pathExists(propertiesPath); From 6e360303eaf42a1bc07010ad26fa6a5305a47561 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 21 May 2024 12:09:13 +0800 Subject: [PATCH 22/30] fix daemon status bugs and add test --- extension/src/test/unit/gradleDaemons.test.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/extension/src/test/unit/gradleDaemons.test.ts b/extension/src/test/unit/gradleDaemons.test.ts index 1dd8b95a3..c61aa835b 100644 --- a/extension/src/test/unit/gradleDaemons.test.ts +++ b/extension/src/test/unit/gradleDaemons.test.ts @@ -231,7 +231,7 @@ describe(getSuiteName("Gradle daemons"), () => { assert.strictEqual(refreshedChildren[0].description, "IDLE"); }); - it("test parseDaemonInfo with various inputs", () => { + it("should correctly parse daemonInfos from input with Unix and Windows line endings", () => { // Windows-style input with \r\n const windowsOutput = ` 95141 IDLE 8.6\r\n @@ -242,7 +242,11 @@ describe(getSuiteName("Gradle daemons"), () => { const windowsDaemonInfos = GradleStatus.parseDaemonInfo(windowsOutput); - assert.strictEqual(windowsDaemonInfos.length, 3, "There should be 3 daemons parsed, ignoring malformed lines (Windows)"); + assert.strictEqual( + windowsDaemonInfos.length, + 3, + "There should be 3 daemons parsed, ignoring malformed lines (Windows)" + ); const windowsDaemon1 = windowsDaemonInfos[0]; assert.strictEqual(windowsDaemon1.getPid(), "95141"); @@ -269,7 +273,11 @@ describe(getSuiteName("Gradle daemons"), () => { const unixDaemonInfos = GradleStatus.parseDaemonInfo(unixOutput); - assert.strictEqual(unixDaemonInfos.length, 3, "There should be 3 daemons parsed, ignoring malformed lines (Unix/Mac)"); + assert.strictEqual( + unixDaemonInfos.length, + 3, + "There should be 3 daemons parsed, ignoring malformed lines (Unix/Mac)" + ); const unixDaemon1 = unixDaemonInfos[0]; assert.strictEqual(unixDaemon1.getPid(), "95141"); From 71705d99d2030ea09690589cc608365c23fb0baf Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Mon, 27 May 2024 17:34:46 +0800 Subject: [PATCH 23/30] fix jdk bugs --- .../gradleDaemons/services/GradleLocalInstallation.ts | 7 ++++++- .../src/views/gradleDaemons/services/GradleWrapper.ts | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 01080782c..80c86d2e2 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,5 +1,7 @@ import { GradleExecution } from "./GradleExecution"; import { execAsync } from "../../../util/execAsync"; +import { getConfigJavaImportGradleJavaHome} from "../../../util/config"; + export class GradleLocalInstallation implements GradleExecution { private gradleHomePath: string; @@ -15,7 +17,10 @@ export class GradleLocalInstallation implements GradleExecution { const command = `${this.gradleHomePath} ${args.join(" ")}`; try { - const { stdout, stderr } = await execAsync(command); + const jdkPath = getConfigJavaImportGradleJavaHome() + const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; + + const { stdout, stderr } = await execAsync(command, { env }); if (stderr) { throw new Error(`Error running gradle: ${stderr}`); } diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 210d48b61..b9d8e959d 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -2,7 +2,7 @@ import * as fse from "fs-extra"; import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; - +import { getConfigJavaImportGradleJavaHome} from "../../../util/config"; export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; constructor(private projectRoot: string) { @@ -17,7 +17,10 @@ export class GradleWrapper implements GradleExecution { const command = `${this.gradleWrapperPath} ${args.join(" ")}`; try { - const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot }); + const jdkPath = getConfigJavaImportGradleJavaHome() + const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; + + const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { throw new Error(`Error running gradle wrapper: ${stderr}`); } From ac109a219e0b81bf5e6ad8c535995ae95de76d46 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 09:42:18 +0800 Subject: [PATCH 24/30] fix gradle daemon status jdk bugs --- .../views/gradleDaemons/services/GradleLocalInstallation.ts | 4 ++-- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 80c86d2e2..80434af5b 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,6 +1,6 @@ import { GradleExecution } from "./GradleExecution"; import { execAsync } from "../../../util/execAsync"; -import { getConfigJavaImportGradleJavaHome} from "../../../util/config"; +import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; export class GradleLocalInstallation implements GradleExecution { private gradleHomePath: string; @@ -17,7 +17,7 @@ export class GradleLocalInstallation implements GradleExecution { const command = `${this.gradleHomePath} ${args.join(" ")}`; try { - const jdkPath = getConfigJavaImportGradleJavaHome() + const jdkPath = getConfigJavaImportGradleJavaHome(); const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; const { stdout, stderr } = await execAsync(command, { env }); diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index b9d8e959d..2c7bbaf3e 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -2,7 +2,7 @@ import * as fse from "fs-extra"; import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; -import { getConfigJavaImportGradleJavaHome} from "../../../util/config"; +import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; constructor(private projectRoot: string) { @@ -17,7 +17,7 @@ export class GradleWrapper implements GradleExecution { const command = `${this.gradleWrapperPath} ${args.join(" ")}`; try { - const jdkPath = getConfigJavaImportGradleJavaHome() + const jdkPath = getConfigJavaImportGradleJavaHome(); const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); From 21c8faf2fe0c93ec3cb01c041a4c23052b2cade2 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 10:29:34 +0800 Subject: [PATCH 25/30] fix bugs --- .../src/views/gradleDaemons/services/GradleWrapper.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 2c7bbaf3e..feeec6861 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -3,6 +3,7 @@ import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; +import { logger } from "../../../logger"; export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; constructor(private projectRoot: string) { @@ -22,7 +23,14 @@ export class GradleWrapper implements GradleExecution { const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { - throw new Error(`Error running gradle wrapper: ${stderr}`); + const stderrLines = stderr.split('\n'); + const isError = stderrLines.some(line => line.toLowerCase().includes('error')); + + if (isError) { + throw new Error(`Error running gradle wrapper: ${stderr}`); + } else { + logger.warn(`Warning: ${stderr}`); + } } return stdout; } catch (error) { From 1daab91a393e685a65442f72d335f58c3e2b1042 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 12:47:49 +0800 Subject: [PATCH 26/30] fix gradle daemon jdk bugs --- .../services/GradleLocalInstallation.ts | 8 +++++--- .../gradleDaemons/services/GradleWrapper.ts | 16 +++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 80434af5b..6f0f1da3b 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,10 +1,11 @@ import { GradleExecution } from "./GradleExecution"; import { execAsync } from "../../../util/execAsync"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; +import * as vscode from "vscode"; export class GradleLocalInstallation implements GradleExecution { private gradleHomePath: string; - + private outputChannel: vscode.OutputChannel; constructor(gradleHomePath: string) { this.gradleHomePath = gradleHomePath; } @@ -22,11 +23,12 @@ export class GradleLocalInstallation implements GradleExecution { const { stdout, stderr } = await execAsync(command, { env }); if (stderr) { - throw new Error(`Error running gradle: ${stderr}`); + this.outputChannel.appendLine(`${stderr}`); + this.outputChannel.show(); } return stdout; } catch (error) { - throw new Error(`Error running gradle: ${error.message}`); + throw new Error(`Error running gradle local installation: ${error.message}`); } } } diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index feeec6861..7a9b8d0ef 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -3,12 +3,16 @@ import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; -import { logger } from "../../../logger"; +import * as vscode from "vscode"; + export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; + private outputChannel: vscode.OutputChannel; + constructor(private projectRoot: string) { const wrapperName = process.platform === "win32" ? "gradlew.bat" : "gradlew"; this.gradleWrapperPath = path.join(projectRoot, wrapperName); + this.outputChannel = vscode.window.createOutputChannel("Gradle Wrapper"); } public async exec(args: string[]): Promise { @@ -23,14 +27,8 @@ export class GradleWrapper implements GradleExecution { const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { - const stderrLines = stderr.split('\n'); - const isError = stderrLines.some(line => line.toLowerCase().includes('error')); - - if (isError) { - throw new Error(`Error running gradle wrapper: ${stderr}`); - } else { - logger.warn(`Warning: ${stderr}`); - } + this.outputChannel.appendLine(`${stderr}`); + this.outputChannel.show(); } return stdout; } catch (error) { From db0d9c31e6222e3723d426c0bb115280ebd35dd1 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 13:46:20 +0800 Subject: [PATCH 27/30] change gradle daemons log method --- .../gradleDaemons/services/GradleLocalInstallation.ts | 7 +++---- .../src/views/gradleDaemons/services/GradleWrapper.ts | 9 ++------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 6f0f1da3b..54644f865 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -1,11 +1,11 @@ import { GradleExecution } from "./GradleExecution"; import { execAsync } from "../../../util/execAsync"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; -import * as vscode from "vscode"; +import { logger } from "../../../logger"; export class GradleLocalInstallation implements GradleExecution { private gradleHomePath: string; - private outputChannel: vscode.OutputChannel; + constructor(gradleHomePath: string) { this.gradleHomePath = gradleHomePath; } @@ -23,8 +23,7 @@ export class GradleLocalInstallation implements GradleExecution { const { stdout, stderr } = await execAsync(command, { env }); if (stderr) { - this.outputChannel.appendLine(`${stderr}`); - this.outputChannel.show(); + logger.warn(stderr); } return stdout; } catch (error) { diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 7a9b8d0ef..074d1beaa 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -3,16 +3,13 @@ import { execAsync } from "../../../util/execAsync"; import { GradleExecution } from "./GradleExecution"; import * as path from "path"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; -import * as vscode from "vscode"; - +import { logger } from "../../../logger"; export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; - private outputChannel: vscode.OutputChannel; constructor(private projectRoot: string) { const wrapperName = process.platform === "win32" ? "gradlew.bat" : "gradlew"; this.gradleWrapperPath = path.join(projectRoot, wrapperName); - this.outputChannel = vscode.window.createOutputChannel("Gradle Wrapper"); } public async exec(args: string[]): Promise { @@ -24,11 +21,9 @@ export class GradleWrapper implements GradleExecution { try { const jdkPath = getConfigJavaImportGradleJavaHome(); const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; - const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { - this.outputChannel.appendLine(`${stderr}`); - this.outputChannel.show(); + logger.warn(stderr); } return stdout; } catch (error) { From 1c0705020956d385321caee73958690d9d34af6f Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 15:05:30 +0800 Subject: [PATCH 28/30] fix lint --- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 074d1beaa..09fcca2bf 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -21,6 +21,7 @@ export class GradleWrapper implements GradleExecution { try { const jdkPath = getConfigJavaImportGradleJavaHome(); const env = jdkPath ? { ...process.env, JAVA_HOME: jdkPath } : process.env; + const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { logger.warn(stderr); From c16318bd0f2f148c88b1fb09ffb11396599b9146 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Tue, 28 May 2024 15:09:39 +0800 Subject: [PATCH 29/30] fix lint --- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index 09fcca2bf..ba9016ded 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -4,6 +4,7 @@ import { GradleExecution } from "./GradleExecution"; import * as path from "path"; import { getConfigJavaImportGradleJavaHome } from "../../../util/config"; import { logger } from "../../../logger"; + export class GradleWrapper implements GradleExecution { private gradleWrapperPath: string; From 03206f3fd076696d31c9b31fdb7d7974c8cfabc2 Mon Sep 17 00:00:00 2001 From: Jiaaming <2455951489@qq.com> Date: Wed, 29 May 2024 10:41:21 +0800 Subject: [PATCH 30/30] add detail logger --- .../views/gradleDaemons/services/GradleLocalInstallation.ts | 3 ++- extension/src/views/gradleDaemons/services/GradleWrapper.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts index 54644f865..d682a8dab 100644 --- a/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts +++ b/extension/src/views/gradleDaemons/services/GradleLocalInstallation.ts @@ -23,10 +23,11 @@ export class GradleLocalInstallation implements GradleExecution { const { stdout, stderr } = await execAsync(command, { env }); if (stderr) { - logger.warn(stderr); + logger.error(stderr); } return stdout; } catch (error) { + logger.error(error.message); throw new Error(`Error running gradle local installation: ${error.message}`); } } diff --git a/extension/src/views/gradleDaemons/services/GradleWrapper.ts b/extension/src/views/gradleDaemons/services/GradleWrapper.ts index ba9016ded..285c724d9 100644 --- a/extension/src/views/gradleDaemons/services/GradleWrapper.ts +++ b/extension/src/views/gradleDaemons/services/GradleWrapper.ts @@ -25,10 +25,11 @@ export class GradleWrapper implements GradleExecution { const { stdout, stderr } = await execAsync(command, { cwd: this.projectRoot, env }); if (stderr) { - logger.warn(stderr); + logger.error(stderr); } return stdout; } catch (error) { + logger.error(error.message); throw new Error(`Error running gradle wrapper: ${error.message}`); } }