From 84e357823928f7e228df1cd8cf7ee86342bd4f2d Mon Sep 17 00:00:00 2001 From: Shi Chen Date: Tue, 18 May 2021 14:58:41 +0800 Subject: [PATCH 1/3] report message --- .../jdtls/ext/core/ProjectCommand.java | 83 ++++++++++++------- src/commands.ts | 2 + src/exportJarSteps/ExportJarTaskProvider.ts | 22 +++-- src/exportJarSteps/GenerateJarExecutor.ts | 16 ++-- src/exportJarSteps/IStepMetadata.ts | 1 + src/exportJarSteps/utility.ts | 16 ++++ src/java/jdtls.ts | 7 +- src/views/dependencyDataProvider.ts | 4 + 8 files changed, 101 insertions(+), 50 deletions(-) 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 f510d290..e77ffeed 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 @@ -29,6 +29,7 @@ import java.util.zip.ZipFile; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; @@ -36,6 +37,8 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IJavaElement; @@ -67,6 +70,8 @@ public final class ProjectCommand { + private static String COMMAND_EXPORT_JAR_REPORT = "java.view.package.exportJarReport"; + private static class MainClassInfo { public String name; public String path; @@ -83,23 +88,6 @@ private static class Classpath { public boolean isArtifact; } - private static class ExportResult { - public boolean result; - public String message; - public String log; - - ExportResult(boolean result) { - this.result = result; - this.log = ""; - } - - ExportResult(boolean result, String message) { - this.result = result; - this.message = message; - this.log = ""; - } - } - private static final Gson gson = new GsonBuilder().registerTypeAdapterFactory(new CollectionTypeAdapter.Factory()) .registerTypeAdapterFactory(new EnumTypeAdapter.Factory()).create(); @@ -151,16 +139,14 @@ private static IWorkspaceRoot getWorkspaceRoot() { return ResourcesPlugin.getWorkspace().getRoot(); } - public static ExportResult exportJar(List arguments, IProgressMonitor monitor) { - if (arguments.size() < 3) { - return new ExportResult(false, "Invalid export Arguments"); - } - if (monitor.isCanceled()) { - return new ExportResult(false, "User cancelled"); + public static boolean exportJar(List arguments, IProgressMonitor monitor) { + if (arguments.size() < 4) { + return false; } 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); Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); if (mainClass.length() > 0) { @@ -170,24 +156,39 @@ public static ExportResult exportJar(List arguments, IProgressMonitor mo Set directories = new HashSet<>(); for (Classpath classpath : classpaths) { if (monitor.isCanceled()) { - return new ExportResult(false, "User cancelled"); + return false; } if (classpath.isArtifact) { - writeArchive(new ZipFile(classpath.source), /* areDirectoryEntriesIncluded = */true, - /* isCompressed = */true, target, directories, monitor); + MultiStatus resultStatus = writeArchive(new ZipFile(classpath.source), + /* areDirectoryEntriesIncluded = */true, /* isCompressed = */true, target, directories, 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 export " + path.getFileName().toString()); + continue; + } + if (resultStatus.isMultiStatus()) { + for (IStatus childStatus : resultStatus.getChildren()) { + reportExportJarMessage(taskLabel, severity, childStatus.getMessage()); + } + } else { + reportExportJarMessage(taskLabel, 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 export " + classpath.destination); } catch (CoreException e) { - // TODO: Collect reports + reportExportJarMessage(taskLabel, IStatus.ERROR, e.getMessage()); } } } } catch (IOException e) { - return new ExportResult(false, e.getMessage()); + reportExportJarMessage(taskLabel, IStatus.ERROR, e.getMessage()); + return false; } - return new ExportResult(true); + return true; } public static List getMainClasses(List arguments, IProgressMonitor monitor) throws Exception { @@ -253,4 +254,28 @@ public static String getModuleName(IJavaProject project) { } } + private static void reportExportJarMessage(String taskLabel, int severity, String message) { + if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(taskLabel)) { + String readableSeverity = getSeverityString(severity); + JavaLanguageServerPlugin.getInstance().getClientConnection().executeClientCommand(COMMAND_EXPORT_JAR_REPORT, + taskLabel, readableSeverity + ": " + message); + } + } + + private static String getSeverityString(int severity) { + switch (severity) { + case IStatus.INFO: + return "INFO"; + case IStatus.WARNING: + return "WARNING"; + case IStatus.ERROR: + return "ERROR"; + case IStatus.CANCEL: + return "CANCEL"; + case IStatus.OK: + return "OK"; + default: + return "UNKNOWN STATUS"; + } + } } diff --git a/src/commands.ts b/src/commands.ts index 6f2c7fe4..d9ccbc17 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -30,6 +30,8 @@ export namespace Commands { export const VIEW_PACKAGE_EXPORT_JAR = "java.view.package.exportJar"; + export const EXPORT_JAR_REPORT = "java.view.package.exportJarReport"; + export const VIEW_PACKAGE_NEW_JAVA_CLASS = "java.view.package.newJavaClass"; export const VIEW_PACKAGE_NEW_JAVA_PACKAGE = "java.view.package.newPackage"; diff --git a/src/exportJarSteps/ExportJarTaskProvider.ts b/src/exportJarSteps/ExportJarTaskProvider.ts index 1074535e..7796d993 100644 --- a/src/exportJarSteps/ExportJarTaskProvider.ts +++ b/src/exportJarSteps/ExportJarTaskProvider.ts @@ -4,7 +4,7 @@ import { lstat } from "fs-extra"; import * as globby from "globby"; import * as _ from "lodash"; -import { platform } from "os"; +import { EOL, platform } from "os"; import { dirname, extname, isAbsolute, join, relative } from "path"; import { CustomExecution, Event, EventEmitter, Pseudoterminal, Task, TaskDefinition, @@ -44,6 +44,7 @@ export async function executeExportJarTask(node?: INodeData): Promise { isExportingJar = true; const stepMetadata: IStepMetadata = { entry: node, + taskLabel: "exportjar:default", steps: [], projectList: [], elements: [], @@ -55,7 +56,7 @@ export async function executeExportJarTask(node?: INodeData): Promise { throw new Error(ExportJarMessages.stepErrorMessage(ExportJarMessages.StepAction.FINDEXECUTOR, ExportJarStep.ResolveJavaProject)); } await resolveJavaProjectExecutor.execute(stepMetadata); - tasks.executeTask(ExportJarTaskProvider.getTask(stepMetadata)); + tasks.executeTask(ExportJarTaskProvider.getDefaultTask(stepMetadata)); } catch (err) { if (err) { failMessage(`${err}`); @@ -68,13 +69,13 @@ export class ExportJarTaskProvider implements TaskProvider { public static exportJarType: string = "java"; - public static getTask(stepMetadata: IStepMetadata): Task { + public static getDefaultTask(stepMetadata: IStepMetadata): Task { if (!stepMetadata.workspaceFolder) { throw new Error(ExportJarMessages.fieldUndefinedMessage(ExportJarMessages.Field.WORKSPACEFOLDER, ExportJarStep.ResolveTask)); } const defaultDefinition: IExportJarTaskDefinition = { type: ExportJarTaskProvider.exportJarType, - label: `${ExportJarTaskProvider.exportJarType}: exportjar:default`, + label: "exportjar:default", targetPath: Settings.getExportJarTargetPath(), elements: [], mainClass: undefined, @@ -93,9 +94,10 @@ export class ExportJarTaskProvider implements TaskProvider { const definition: IExportJarTaskDefinition = task.definition; const folder: WorkspaceFolder = task.scope; const resolvedTask: Task = new Task(definition, folder, task.name, ExportJarTaskProvider.exportJarType, - new CustomExecution(async (resolvedDefinition: TaskDefinition): Promise => { + new CustomExecution(async (resolvedDefinition: IExportJarTaskDefinition): Promise => { const stepMetadata: IStepMetadata = { entry: undefined, + taskLabel: resolvedDefinition.label || `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`, workspaceFolder: folder, projectList: await Jdtls.getProjects(folder.uri.toString()), steps: [], @@ -139,10 +141,11 @@ export class ExportJarTaskProvider implements TaskProvider { targetPath: Settings.getExportJarTargetPath(), elements: elementList, }; - const defaultTask: Task = new Task(defaultDefinition, folder, `exportjar:${folder.name}`, - ExportJarTaskProvider.exportJarType, new CustomExecution(async (resolvedDefinition: TaskDefinition): Promise => { + const defaultTask: Task = new Task(defaultDefinition, folder, `exportjar:${folder.name}`, ExportJarTaskProvider.exportJarType, + new CustomExecution(async (resolvedDefinition: IExportJarTaskDefinition): Promise => { const stepMetadata: IStepMetadata = { entry: undefined, + taskLabel: resolvedDefinition.label || `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`, workspaceFolder: folder, projectList: await Jdtls.getProjects(folder.uri.toString()), steps: [], @@ -170,11 +173,16 @@ class ExportJarTaskTerminal implements Pseudoterminal { constructor(exportJarTaskDefinition: IExportJarTaskDefinition, stepMetadata: IStepMetadata) { this.stepMetadata = stepMetadata; + this.stepMetadata.taskLabel = exportJarTaskDefinition.label || ""; this.stepMetadata.mainClass = exportJarTaskDefinition.mainClass; this.stepMetadata.outputPath = exportJarTaskDefinition.targetPath; this.stepMetadata.elements = exportJarTaskDefinition.elements || []; } + public handleInput(data: string): void { + this.writeEmitter.fire(data + EOL); + } + public async open(_initialDimensions: TerminalDimensions | undefined): Promise { let exportResult: boolean | undefined; try { diff --git a/src/exportJarSteps/GenerateJarExecutor.ts b/src/exportJarSteps/GenerateJarExecutor.ts index 09d5d8e4..3bd44b36 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, toPosixPath } from "./utility"; +import { createPickBox, ExportJarMessages, ExportJarStep, ExportJarTargets, getExtensionApi, revealTerminal, toPosixPath } from "./utility"; export class GenerateJarExecutor implements IExportJarStepExecutor { @@ -82,12 +82,14 @@ export class GenerateJarExecutor implements IExportJarStepExecutor { if (_.isEmpty(classpaths)) { return reject(new Error(ExportJarMessages.CLASSPATHS_EMPTY)); } - const exportResult: IExportResult | undefined = await Jdtls.exportJar(basename(mainClass), classpaths, destPath, token); - if (exportResult?.result === true) { + revealTerminal(stepMetadata.taskLabel); + const exportResult: boolean | undefined = await Jdtls.exportJar(basename(mainClass), + classpaths, destPath, stepMetadata.taskLabel, token); + if (exportResult === true) { stepMetadata.outputPath = destPath; return resolve(true); } else { - return reject(new Error("Export jar failed." + exportResult?.message)); + return reject(new Error("Export jar failed.")); } }); }); @@ -249,9 +251,3 @@ interface IJarQuickPickItem extends QuickPickItem { path: string; type: string; } - -export interface IExportResult { - result: boolean; - message: string; - log?: string; -} diff --git a/src/exportJarSteps/IStepMetadata.ts b/src/exportJarSteps/IStepMetadata.ts index d4afda56..5e67d29d 100644 --- a/src/exportJarSteps/IStepMetadata.ts +++ b/src/exportJarSteps/IStepMetadata.ts @@ -7,6 +7,7 @@ import { ExportJarStep } from "./utility"; export interface IStepMetadata { entry?: INodeData; + taskLabel: string; workspaceFolder?: WorkspaceFolder; mainClass?: string; outputPath?: string; diff --git a/src/exportJarSteps/utility.ts b/src/exportJarSteps/utility.ts index 9ce26d9d..4ffba226 100644 --- a/src/exportJarSteps/utility.ts +++ b/src/exportJarSteps/utility.ts @@ -153,3 +153,19 @@ 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); + if (presenterTerminals.length > 0) { + presenterTerminals[presenterTerminals.length - 1].show(); + } +} diff --git a/src/java/jdtls.ts b/src/java/jdtls.ts index ada3b6fb..1c94beff 100644 --- a/src/java/jdtls.ts +++ b/src/java/jdtls.ts @@ -3,7 +3,6 @@ import { CancellationToken, commands } from "vscode"; import { Commands, executeJavaLanguageServerCommand } from "../commands"; -import { IExportResult } from "../exportJarSteps/GenerateJarExecutor"; import { IClasspath } from "../exportJarSteps/IStepMetadata"; import { IMainClassInfo } from "../exportJarSteps/ResolveMainClassExecutor"; import { INodeData } from "./nodeData"; @@ -17,7 +16,7 @@ export namespace Jdtls { return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_REFRESH_LIB_SERVER, params); } - export async function getPackageData(params: {[key: string]: any}): Promise { + export async function getPackageData(params: { [key: string]: any }): Promise { return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_GETPACKAGEDATA, params) || []; } @@ -30,9 +29,9 @@ export namespace Jdtls { } export async function exportJar(mainClass: string, classpaths: IClasspath[], - destination: string, token: CancellationToken): Promise { + destination: string, taskLabel: string, token: CancellationToken): Promise { return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_GENERATEJAR, - mainClass, classpaths, destination, token); + mainClass, classpaths, destination, taskLabel, token); } export enum CompileWorkspaceStatus { diff --git a/src/views/dependencyDataProvider.ts b/src/views/dependencyDataProvider.ts index 1afd19db..df2b1cc0 100644 --- a/src/views/dependencyDataProvider.ts +++ b/src/views/dependencyDataProvider.ts @@ -11,6 +11,7 @@ import { contextManager } from "../../extension.bundle"; import { Commands } from "../commands"; import { Context } from "../constants"; import { executeExportJarTask } from "../exportJarSteps/ExportJarTaskProvider"; +import { showExportJarReport } from "../exportJarSteps/utility"; import { Jdtls } from "../java/jdtls"; import { INodeData, NodeKind } from "../java/nodeData"; import { languageServerApiManager } from "../languageServerApi/languageServerApiManager"; @@ -35,6 +36,9 @@ 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(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_EXPORT_JAR, async (node: INodeData) => { executeExportJarTask(node); })); From cf1b1e2a50ddcfe167a04c336d6a8034f0714372 Mon Sep 17 00:00:00 2001 From: Shi Chen Date: Thu, 20 May 2021 18:18:28 +0800 Subject: [PATCH 2/3] address comment --- src/exportJarSteps/ExportJarTaskProvider.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/exportJarSteps/ExportJarTaskProvider.ts b/src/exportJarSteps/ExportJarTaskProvider.ts index 7796d993..669fdc92 100644 --- a/src/exportJarSteps/ExportJarTaskProvider.ts +++ b/src/exportJarSteps/ExportJarTaskProvider.ts @@ -97,7 +97,7 @@ export class ExportJarTaskProvider implements TaskProvider { new CustomExecution(async (resolvedDefinition: IExportJarTaskDefinition): Promise => { const stepMetadata: IStepMetadata = { entry: undefined, - taskLabel: resolvedDefinition.label || `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`, + taskLabel: resolvedDefinition.label || `exportjar:${folder.name}`, workspaceFolder: folder, projectList: await Jdtls.getProjects(folder.uri.toString()), steps: [], @@ -136,7 +136,6 @@ export class ExportJarTaskProvider implements TaskProvider { const mainClasses: IMainClassInfo[] = await Jdtls.getMainClasses(folder.uri.toString()); const defaultDefinition: IExportJarTaskDefinition = { type: ExportJarTaskProvider.exportJarType, - label: `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`, mainClass: (mainClasses.length === 1) ? mainClasses[0].name : undefined, targetPath: Settings.getExportJarTargetPath(), elements: elementList, @@ -145,7 +144,7 @@ export class ExportJarTaskProvider implements TaskProvider { new CustomExecution(async (resolvedDefinition: IExportJarTaskDefinition): Promise => { const stepMetadata: IStepMetadata = { entry: undefined, - taskLabel: resolvedDefinition.label || `${ExportJarTaskProvider.exportJarType}: exportjar:${folder.name}`, + taskLabel: resolvedDefinition.label || `exportjar:${folder.name}`, workspaceFolder: folder, projectList: await Jdtls.getProjects(folder.uri.toString()), steps: [], From 1fec3ce0f3e8e5f7fbeeb7f8bb7bdb7232f1d822 Mon Sep 17 00:00:00 2001 From: Shi Chen Date: Thu, 20 May 2021 23:12:26 +0800 Subject: [PATCH 3/3] refine report wording --- .../src/com/microsoft/jdtls/ext/core/ProjectCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 e77ffeed..cb3fcdda 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 @@ -164,7 +164,7 @@ 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 export " + path.getFileName().toString()); + reportExportJarMessage(taskLabel, IStatus.OK, "Successfully added the file to the exported jar: " + path.getFileName().toString()); continue; } if (resultStatus.isMultiStatus()) { @@ -178,7 +178,7 @@ public static boolean exportJar(List arguments, IProgressMonitor monitor try { writeFile(new File(classpath.source), new Path(classpath.destination), /* areDirectoryEntriesIncluded = */true, /* isCompressed = */true, target, directories); - reportExportJarMessage(taskLabel, IStatus.OK, "successfully export " + classpath.destination); + reportExportJarMessage(taskLabel, IStatus.OK, "Successfully added the file to the exported jar: " + classpath.destination); } catch (CoreException e) { reportExportJarMessage(taskLabel, IStatus.ERROR, e.getMessage()); } @@ -258,7 +258,7 @@ private static void reportExportJarMessage(String taskLabel, int severity, Strin if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(taskLabel)) { String readableSeverity = getSeverityString(severity); JavaLanguageServerPlugin.getInstance().getClientConnection().executeClientCommand(COMMAND_EXPORT_JAR_REPORT, - taskLabel, readableSeverity + ": " + message); + taskLabel, "[" + readableSeverity + "] " + message); } }