From 8757c72e0c9e03e6fdecd6e2825c1b75a9ac7bd8 Mon Sep 17 00:00:00 2001 From: Gustavo Simon Date: Sun, 6 Nov 2022 14:43:53 -0300 Subject: [PATCH 1/4] Created new Favorites Menu as described in the issue #884 --- package.json | 22 ++++++++++++++- src/Settings.ts | 8 ++++-- src/explorer/model/FavoriteCommand.ts | 23 ++++++++++++++++ src/explorer/model/FavoritesMenu.ts | 27 +++++++++++++++++++ src/explorer/model/ITreeItem.ts | 1 + src/explorer/model/LifecycleMenu.ts | 1 + src/explorer/model/LifecyclePhase.ts | 6 ++--- src/explorer/model/MavenProject.ts | 2 ++ src/extension.ts | 1 + src/handlers/runFavoriteCommandsHandler.ts | 31 ++++++++++++---------- src/utils/Utils.ts | 10 +++++++ 11 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 src/explorer/model/FavoriteCommand.ts create mode 100644 src/explorer/model/FavoritesMenu.ts diff --git a/package.json b/package.json index 56634457..26c18dfb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-maven", "displayName": "Maven for Java", "description": "%description%", - "version": "0.39.0", + "version": "0.40.0", "icon": "resources/logo.png", "publisher": "vscjava", "preview": true, @@ -171,6 +171,12 @@ "category": "Maven", "icon": "$(play)" }, + { + "command": "maven.goal.execute.fromFavoritesMenu", + "title": "%contributes.commands.maven.plugin.execute%", + "category": "Maven", + "icon": "$(play)" + }, { "command": "maven.plugin.execute", "title": "%contributes.commands.maven.plugin.execute%", @@ -322,6 +328,10 @@ "command": "maven.goal.execute.fromLifecycleMenu", "when": "never" }, + { + "command": "maven.goal.execute.fromFavoritesMenu", + "when": "never" + }, { "command": "maven.plugin.execute", "when": "never" @@ -560,6 +570,16 @@ "command": "maven.goal.execute.fromLifecycleMenu", "when": "view == mavenProjects && viewItem == maven:lifecycle", "group": "1@1" + }, + { + "command": "maven.goal.execute.fromFavoritesMenu", + "when": "view == mavenProjects && viewItem == maven:favorites", + "group": "inline" + }, + { + "command": "maven.goal.execute.fromFavoritesMenu", + "when": "view == mavenProjects && viewItem == maven:favorites", + "group": "1@1" } ], "javaProject.maven": [ diff --git a/src/Settings.ts b/src/Settings.ts index f0627314..52f52bb9 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -1,7 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +import * as vscode from "vscode"; import { Uri, workspace } from "vscode"; +import { FavoriteCommand } from "./explorer/model/FavoriteCommand"; +import { MavenProject } from "./explorer/model/MavenProject"; export namespace Settings { export function excludedFolders(resource: Uri): string[] { @@ -59,8 +62,9 @@ export namespace Settings { return _getMavenSection("terminal.customEnv", resourceOrFilepath); } - export function favorites(resource: Uri): { alias: string; command: string }[] | undefined { - return _getMavenSection("terminal.favorites", resource); + export function favorites(project: MavenProject): FavoriteCommand[] | undefined { + const favorites: {alias: string, command: string, debug?: boolean}[] | undefined = _getMavenSection("terminal.favorites", vscode.Uri.file(project.pomPath)); + return favorites?.map(favorite => new FavoriteCommand(project, favorite.command, favorite.alias, favorite.debug)); } } export namespace Executable { diff --git a/src/explorer/model/FavoriteCommand.ts b/src/explorer/model/FavoriteCommand.ts new file mode 100644 index 00000000..fcb75d1e --- /dev/null +++ b/src/explorer/model/FavoriteCommand.ts @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { TreeItem } from "vscode"; +import { ITreeItem } from "./ITreeItem"; +import { MavenProject } from "./MavenProject"; + +export class FavoriteCommand implements ITreeItem { + + constructor(public project: MavenProject, public command: string, public alias: string, public debug?: boolean) {} + + getContextValue(): string { + return "maven:favorites"; + } + + getTreeItem(): TreeItem | Thenable { + const treeItem: vscode.TreeItem = new vscode.TreeItem(this.alias, vscode.TreeItemCollapsibleState.None); + treeItem.iconPath = new vscode.ThemeIcon("gear"); + return treeItem; + } + +} diff --git a/src/explorer/model/FavoritesMenu.ts b/src/explorer/model/FavoritesMenu.ts new file mode 100644 index 00000000..2cbf0fb6 --- /dev/null +++ b/src/explorer/model/FavoritesMenu.ts @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; +import { Menu } from "./Menu"; +import { ITreeItem } from "./ITreeItem"; +import { MavenProject } from "./MavenProject"; +import { FavoriteCommand } from "./FavoriteCommand"; +import { Settings } from "../../Settings"; + +export class FavoritesMenu extends Menu implements ITreeItem { + + constructor(project: MavenProject) { + super(project); + this.name = "Favorites"; + } + + public async getChildren(): Promise { + return Settings.Terminal.favorites(this.project); + } + + public getTreeItem(): vscode.TreeItem | Thenable { + const treeItem: vscode.TreeItem = new vscode.TreeItem(this.name, vscode.TreeItemCollapsibleState.Collapsed); + treeItem.iconPath = new vscode.ThemeIcon("star-empty"); + return treeItem; + } +} \ No newline at end of file diff --git a/src/explorer/model/ITreeItem.ts b/src/explorer/model/ITreeItem.ts index f77af9e0..b64d6431 100644 --- a/src/explorer/model/ITreeItem.ts +++ b/src/explorer/model/ITreeItem.ts @@ -11,6 +11,7 @@ export interface ITreeItem { * If implemented, it will be triggered to get children items. */ getChildren?(): ITreeItem[] | undefined | Promise; + /** * If implemented, it will be triggered to refresh tree item. */ diff --git a/src/explorer/model/LifecycleMenu.ts b/src/explorer/model/LifecycleMenu.ts index c6d91af6..cce5bb9a 100644 --- a/src/explorer/model/LifecycleMenu.ts +++ b/src/explorer/model/LifecycleMenu.ts @@ -9,6 +9,7 @@ import { MavenProject } from "./MavenProject"; import { Menu } from "./Menu"; export class LifecycleMenu extends Menu implements ITreeItem { + constructor(project: MavenProject) { super(project); this.name = "Lifecycle"; diff --git a/src/explorer/model/LifecyclePhase.ts b/src/explorer/model/LifecyclePhase.ts index 14b291af..49f6ce33 100644 --- a/src/explorer/model/LifecyclePhase.ts +++ b/src/explorer/model/LifecyclePhase.ts @@ -1,4 +1,3 @@ - // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. @@ -7,12 +6,13 @@ import { ITreeItem } from "./ITreeItem"; import { MavenProject } from "./MavenProject"; export class LifecyclePhase implements ITreeItem { - constructor(public project: MavenProject, public phase: string) { - } + + constructor(public project: MavenProject, public phase: string) {} public getContextValue(): string { return "maven:lifecycle"; } + public getTreeItem(): vscode.TreeItem | Thenable { const treeItem: vscode.TreeItem = new vscode.TreeItem(this.phase, vscode.TreeItemCollapsibleState.None); treeItem.iconPath = new vscode.ThemeIcon("gear"); diff --git a/src/explorer/model/MavenProject.ts b/src/explorer/model/MavenProject.ts index 24034fc1..6efc425e 100644 --- a/src/explorer/model/MavenProject.ts +++ b/src/explorer/model/MavenProject.ts @@ -18,6 +18,7 @@ import { ITreeItem } from "./ITreeItem"; import { LifecycleMenu } from "./LifecycleMenu"; import { MavenPlugin } from "./MavenPlugin"; import { PluginsMenu } from "./PluginsMenu"; +import { FavoritesMenu } from "./FavoritesMenu"; const CONTEXT_VALUE: string = "maven:project"; @@ -165,6 +166,7 @@ export class MavenProject implements ITreeItem { ret.push(new LifecycleMenu(this)); ret.push(new PluginsMenu(this)); ret.push(new DependenciesMenu(this)); + ret.push(new FavoritesMenu(this)); if (this.moduleNames.length > 0 && Settings.viewType() === "hierarchical") { const projects: MavenProject[] = this.modules.map(m => MavenProjectManager.get(m)).filter(Boolean) as MavenProject[]; ret.push(...projects); diff --git a/src/extension.ts b/src/extension.ts index 50cdcdf0..6f361455 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -97,6 +97,7 @@ async function doActivate(_operationId: string, context: vscode.ExtensionContext registerCommandRequiringTrust(context, "maven.goal.execute", Utils.executeMavenCommand); registerCommandRequiringTrust(context, "maven.goal.execute.fromProjectManager", Utils.executeMavenCommand); registerCommandRequiringTrust(context, "maven.goal.execute.fromLifecycleMenu", Utils.executeMavenCommand); + registerCommandRequiringTrust(context, "maven.goal.execute.fromFavoritesMenu", Utils.executeMavenCommand); registerCommandRequiringTrust(context, "maven.plugin.execute", async (pluginGoal: PluginGoal) => await executeInTerminal({ command: pluginGoal.name, pomfile: pluginGoal.plugin.project.pomPath })); registerCommand(context, "maven.view.flat", () => Settings.changeToFlatView()); registerCommand(context, "maven.view.hierarchical", () => Settings.changeToHierarchicalView()); diff --git a/src/handlers/runFavoriteCommandsHandler.ts b/src/handlers/runFavoriteCommandsHandler.ts index 02329f39..78889f63 100644 --- a/src/handlers/runFavoriteCommandsHandler.ts +++ b/src/handlers/runFavoriteCommandsHandler.ts @@ -8,9 +8,9 @@ import { Settings } from "../Settings"; import { executeInTerminal } from "../utils/mavenUtils"; import { selectProjectIfNecessary } from "../utils/uiUtils"; import { debugCommand, IDebugOptions } from "./debugHandler"; +import { FavoriteCommand } from "../explorer/model/FavoriteCommand"; -type FavoriteCommand = { command: string, alias: string, debug?: boolean }; -export async function runFavoriteCommandsHandler(project: MavenProject | undefined): Promise { +export async function runFavoriteCommandsHandler(project: MavenProject | undefined, command?: FavoriteCommand): Promise { let selectedProject: MavenProject | undefined = project; if (!selectedProject) { selectedProject = await selectProjectIfNecessary(); @@ -18,7 +18,7 @@ export async function runFavoriteCommandsHandler(project: MavenProject | undefin if (!selectedProject) { return; } - const favorites: FavoriteCommand[] | undefined = Settings.Terminal.favorites(vscode.Uri.file(selectedProject.pomPath)); + const favorites: FavoriteCommand[] | undefined = Settings.Terminal.favorites(selectedProject); if (!favorites || _.isEmpty(favorites)) { const BUTTON_OPEN_SETTINGS: string = "Open Settings"; const choice: string | undefined = await vscode.window.showInformationMessage("Found no favorite commands. You can specify `maven.terminal.favorites` in Settings.", BUTTON_OPEN_SETTINGS); @@ -28,17 +28,20 @@ export async function runFavoriteCommandsHandler(project: MavenProject | undefin return; } - const selectedCommand: FavoriteCommand | undefined = await vscode.window.showQuickPick( - favorites.map(item => ({ - value: item, - label: item.alias, - description: item.command - })), { - ignoreFocusOut: true, - placeHolder: "Select a favorite command ...", - matchOnDescription: true - } - ).then(item => item ? item.value : undefined); + let selectedCommand: FavoriteCommand | undefined = command; + if (!selectedCommand) { + selectedCommand = await vscode.window.showQuickPick( + favorites.map(item => ({ + value: item, + label: item.alias, + description: item.command + })), { + ignoreFocusOut: true, + placeHolder: "Select a favorite command ...", + matchOnDescription: true + } + ).then(item => item ? item.value : undefined); + } if (!selectedCommand) { return; } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index f6065aef..2bc36f63 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -11,8 +11,10 @@ import { commands, Progress, ProgressLocation, Uri, window } from "vscode"; import { createUuid, setUserError } from "vscode-extension-telemetry-wrapper"; import * as xml2js from "xml2js"; import { DEFAULT_MAVEN_LIFECYCLES } from "../completion/constants"; +import { FavoriteCommand } from "../explorer/model/FavoriteCommand"; import { LifecyclePhase } from "../explorer/model/LifecyclePhase"; import { MavenProject } from "../explorer/model/MavenProject"; +import { runFavoriteCommandsHandler } from "../handlers/runFavoriteCommandsHandler"; import { MavenProjectManager } from "../project/MavenProjectManager"; import { Settings } from "../Settings"; import { getExtensionVersion, getPathToTempFolder, getPathToWorkspaceStorage } from "./contextUtils"; @@ -211,6 +213,9 @@ export namespace Utils { if (node instanceof LifecyclePhase) { selectedProject = node.project; selectedCommand = node.phase; + } else if (node instanceof FavoriteCommand) { + selectedProject = node.project; + selectedCommand = node.command; } else if (node && node.uri) { // for nodes from Project Manager const pomPath: string = path.join(Uri.parse(node.uri).fsPath, "pom.xml"); @@ -250,6 +255,11 @@ export namespace Utils { } } + if (node instanceof FavoriteCommand){ + await runFavoriteCommandsHandler(selectedProject, node); + return; + } + await commands.executeCommand(`maven.goal.${selectedCommand}`, selectedProject); } From 6ccd5118c3d43c43275cc4a609f56b811a64c61f Mon Sep 17 00:00:00 2001 From: Gustavo Simon Date: Mon, 7 Nov 2022 13:27:22 -0300 Subject: [PATCH 2/4] Added the command into items description of Favorites Menu. --- CHANGELOG.md | 4 ++++ src/explorer/model/FavoriteCommand.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a0ad2b..df3e26c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to the "vscode-maven" extension will be documented in this file. +## 0.40.0 +### Added +- Created a new FavoritesMenu. This menu allows shortcuts to execute the favorite commands. [#884](https://github.com/microsoft/vscode-maven/issues/884) + ## 0.39.2 ### Fixed - Input boxes freeze when value is invalid, since VS Code v1.73.0. [#896](https://github.com/microsoft/vscode-maven/issues/896) diff --git a/src/explorer/model/FavoriteCommand.ts b/src/explorer/model/FavoriteCommand.ts index fcb75d1e..aa875027 100644 --- a/src/explorer/model/FavoriteCommand.ts +++ b/src/explorer/model/FavoriteCommand.ts @@ -16,6 +16,7 @@ export class FavoriteCommand implements ITreeItem { getTreeItem(): TreeItem | Thenable { const treeItem: vscode.TreeItem = new vscode.TreeItem(this.alias, vscode.TreeItemCollapsibleState.None); + treeItem.description = this.command; treeItem.iconPath = new vscode.ThemeIcon("gear"); return treeItem; } From eb2a6dd8e186d1106622769910cc0ca0ece853cd Mon Sep 17 00:00:00 2001 From: Gustavo Simon Date: Tue, 8 Nov 2022 08:36:22 -0300 Subject: [PATCH 3/4] Fixing linting issues --- src/Settings.ts | 4 ++-- src/explorer/model/FavoriteCommand.ts | 4 ++-- src/explorer/model/ITreeItem.ts | 2 +- src/utils/Utils.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Settings.ts b/src/Settings.ts index 52f52bb9..d397da4b 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -63,8 +63,8 @@ export namespace Settings { } export function favorites(project: MavenProject): FavoriteCommand[] | undefined { - const favorites: {alias: string, command: string, debug?: boolean}[] | undefined = _getMavenSection("terminal.favorites", vscode.Uri.file(project.pomPath)); - return favorites?.map(favorite => new FavoriteCommand(project, favorite.command, favorite.alias, favorite.debug)); + type Favorite = {alias: string, command: string, debug?: boolean}; + return _getMavenSection("terminal.favorites", vscode.Uri.file(project.pomPath))?.map(favorite => new FavoriteCommand(project, favorite.command, favorite.alias, favorite.debug)); } } export namespace Executable { diff --git a/src/explorer/model/FavoriteCommand.ts b/src/explorer/model/FavoriteCommand.ts index aa875027..ce833bc5 100644 --- a/src/explorer/model/FavoriteCommand.ts +++ b/src/explorer/model/FavoriteCommand.ts @@ -7,7 +7,7 @@ import { ITreeItem } from "./ITreeItem"; import { MavenProject } from "./MavenProject"; export class FavoriteCommand implements ITreeItem { - + constructor(public project: MavenProject, public command: string, public alias: string, public debug?: boolean) {} getContextValue(): string { @@ -20,5 +20,5 @@ export class FavoriteCommand implements ITreeItem { treeItem.iconPath = new vscode.ThemeIcon("gear"); return treeItem; } - + } diff --git a/src/explorer/model/ITreeItem.ts b/src/explorer/model/ITreeItem.ts index b64d6431..111e4820 100644 --- a/src/explorer/model/ITreeItem.ts +++ b/src/explorer/model/ITreeItem.ts @@ -11,7 +11,7 @@ export interface ITreeItem { * If implemented, it will be triggered to get children items. */ getChildren?(): ITreeItem[] | undefined | Promise; - + /** * If implemented, it will be triggered to refresh tree item. */ diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 2bc36f63..e27e294c 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -259,7 +259,7 @@ export namespace Utils { await runFavoriteCommandsHandler(selectedProject, node); return; } - + await commands.executeCommand(`maven.goal.${selectedCommand}`, selectedProject); } From 0692f665191d79cd417553b0592f6e988de4d23b Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Tue, 8 Nov 2022 21:02:39 +0800 Subject: [PATCH 4/4] make TS compiler happy --- src/completion/providers/ArtifactProvider.ts | 2 +- src/utils/contextUtils.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/completion/providers/ArtifactProvider.ts b/src/completion/providers/ArtifactProvider.ts index 40b21393..4d11966a 100644 --- a/src/completion/providers/ArtifactProvider.ts +++ b/src/completion/providers/ArtifactProvider.ts @@ -75,7 +75,7 @@ export class ArtifactProvider implements IXmlCompletionProvider { // also update corresponding groupId node if (groupIdTextNode && groupIdTextNode.startIndex !== null && groupIdTextNode.endIndex !== null) { for (const item of mergedItems) { - const matchedGroupId: string = _.get(item, "data.groupId"); + const matchedGroupId: string | undefined = _.get(item, "data.groupId"); if (matchedGroupId) { const groupIdRange: vscode.Range | undefined = getRange(groupIdTextNode, document); if (groupIdRange){ diff --git a/src/utils/contextUtils.ts b/src/utils/contextUtils.ts index ad832148..58b009b3 100644 --- a/src/utils/contextUtils.ts +++ b/src/utils/contextUtils.ts @@ -43,8 +43,11 @@ export async function loadMavenSettingsFilePath(): Promise { userSettingsPath = path.join(os.homedir(), ".m2", "settings.xml"); } const userSettings: {} | undefined = await Utils.parseXmlFile(userSettingsPath); - MAVEN_LOCAL_REPOSITORY = path.resolve(_.get(userSettings, "settings.localRepository[0]")); - mavenOutputChannel.appendLine(`local repository: ${MAVEN_LOCAL_REPOSITORY}`); + const localRepository = _.get(userSettings, "settings.localRepository[0]"); + if (localRepository) { + MAVEN_LOCAL_REPOSITORY = path.resolve(); + mavenOutputChannel.appendLine(`local repository: ${MAVEN_LOCAL_REPOSITORY}`); + } } catch (error) { // ignore }