diff --git a/src/languageServerApi/languageServerApiManager.ts b/src/languageServerApi/languageServerApiManager.ts index 494c08a4..28d2d20b 100644 --- a/src/languageServerApi/languageServerApiManager.ts +++ b/src/languageServerApi/languageServerApiManager.ts @@ -99,6 +99,10 @@ class LanguageServerApiManager { public isReady(timeout: number): Promise { return Promise.race([this.ready(), new Promise((resolve) => setTimeout(() => resolve(false), timeout))]); } + + public getExtensionApi() { + return this.extensionApi; + } } export const languageServerApiManager: LanguageServerApiManager = new LanguageServerApiManager(); diff --git a/src/syncHandler.ts b/src/syncHandler.ts index cbdd05eb..4b1d9b6e 100644 --- a/src/syncHandler.ts +++ b/src/syncHandler.ts @@ -47,7 +47,7 @@ class SyncHandler implements Disposable { this.disposables.push(workspace.onDidChangeWorkspaceFolders(() => { this.refresh(); - setImmediate(() => upgradeManager.scan()); // Deferred + setImmediate(() => upgradeManager.scan("workspaceFoldersChange", true)); // Deferred })); try { diff --git a/src/upgrade/upgradeManager.ts b/src/upgrade/upgradeManager.ts index 155eda17..94c628d7 100644 --- a/src/upgrade/upgradeManager.ts +++ b/src/upgrade/upgradeManager.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -import { commands, type ExtensionContext, workspace, type WorkspaceFolder } from "vscode"; +import { commands, type ExtensionContext, type Event, workspace, type WorkspaceFolder } from "vscode"; import { Jdtls } from "../java/jdtls"; import { languageServerApiManager } from "../languageServerApi/languageServerApiManager"; @@ -12,6 +12,8 @@ import notificationManager from "./display/notificationManager"; import { Settings } from "../settings"; import assessmentManager, { getDirectDependencies } from "./assessmentManager"; import { checkOrInstallAppModExtensionForUpgrade, checkOrPopupToInstallAppModExtensionForModernization } from "./utility"; +import { contextManager } from "../contextManager"; +import { LanguageServerMode } from "../languageServerApi/LanguageServerMode"; const DEFAULT_UPGRADE_PROMPT = "Upgrade Java project dependency to latest version."; @@ -21,6 +23,9 @@ function shouldRunCheckup() { } class UpgradeManager { + private static watcherSetup = false; + private static scanned = false; + public static initialize(context: ExtensionContext) { notificationManager.initialize(context); @@ -41,21 +46,25 @@ class UpgradeManager { })); // Defer the expensive scan operation to not block extension activation - setImmediate(() => UpgradeManager.scan()); + setImmediate(() => UpgradeManager.scan("initialization", false)); } - public static scan() { - if (!shouldRunCheckup()) { - return; - } - workspace.workspaceFolders?.forEach((folder) => - UpgradeManager.runDependencyCheckup(folder) - ); - } + public static scan(triggerReason: string, forceRescan: boolean) { + return instrumentOperation("java.dependency.scan", async (_operationId: string) => { + sendInfo(_operationId, { triggerReason }); - private static async runDependencyCheckup(folder: WorkspaceFolder) { - return instrumentOperation("java.dependency.runDependencyCheckup", async (_operationId: string) => { - if (!(await languageServerApiManager.ready())) { + if (!shouldRunCheckup()) { + return; + } + + if (forceRescan) { + UpgradeManager.scanned = false; + } + + const readyResult = await languageServerApiManager.ready(); + this.setupWatcherForServerModeChange(); + + if (!readyResult) { sendInfo(_operationId, { skipReason: "languageServerNotReady" }); return; } @@ -66,6 +75,19 @@ class UpgradeManager { return; } + if (UpgradeManager.scanned) { + return; + } + UpgradeManager.scanned = true; + + workspace.workspaceFolders?.forEach((folder) => + UpgradeManager.runDependencyCheckup(folder) + ); + })(); + } + + private static async runDependencyCheckup(folder: WorkspaceFolder) { + return instrumentOperation("java.dependency.runDependencyCheckup", async (_operationId: string) => { const projects = await Jdtls.getProjects(folder.uri.toString()); const projectDirectDepsResults = await Promise.allSettled( projects.map(async (projectNode) => ({ @@ -89,6 +111,23 @@ class UpgradeManager { } })(); } + + private static setupWatcherForServerModeChange() { + if (UpgradeManager.watcherSetup) { + return; + } + + const extensionApi = languageServerApiManager.getExtensionApi(); + if (extensionApi.onDidServerModeChange) { + const onDidServerModeChange: Event = extensionApi.onDidServerModeChange; + contextManager.context.subscriptions.push(onDidServerModeChange((mode: LanguageServerMode) => { + if (mode !== LanguageServerMode.LightWeight) { + setImmediate(() => UpgradeManager.scan(`languageServerModeChangeTo${mode}`, false)); + } + })); + UpgradeManager.watcherSetup = true; + } + } } export default UpgradeManager; \ No newline at end of file