Skip to content

Commit b8548d6

Browse files
Check extension existence on-the-fly when needed (#911)
* feat: do JIT extension check on command execution * chore: revise extension install UX * chore: UX update * chore: bump to 0.25.2
1 parent 64737bc commit b8548d6

File tree

8 files changed

+83
-24
lines changed

8 files changed

+83
-24
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to the "vscode-java-dependency" extension will be documented
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## 0.25.2
8+
9+
- ux - Check extension existence on-the-fly when needed by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/911
10+
711
## 0.25.0
812
- feat - Remind users to upgrade old (<21) Java and EOL Spring Boot/Framework versions by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/901
913
- feat - Improve ProjectCommand.getMainClasses by @snjeza in https://github.com/microsoft/vscode-java-dependency/pull/883

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-java-dependency",
33
"displayName": "Project Manager for Java",
44
"description": "%description%",
5-
"version": "0.25.0",
5+
"version": "0.25.2",
66
"publisher": "vscjava",
77
"preview": false,
88
"aiKey": "5c642b22-e845-4400-badb-3f8509a70777",
@@ -593,7 +593,7 @@
593593
},
594594
{
595595
"command": "_java.view.modernizeJavaProject",
596-
"when": "explorerResourceIsFolder && java:serverMode && isModernizationExtensionInstalled",
596+
"when": "explorerResourceIsFolder && java:serverMode",
597597
"group": "1_javaactions@40"
598598
},
599599
{

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export namespace ExtensionName {
3535
export const JAVA_LANGUAGE_SUPPORT: string = "redhat.java";
3636
export const APP_MODERNIZATION_FOR_JAVA = "vscjava.migrate-java-to-azure";
3737
export const APP_MODERNIZATION_UPGRADE_FOR_JAVA = "vscjava.vscode-java-upgrade";
38+
export const APP_MODERNIZATION_EXTENSION_NAME = "GitHub Copilot app modernization";
3839
}
3940

4041
export namespace Upgrade {

src/upgrade/dependency.metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const DEPENDENCY_JAVA_RUNTIME = {
1111
"reason": UpgradeReason.JRE_TOO_OLD,
1212
"supportedVersion": `>=${LATEST_JAVA_LTS_VESRION}`,
1313
"suggestedVersion": {
14-
"name": String(LATEST_JAVA_LTS_VESRION),
14+
"name": `Java ${LATEST_JAVA_LTS_VESRION}`,
1515
"description": "latest LTS version",
1616
},
1717
} as const;

src/upgrade/display/notificationManager.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import { commands, ExtensionContext, window } from "vscode";
4+
import { commands, ExtensionContext, extensions, window } from "vscode";
55
import type { IUpgradeIssuesRenderer, UpgradeIssue } from "../type";
66
import { buildFixPrompt, buildNotificationMessage } from "../utility";
77
import { Commands } from "../../commands";
88
import { Settings } from "../../settings";
99
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
10+
import { ExtensionName } from "../../constants";
1011

1112
const KEY_PREFIX = 'javaupgrade.notificationManager';
1213
const NEXT_SHOW_TS_KEY = `${KEY_PREFIX}.nextShowTs`;
1314

1415
const BUTTON_TEXT_UPGRADE = "Upgrade Now";
16+
const BUTTON_TEXT_INSTALL_AND_UPGRADE = "Install Extension and Upgrade";
1517
const BUTTON_TEXT_NOT_NOW = "Not Now";
1618

1719
const SECONDS_IN_A_DAY = 24 * 60 * 60;
@@ -47,19 +49,21 @@ class NotificationManager implements IUpgradeIssuesRenderer {
4749
}
4850
this.hasShown = true;
4951

52+
const hasExtension = !!extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
5053
const prompt = buildFixPrompt(issue);
51-
const notificationMessage = buildNotificationMessage(issue);
54+
const notificationMessage = buildNotificationMessage(issue, hasExtension);
55+
const upgradeButtonText = hasExtension ? BUTTON_TEXT_UPGRADE : BUTTON_TEXT_INSTALL_AND_UPGRADE;
5256
const selection = await window.showInformationMessage(
5357
notificationMessage,
54-
BUTTON_TEXT_UPGRADE,
58+
upgradeButtonText,
5559
BUTTON_TEXT_NOT_NOW);
5660
sendInfo(operationId, {
5761
operationName: "java.dependency.upgradeNotification.runUpgrade",
5862
choice: selection ?? "",
5963
});
6064

6165
switch (selection) {
62-
case BUTTON_TEXT_UPGRADE: {
66+
case upgradeButtonText: {
6367
commands.executeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, prompt);
6468
break;
6569
}

src/upgrade/upgradeManager.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import { commands, type ExtensionContext, extensions, workspace, type WorkspaceFolder } from "vscode";
4+
import { commands, type ExtensionContext, workspace, type WorkspaceFolder } from "vscode";
55

66
import { Jdtls } from "../java/jdtls";
77
import { languageServerApiManager } from "../languageServerApi/languageServerApiManager";
@@ -11,28 +11,33 @@ import { Commands } from "../commands";
1111
import notificationManager from "./display/notificationManager";
1212
import { Settings } from "../settings";
1313
import assessmentManager from "./assessmentManager";
14+
import { checkOrInstallAppModExtension, checkOrPromptToInstallAppModExtension } from "./utility";
1415

1516
const DEFAULT_UPGRADE_PROMPT = "Upgrade Java project dependency to latest version.";
1617

1718

1819
function shouldRunCheckup() {
19-
return Settings.getEnableDependencyCheckup()
20-
&& !!extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
20+
return Settings.getEnableDependencyCheckup();
2121
}
2222

2323
class UpgradeManager {
2424
public static initialize(context: ExtensionContext) {
2525
notificationManager.initialize(context);
2626

27-
// Commands to be used
27+
// Upgrade project
2828
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, async (promptText?: string) => {
29+
await checkOrInstallAppModExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
2930
const promptToUse = promptText ?? DEFAULT_UPGRADE_PROMPT;
3031
await commands.executeCommand(Commands.GOTO_AGENT_MODE, { prompt: promptToUse });
3132
}));
32-
commands.executeCommand('setContext', 'isModernizationExtensionInstalled',
33-
!!extensions.getExtension(ExtensionName.APP_MODERNIZATION_FOR_JAVA));
34-
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MODERNIZE_JAVA_PROJECT, () => {
35-
commands.executeCommand("workbench.view.extension.azureJavaMigrationExplorer");
33+
34+
// Show modernization view
35+
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MODERNIZE_JAVA_PROJECT, async () => {
36+
await checkOrPromptToInstallAppModExtension(
37+
ExtensionName.APP_MODERNIZATION_FOR_JAVA,
38+
"Install GitHub Copilot app modernization to modernize the Java project.",
39+
"Install Extension and Modernize");
40+
await commands.executeCommand("workbench.view.extension.azureJavaMigrationExplorer");
3641
}));
3742

3843
UpgradeManager.scan();

src/upgrade/utility.ts

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import { Uri } from "vscode";
4+
import { commands, extensions, Uri, window } from "vscode";
55
import * as semver from "semver";
66
import { UpgradeReason, type UpgradeIssue } from "./type";
7-
import { Upgrade } from "../constants";
7+
import { ExtensionName, Upgrade } from "../constants";
88

99

1010
function findEolDate(currentVersion: string, eolDate: Record<string, string>): string | null {
@@ -20,7 +20,7 @@ function findEolDate(currentVersion: string, eolDate: Record<string, string>): s
2020
return null;
2121
}
2222

23-
export function buildNotificationMessage(issue: UpgradeIssue): string {
23+
export function buildNotificationMessage(issue: UpgradeIssue, hasExtension: boolean): string {
2424
const {
2525
packageId,
2626
currentVersion,
@@ -29,21 +29,22 @@ export function buildNotificationMessage(issue: UpgradeIssue): string {
2929
packageDisplayName
3030
} = issue;
3131

32+
const upgradeWord = hasExtension ? "upgrade" : `install ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and upgrade`;
3233

3334
if (packageId === Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME) {
34-
return `The current project is using an older Java runtime (${currentVersion}). Do you want to upgrade to the latest LTS version ${suggestedVersionName}?`;
35+
return `This project is using an older Java runtime (${currentVersion}). Would you like to ${upgradeWord} it to ${suggestedVersionName} (latest LTS)?`;
3536
}
3637

3738
switch (reason) {
3839
case UpgradeReason.END_OF_LIFE: {
3940
const { eolDate } = issue;
4041
const versionEolDate = findEolDate(currentVersion, eolDate);
41-
return `The current project is using ${packageDisplayName} ${currentVersion}, which has reached end of life${versionEolDate ? ` in ${versionEolDate}` : ""
42-
}. Do you want to upgrade to ${suggestedVersionName} (${suggestedVersionDescription})?`;
42+
return `This project is using ${packageDisplayName} ${currentVersion}, which has reached end of life${versionEolDate ? ` in ${versionEolDate}` : ""
43+
}. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`;
4344
}
4445
case UpgradeReason.DEPRECATED:
4546
default: {
46-
return `The current project is using ${packageDisplayName} ${currentVersion}, which has been deprecated. Do you want to upgrade to ${suggestedVersionName} (${suggestedVersionDescription})?`;
47+
return `This project is using ${packageDisplayName} ${currentVersion}, which has been deprecated. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`;
4748
}
4849
}
4950
}
@@ -73,3 +74,47 @@ export function normalizePath(path: string): string {
7374
return Uri.parse(path).toString();
7475
}
7576

77+
async function checkOrPromptToEnableAppModExtension() {
78+
if (extensions.getExtension(ExtensionName.APP_MODERNIZATION_FOR_JAVA)) {
79+
return;
80+
}
81+
82+
// The extension is disabled if we cannot detect the extension after installing it.
83+
await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
84+
const BTN_TEXT = "Show extension in sidebar";
85+
const choice2 = await window.showInformationMessage(
86+
`${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension is needed for the feature to work but it seems disabled. Please enable it manually and try again.`,
87+
BTN_TEXT
88+
);
89+
if (choice2 === BTN_TEXT) {
90+
await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
91+
}
92+
}
93+
94+
export async function checkOrPromptToInstallAppModExtension(
95+
extensionIdToCheck: string,
96+
notificationText: string,
97+
buttonText: string): Promise<void> {
98+
if (extensions.getExtension(extensionIdToCheck)) {
99+
return;
100+
}
101+
102+
const choice = await window.showInformationMessage(notificationText, buttonText);
103+
if (choice === buttonText) {
104+
await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
105+
} else {
106+
return;
107+
}
108+
109+
await checkOrPromptToEnableAppModExtension();
110+
}
111+
112+
export async function checkOrInstallAppModExtension(
113+
extensionIdToCheck: string): Promise<void> {
114+
if (extensions.getExtension(extensionIdToCheck)) {
115+
return;
116+
}
117+
118+
await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
119+
await checkOrPromptToEnableAppModExtension();
120+
}

0 commit comments

Comments
 (0)