diff --git a/src/definitions/constants.ts b/src/definitions/constants.ts index c05d7176..4c42c9d7 100644 --- a/src/definitions/constants.ts +++ b/src/definitions/constants.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, 2022 IBM Corporation. + * Copyright (c) 2020, 2024 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -34,6 +34,7 @@ export const COMMAND_AND_PROJECT_TYPE_MAP: { [command: string]: string[] } = { }; export const EXCLUDED_DIR_PATTERN = "**/{bin,classes,target}/**"; export const COMMAND_TITLES = new Map(); +export const UNTITLED_WORKSPACE="Untitled (Workspace)"; COMMAND_TITLES.set(localize("hotkey.commands.title.refresh"), "liberty.explorer.refresh"); COMMAND_TITLES.set(localize("hotkey.commands.title.start"), "liberty.dev.start"); diff --git a/src/extension.ts b/src/extension.ts index fb7be862..91c31cb4 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, 2022 IBM Corporation. + * Copyright (c) 2020, 2024 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -19,6 +19,7 @@ import { JAVA_EXTENSION_ID, waitForStandardMode } from "./util/javaServerMode"; import { localize } from "./util/i18nUtil"; import { RequirementsData, resolveRequirements, resolveLclsRequirements } from "./util/requirements"; import { prepareExecutable } from "./util/javaServerStarter"; +import * as helperUtil from "./util/helperUtil"; const LIBERTY_CLIENT_ID = "LANGUAGE_ID_LIBERTY"; const JAKARTA_CLIENT_ID = "LANGUAGE_ID_JAKARTA"; @@ -62,7 +63,7 @@ export async function activate(context: vscode.ExtensionContext): Promise item.text = localize("liberty.ls.thumbs.up"); item.tooltip = localize("liberty.ls.started"); toggleItem(window.activeTextEditor, item); - + handleWorkspaceSaveInProgress(context); registerCommands(context); }, (error: any) => { console.log("Liberty client was not ready. Did not initialize"); @@ -104,11 +105,7 @@ function bindRequest(request: string) { } function registerCommands(context: ExtensionContext) { - let projectProvider = ProjectProvider.getInstance(); - if ( !projectProvider ) { - projectProvider = new ProjectProvider(context); - ProjectProvider.setInstance(projectProvider); - } + let projectProvider = getProjectProvider(context); if (vscode.workspace.workspaceFolders !== undefined) { registerFileWatcher(projectProvider); @@ -261,3 +258,21 @@ async function getJavaExtensionAPI(): Promise { } return Promise.resolve(api); } + +function handleWorkspaceSaveInProgress(context: vscode.ExtensionContext) { + let projectProvider = getProjectProvider(context); + if (projectProvider.getContext().globalState.get('workspaceSaveInProgress') && + projectProvider.getContext().globalState.get('selectedProject') !== undefined) { + devCommands.addProjectsToTheDashBoard(projectProvider, projectProvider.getContext().globalState.get('selectedProject') as string); + helperUtil.clearDataSavedInGlobalState(projectProvider.getContext()); + } +} + +function getProjectProvider(context: vscode.ExtensionContext): ProjectProvider { + let projectProvider = ProjectProvider.getInstance(); + if (!projectProvider) { + projectProvider = new ProjectProvider(context); + ProjectProvider.setInstance(projectProvider); + } + return projectProvider; +} \ No newline at end of file diff --git a/src/liberty/devCommands.ts b/src/liberty/devCommands.ts index 6d0a8633..ad222aea 100644 --- a/src/liberty/devCommands.ts +++ b/src/liberty/devCommands.ts @@ -168,10 +168,18 @@ function showListOfPathsToAdd(uris: string[]) { if (!selection) { return; } - const result = await projectProvider.addUserSelectedPath(selection, projectProvider.getProjects()); - const message = localize(`add.project.manually.message.${result}`, selection); - (result !== 0) ? console.error(message) : console.info(message); projectProvider.fireChangeEvent(); - vscode.window.showInformationMessage(message); + if (projectProvider.isMultiProjectUntitledWorkspace()) { + /** + * Saving the selected project to globalstate for adding it to the dashboard after + * reinitialization of the extension when workspace is saved + */ + await projectProvider.getContext().globalState.update('selectedProject', selection); + /* + if the workspace is untitled suggest the user to save the workspace first + */ + await projectProvider.checkUntitledWorkspaceAndSaveIt(); + } + await addProjectsToTheDashBoard(projectProvider, selection); }); } @@ -539,7 +547,7 @@ function getReportFile(path: any, dir: string, filename: string): any { /* Function will check if the report is available within the given path and returns a boolean based on it and also - the report will be displayed if it is available +the report will be displayed if it is available */ function checkReportAndDisplay(report: any, reportType: string, reportTypeLabel: string, libProject: LibertyProject, showErrorMessage: boolean): Promise { return new Promise((resolve) => { @@ -565,3 +573,14 @@ function checkReportAndDisplay(report: any, reportType: string, reportTypeLabel: }); }); } + +/* +Method adds a project which is selected by the user from the list to the liberty dashboard +*/ +export async function addProjectsToTheDashBoard(projectProvider: ProjectProvider, selection: string): Promise { + const result = await projectProvider.addUserSelectedPath(selection, projectProvider.getProjects()); + const message = localize(`add.project.manually.message.${result}`, selection); + (result !== 0) ? console.error(message) : console.info(message); projectProvider.fireChangeEvent(); + vscode.window.showInformationMessage(message); + return Promise.resolve(); +} diff --git a/src/liberty/libertyProject.ts b/src/liberty/libertyProject.ts index 8abae9ff..6672977b 100644 --- a/src/liberty/libertyProject.ts +++ b/src/liberty/libertyProject.ts @@ -14,7 +14,7 @@ import * as gradleUtil from "../util/gradleUtil"; import * as mavenUtil from "../util/mavenUtil"; import * as util from "../util/helperUtil"; import { localize } from "../util/i18nUtil"; -import { EXCLUDED_DIR_PATTERN, LIBERTY_GRADLE_PROJECT, LIBERTY_GRADLE_PROJECT_CONTAINER, LIBERTY_MAVEN_PROJECT, LIBERTY_MAVEN_PROJECT_CONTAINER } from "../definitions/constants"; +import { EXCLUDED_DIR_PATTERN, LIBERTY_GRADLE_PROJECT, LIBERTY_GRADLE_PROJECT_CONTAINER, LIBERTY_MAVEN_PROJECT, LIBERTY_MAVEN_PROJECT_CONTAINER, UNTITLED_WORKSPACE } from "../definitions/constants"; import { BuildFileImpl, GradleBuildFile } from "../util/buildFile"; import { DashboardData } from "./dashboard"; import { BaseLibertyProject } from "./baseLibertyProject"; @@ -203,6 +203,56 @@ export class ProjectProvider implements vscode.TreeDataProvider statusMessage.dispose(); } + /** + * This method asks the user to save the workspace first if it is untitled and the workspace contains more than + * one project. If the workspace is not saved, there are chances that the project's state may not be saved and + * manually added projects may not be visible in the Liberty dashboard in a new VS Code session. + */ + public async checkUntitledWorkspaceAndSaveIt(): Promise { + return new Promise((resolve) => { + try { + vscode.window.showInformationMessage( + localize("workspace.not.saved.projects.may.not.persist"), + { modal: true }, + 'Save Workspace' + ).then(async (selection) => { + if (selection === 'Save Workspace') { + /** + * setting workspaceSaveInProgress to true and storing it in globalstate for identifyting that the + * workspace is saved and needs to save the manually added projects to the dashboard + */ + await this._context.globalState.update('workspaceSaveInProgress', true); + //opens the saveWorkspace as dialog box + await vscode.commands.executeCommand('workbench.action.saveWorkspaceAs'); + } + /** + * If the user cancels saving the workspace and exits without saving, the data stays in the global state, + * which is shared across all VS Code instances. To prevent this data from being mistakenly used in other + * sessions and added to the dashboard, it should be cleared if the user cancels the save. + */ + util.clearDataSavedInGlobalState(this._context); + resolve(); + }); + } catch (error) { + console.debug("exception while saving the workspace" + error); + util.clearDataSavedInGlobalState(this._context); + resolve(); + } + }); + } + + /* + This method identifies a workspace that is untitled and contains more than one project + */ + public isMultiProjectUntitledWorkspace(): boolean { + const workspaceFolders = vscode.workspace.workspaceFolders; + if ((workspaceFolders && workspaceFolders.length > 1 + && vscode.workspace.name === UNTITLED_WORKSPACE)) { + return true; + } + return false; + } + public fireChangeEvent(): void { this._onDidChangeTreeData.fire(undefined); } diff --git a/src/locales/en.json b/src/locales/en.json index 265ec37b..31389d78 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -71,5 +71,6 @@ "hotkey.commands.title.view.test.report": "Liberty: View test report", "hotkey.commands.title.add.project": "Liberty: Add Project to Liberty Dashboard", "hotkey.commands.title.remove.project": "Liberty: Remove Project from Liberty Dashboard", - "hotkey.commands.title.show.commands": "Liberty: Show Liberty commands" + "hotkey.commands.title.show.commands": "Liberty: Show Liberty commands", + "workspace.not.saved.projects.may.not.persist": "Please save the workspace first. Projects that are manually added to the Liberty dashboard may not persist in the next VS Code session if the workspace is not saved before adding the project." } diff --git a/src/util/helperUtil.ts b/src/util/helperUtil.ts index 46582534..277ed455 100644 --- a/src/util/helperUtil.ts +++ b/src/util/helperUtil.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, 2022 IBM Corporation. + * Copyright (c) 2020, 2024 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -71,4 +71,12 @@ export function getStorageData(context: vscode.ExtensionContext): DashboardData export async function saveStorageData(context: vscode.ExtensionContext, dasboardData: DashboardData): Promise{ await context.workspaceState.update(LIBERTY_DASHBOARD_WORKSPACE_STORAGE_KEY, dasboardData); } +/** + * clears the states saved in global state + * @param context + */ +export function clearDataSavedInGlobalState(context: vscode.ExtensionContext) { + context.globalState.update('workspaceSaveInProgress', false); + context.globalState.update('selectedProject', undefined); +}