diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java index cb3fcdda..5d3b4f94 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java @@ -146,7 +146,7 @@ public static boolean exportJar(List arguments, IProgressMonitor monitor String mainClass = gson.fromJson(gson.toJson(arguments.get(0)), String.class); Classpath[] classpaths = gson.fromJson(gson.toJson(arguments.get(1)), Classpath[].class); String destination = gson.fromJson(gson.toJson(arguments.get(2)), String.class); - String taskLabel = gson.fromJson(gson.toJson(arguments.get(3)), String.class); + String terminalId = gson.fromJson(gson.toJson(arguments.get(3)), String.class); Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); if (mainClass.length() > 0) { @@ -164,28 +164,28 @@ public static boolean exportJar(List arguments, IProgressMonitor monitor int severity = resultStatus.getSeverity(); if (severity == IStatus.OK) { java.nio.file.Path path = java.nio.file.Paths.get(classpath.source); - reportExportJarMessage(taskLabel, IStatus.OK, "Successfully added the file to the exported jar: " + path.getFileName().toString()); + reportExportJarMessage(terminalId, IStatus.OK, "Successfully extracted the file to the exported jar: " + path.getFileName().toString()); continue; } if (resultStatus.isMultiStatus()) { for (IStatus childStatus : resultStatus.getChildren()) { - reportExportJarMessage(taskLabel, severity, childStatus.getMessage()); + reportExportJarMessage(terminalId, severity, childStatus.getMessage()); } } else { - reportExportJarMessage(taskLabel, severity, resultStatus.getMessage()); + reportExportJarMessage(terminalId, severity, resultStatus.getMessage()); } } else { try { writeFile(new File(classpath.source), new Path(classpath.destination), /* areDirectoryEntriesIncluded = */true, /* isCompressed = */true, target, directories); - reportExportJarMessage(taskLabel, IStatus.OK, "Successfully added the file to the exported jar: " + classpath.destination); + reportExportJarMessage(terminalId, IStatus.OK, "Successfully added the file to the exported jar: " + classpath.destination); } catch (CoreException e) { - reportExportJarMessage(taskLabel, IStatus.ERROR, e.getMessage()); + reportExportJarMessage(terminalId, IStatus.ERROR, e.getMessage()); } } } } catch (IOException e) { - reportExportJarMessage(taskLabel, IStatus.ERROR, e.getMessage()); + reportExportJarMessage(terminalId, IStatus.ERROR, e.getMessage()); return false; } return true; @@ -254,11 +254,11 @@ public static String getModuleName(IJavaProject project) { } } - private static void reportExportJarMessage(String taskLabel, int severity, String message) { - if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(taskLabel)) { + private static void reportExportJarMessage(String terminalId, int severity, String message) { + if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(terminalId)) { String readableSeverity = getSeverityString(severity); JavaLanguageServerPlugin.getInstance().getClientConnection().executeClientCommand(COMMAND_EXPORT_JAR_REPORT, - taskLabel, "[" + readableSeverity + "] " + message); + terminalId, "[" + readableSeverity + "] " + message); } } diff --git a/src/exportJarSteps/ExportJarTaskProvider.ts b/src/exportJarSteps/ExportJarTaskProvider.ts index 669fdc92..d8be067a 100644 --- a/src/exportJarSteps/ExportJarTaskProvider.ts +++ b/src/exportJarSteps/ExportJarTaskProvider.ts @@ -22,7 +22,7 @@ import { IClasspath, IStepMetadata } from "./IStepMetadata"; import { IMainClassInfo } from "./ResolveMainClassExecutor"; import { ExportJarConstants, ExportJarMessages, ExportJarStep, failMessage, getExtensionApi, - resetStepMetadata, stepMap, successMessage, toPosixPath, toWinPath, + resetStepMetadata, revealTerminal, stepMap, successMessage, toPosixPath, toWinPath, } from "./utility"; interface IExportJarTaskDefinition extends TaskDefinition { @@ -33,6 +33,8 @@ interface IExportJarTaskDefinition extends TaskDefinition { } let isExportingJar: boolean = false; +// key: terminalId, value: ExportJarTaskTerminal +const activeTerminalMap: Map = new Map(); export async function executeExportJarTask(node?: INodeData): Promise { // save the workspace first @@ -168,21 +170,32 @@ class ExportJarTaskTerminal implements Pseudoterminal { public onDidWrite: Event = this.writeEmitter.event; public onDidClose?: Event = this.closeEmitter.event; + public terminalId: string; private stepMetadata: IStepMetadata; constructor(exportJarTaskDefinition: IExportJarTaskDefinition, stepMetadata: IStepMetadata) { this.stepMetadata = stepMetadata; this.stepMetadata.taskLabel = exportJarTaskDefinition.label || ""; + this.stepMetadata.terminalId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(); this.stepMetadata.mainClass = exportJarTaskDefinition.mainClass; this.stepMetadata.outputPath = exportJarTaskDefinition.targetPath; this.stepMetadata.elements = exportJarTaskDefinition.elements || []; + this.terminalId = this.stepMetadata.terminalId; } - public handleInput(data: string): void { - this.writeEmitter.fire(data + EOL); + public exit(message?: string) { + if (message) { + this.writeEmitter.fire(message); + } + if (activeTerminalMap.has(this.terminalId)) { + activeTerminalMap.delete(this.terminalId); + this.closeEmitter.fire(); + } } public async open(_initialDimensions: TerminalDimensions | undefined): Promise { + activeTerminalMap.set(this.terminalId, this); + revealTerminal(this.stepMetadata.taskLabel); let exportResult: boolean | undefined; try { if (!this.stepMetadata.workspaceFolder) { @@ -210,17 +223,21 @@ class ExportJarTaskTerminal implements Pseudoterminal { } catch (err) { if (err) { failMessage(`${err}`); + this.exit("[ERROR] An error occurs during export Jar process"); + } else { + this.exit("[CANCEL] Export Jar process is cancelled by user"); } } finally { isExportingJar = false; if (exportResult === true) { successMessage(this.stepMetadata.outputPath); + this.exit("[SUCCESS] Export Jar process is finished successfully"); } else if (exportResult === false) { // We call `executeExportJarTask()` with the same entry here // to help the user reselect the Java project. executeExportJarTask(this.stepMetadata.entry); } - this.closeEmitter.fire(); + this.exit(); } } @@ -406,3 +423,11 @@ class ExportJarTaskTerminal implements Pseudoterminal { return negative ? "!" + positivePath : positivePath; } } + +export function appendOutput(terminalId: string, message: string): void { + const terminal = activeTerminalMap.get(terminalId); + if (!terminal) { + return; + } + terminal.writeEmitter.fire(message + EOL); +} diff --git a/src/exportJarSteps/GenerateJarExecutor.ts b/src/exportJarSteps/GenerateJarExecutor.ts index 3bd44b36..c87d79d4 100644 --- a/src/exportJarSteps/GenerateJarExecutor.ts +++ b/src/exportJarSteps/GenerateJarExecutor.ts @@ -11,7 +11,7 @@ import { Jdtls } from "../java/jdtls"; import { INodeData } from "../java/nodeData"; import { IExportJarStepExecutor } from "./IExportJarStepExecutor"; import { IClasspath, IStepMetadata } from "./IStepMetadata"; -import { createPickBox, ExportJarMessages, ExportJarStep, ExportJarTargets, getExtensionApi, revealTerminal, toPosixPath } from "./utility"; +import { createPickBox, ExportJarMessages, ExportJarStep, ExportJarTargets, getExtensionApi, toPosixPath } from "./utility"; export class GenerateJarExecutor implements IExportJarStepExecutor { @@ -82,9 +82,11 @@ export class GenerateJarExecutor implements IExportJarStepExecutor { if (_.isEmpty(classpaths)) { return reject(new Error(ExportJarMessages.CLASSPATHS_EMPTY)); } - revealTerminal(stepMetadata.taskLabel); + if (!stepMetadata.terminalId) { + return reject(new Error("Can't find related terminal.")); + } const exportResult: boolean | undefined = await Jdtls.exportJar(basename(mainClass), - classpaths, destPath, stepMetadata.taskLabel, token); + classpaths, destPath, stepMetadata.terminalId, token); if (exportResult === true) { stepMetadata.outputPath = destPath; return resolve(true); diff --git a/src/exportJarSteps/IStepMetadata.ts b/src/exportJarSteps/IStepMetadata.ts index 5e67d29d..de582e2d 100644 --- a/src/exportJarSteps/IStepMetadata.ts +++ b/src/exportJarSteps/IStepMetadata.ts @@ -8,6 +8,7 @@ import { ExportJarStep } from "./utility"; export interface IStepMetadata { entry?: INodeData; taskLabel: string; + terminalId?: string; workspaceFolder?: WorkspaceFolder; mainClass?: string; outputPath?: string; diff --git a/src/exportJarSteps/utility.ts b/src/exportJarSteps/utility.ts index 481e5e77..6184fa89 100644 --- a/src/exportJarSteps/utility.ts +++ b/src/exportJarSteps/utility.ts @@ -154,14 +154,6 @@ export async function getExtensionApi(): Promise { return extensionApi; } -export function showExportJarReport(taskLabel: string, message: string) { - const terminals = window.terminals; - const presenterTerminals = terminals.filter((terminal) => terminal.name.indexOf(taskLabel) >= 0); - if (presenterTerminals.length > 0) { - presenterTerminals[presenterTerminals.length - 1].sendText(message); - } -} - export function revealTerminal(terminalName: string) { const terminals = window.terminals; const presenterTerminals = terminals.filter((terminal) => terminal.name.indexOf(terminalName) >= 0); diff --git a/src/java/jdtls.ts b/src/java/jdtls.ts index 1c94beff..01751f31 100644 --- a/src/java/jdtls.ts +++ b/src/java/jdtls.ts @@ -29,9 +29,9 @@ export namespace Jdtls { } export async function exportJar(mainClass: string, classpaths: IClasspath[], - destination: string, taskLabel: string, token: CancellationToken): Promise { + destination: string, terminalId: string, token: CancellationToken): Promise { return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_GENERATEJAR, - mainClass, classpaths, destination, taskLabel, token); + mainClass, classpaths, destination, terminalId, token); } export enum CompileWorkspaceStatus { diff --git a/src/views/dependencyDataProvider.ts b/src/views/dependencyDataProvider.ts index df2b1cc0..d0891f0f 100644 --- a/src/views/dependencyDataProvider.ts +++ b/src/views/dependencyDataProvider.ts @@ -10,8 +10,7 @@ import { instrumentOperation, instrumentOperationAsVsCodeCommand } from "vscode- import { contextManager } from "../../extension.bundle"; import { Commands } from "../commands"; import { Context } from "../constants"; -import { executeExportJarTask } from "../exportJarSteps/ExportJarTaskProvider"; -import { showExportJarReport } from "../exportJarSteps/utility"; +import { appendOutput, executeExportJarTask } from "../exportJarSteps/ExportJarTaskProvider"; import { Jdtls } from "../java/jdtls"; import { INodeData, NodeKind } from "../java/nodeData"; import { languageServerApiManager } from "../languageServerApi/languageServerApiManager"; @@ -36,8 +35,8 @@ export class DependencyDataProvider implements TreeDataProvider { constructor(public readonly context: ExtensionContext) { context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, (debounce?: boolean, element?: ExplorerNode) => this.refreshWithLog(debounce, element))); - context.subscriptions.push(commands.registerCommand(Commands.EXPORT_JAR_REPORT, (taskLabel: string, message: string) => { - showExportJarReport(taskLabel, message); + context.subscriptions.push(commands.registerCommand(Commands.EXPORT_JAR_REPORT, (terminalId: string, message: string) => { + appendOutput(terminalId, message); })); context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_EXPORT_JAR, async (node: INodeData) => { executeExportJarTask(node);