Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to the "vscode-java-dependency" extension will be documented
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 0.25.2

- ux - Check extension existence on-the-fly when needed by @FluoriteCafe-work in https://github.com/microsoft/vscode-java-dependency/pull/911

## 0.25.0
- 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
- feat - Improve ProjectCommand.getMainClasses by @snjeza in https://github.com/microsoft/vscode-java-dependency/pull/883
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-java-dependency",
"displayName": "Project Manager for Java",
"description": "%description%",
"version": "0.25.0",
"version": "0.25.2",
"publisher": "vscjava",
"preview": false,
"aiKey": "5c642b22-e845-4400-badb-3f8509a70777",
Expand Down Expand Up @@ -593,7 +593,7 @@
},
{
"command": "_java.view.modernizeJavaProject",
"when": "explorerResourceIsFolder && java:serverMode && isModernizationExtensionInstalled",
"when": "explorerResourceIsFolder && java:serverMode",
"group": "1_javaactions@40"
},
{
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export namespace ExtensionName {
export const JAVA_LANGUAGE_SUPPORT: string = "redhat.java";
export const APP_MODERNIZATION_FOR_JAVA = "vscjava.migrate-java-to-azure";
export const APP_MODERNIZATION_UPGRADE_FOR_JAVA = "vscjava.vscode-java-upgrade";
export const APP_MODERNIZATION_EXTENSION_NAME = "GitHub Copilot app modernization";
}

export namespace Upgrade {
Expand Down
2 changes: 1 addition & 1 deletion src/upgrade/dependency.metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const DEPENDENCY_JAVA_RUNTIME = {
"reason": UpgradeReason.JRE_TOO_OLD,
"supportedVersion": `>=${LATEST_JAVA_LTS_VESRION}`,
"suggestedVersion": {
"name": String(LATEST_JAVA_LTS_VESRION),
"name": `Java ${LATEST_JAVA_LTS_VESRION}`,
"description": "latest LTS version",
},
} as const;
Expand Down
12 changes: 8 additions & 4 deletions src/upgrade/display/notificationManager.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import { commands, ExtensionContext, window } from "vscode";
import { commands, ExtensionContext, extensions, window } from "vscode";
import type { IUpgradeIssuesRenderer, UpgradeIssue } from "../type";
import { buildFixPrompt, buildNotificationMessage } from "../utility";
import { Commands } from "../../commands";
import { Settings } from "../../settings";
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
import { ExtensionName } from "../../constants";

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

const BUTTON_TEXT_UPGRADE = "Upgrade Now";
const BUTTON_TEXT_INSTALL_AND_UPGRADE = "Install Extension and Upgrade";
const BUTTON_TEXT_NOT_NOW = "Not Now";

const SECONDS_IN_A_DAY = 24 * 60 * 60;
Expand Down Expand Up @@ -47,19 +49,21 @@ class NotificationManager implements IUpgradeIssuesRenderer {
}
this.hasShown = true;

const hasExtension = !!extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
const prompt = buildFixPrompt(issue);
const notificationMessage = buildNotificationMessage(issue);
const notificationMessage = buildNotificationMessage(issue, hasExtension);
const upgradeButtonText = hasExtension ? BUTTON_TEXT_UPGRADE : BUTTON_TEXT_INSTALL_AND_UPGRADE;
const selection = await window.showInformationMessage(
notificationMessage,
BUTTON_TEXT_UPGRADE,
upgradeButtonText,
BUTTON_TEXT_NOT_NOW);
sendInfo(operationId, {
operationName: "java.dependency.upgradeNotification.runUpgrade",
choice: selection ?? "",
});

switch (selection) {
case BUTTON_TEXT_UPGRADE: {
case upgradeButtonText: {
commands.executeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, prompt);
break;
}
Expand Down
21 changes: 13 additions & 8 deletions src/upgrade/upgradeManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import { commands, type ExtensionContext, extensions, workspace, type WorkspaceFolder } from "vscode";
import { commands, type ExtensionContext, workspace, type WorkspaceFolder } from "vscode";

import { Jdtls } from "../java/jdtls";
import { languageServerApiManager } from "../languageServerApi/languageServerApiManager";
Expand All @@ -11,28 +11,33 @@ import { Commands } from "../commands";
import notificationManager from "./display/notificationManager";
import { Settings } from "../settings";
import assessmentManager from "./assessmentManager";
import { checkOrInstallAppModExtension, checkOrPromptToInstallAppModExtension } from "./utility";

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


function shouldRunCheckup() {
return Settings.getEnableDependencyCheckup()
&& !!extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
return Settings.getEnableDependencyCheckup();
}

class UpgradeManager {
public static initialize(context: ExtensionContext) {
notificationManager.initialize(context);

// Commands to be used
// Upgrade project
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, async (promptText?: string) => {
await checkOrInstallAppModExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
const promptToUse = promptText ?? DEFAULT_UPGRADE_PROMPT;
await commands.executeCommand(Commands.GOTO_AGENT_MODE, { prompt: promptToUse });
}));
commands.executeCommand('setContext', 'isModernizationExtensionInstalled',
!!extensions.getExtension(ExtensionName.APP_MODERNIZATION_FOR_JAVA));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MODERNIZE_JAVA_PROJECT, () => {
commands.executeCommand("workbench.view.extension.azureJavaMigrationExplorer");

// Show modernization view
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_MODERNIZE_JAVA_PROJECT, async () => {
await checkOrPromptToInstallAppModExtension(
ExtensionName.APP_MODERNIZATION_FOR_JAVA,
"Install GitHub Copilot app modernization to modernize the Java project.",
"Install Extension and Modernize");
await commands.executeCommand("workbench.view.extension.azureJavaMigrationExplorer");
}));

UpgradeManager.scan();
Expand Down
59 changes: 52 additions & 7 deletions src/upgrade/utility.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import { Uri } from "vscode";
import { commands, extensions, Uri, window } from "vscode";
import * as semver from "semver";
import { UpgradeReason, type UpgradeIssue } from "./type";
import { Upgrade } from "../constants";
import { ExtensionName, Upgrade } from "../constants";


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

export function buildNotificationMessage(issue: UpgradeIssue): string {
export function buildNotificationMessage(issue: UpgradeIssue, hasExtension: boolean): string {
const {
packageId,
currentVersion,
Expand All @@ -29,21 +29,22 @@ export function buildNotificationMessage(issue: UpgradeIssue): string {
packageDisplayName
} = issue;

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

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

switch (reason) {
case UpgradeReason.END_OF_LIFE: {
const { eolDate } = issue;
const versionEolDate = findEolDate(currentVersion, eolDate);
return `The current project is using ${packageDisplayName} ${currentVersion}, which has reached end of life${versionEolDate ? ` in ${versionEolDate}` : ""
}. Do you want to upgrade to ${suggestedVersionName} (${suggestedVersionDescription})?`;
return `This project is using ${packageDisplayName} ${currentVersion}, which has reached end of life${versionEolDate ? ` in ${versionEolDate}` : ""
}. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`;
}
case UpgradeReason.DEPRECATED:
default: {
return `The current project is using ${packageDisplayName} ${currentVersion}, which has been deprecated. Do you want to upgrade to ${suggestedVersionName} (${suggestedVersionDescription})?`;
return `This project is using ${packageDisplayName} ${currentVersion}, which has been deprecated. Would you like to ${upgradeWord} it to ${suggestedVersionName} (${suggestedVersionDescription})?`;
}
}
}
Expand Down Expand Up @@ -73,3 +74,47 @@ export function normalizePath(path: string): string {
return Uri.parse(path).toString();
}

async function checkOrPromptToEnableAppModExtension() {
if (extensions.getExtension(ExtensionName.APP_MODERNIZATION_FOR_JAVA)) {
return;
}

// The extension is disabled if we cannot detect the extension after installing it.
await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
const BTN_TEXT = "Show extension in sidebar";
const choice2 = await window.showInformationMessage(
`${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension is needed for the feature to work but it seems disabled. Please enable it manually and try again.`,
BTN_TEXT
);
if (choice2 === BTN_TEXT) {
await commands.executeCommand("workbench.extensions.search", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
}
}

export async function checkOrPromptToInstallAppModExtension(
extensionIdToCheck: string,
notificationText: string,
buttonText: string): Promise<void> {
if (extensions.getExtension(extensionIdToCheck)) {
return;
}

const choice = await window.showInformationMessage(notificationText, buttonText);
if (choice === buttonText) {
await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
} else {
return;
}

await checkOrPromptToEnableAppModExtension();
}

export async function checkOrInstallAppModExtension(
extensionIdToCheck: string): Promise<void> {
if (extensions.getExtension(extensionIdToCheck)) {
return;
}

await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
await checkOrPromptToEnableAppModExtension();
}
Loading