diff --git a/.vscode/launch.json b/.vscode/launch.json index c96e935da9b..0893a35dbb3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -245,7 +245,8 @@ "--extensionTestsPath=${workspaceFolder}/workspaces/ballerina/ballerina-extension/out/test", "${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/bi_empty_project", "${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/bi_init", - "${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/simple_order_management_system","${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/ai_datamapper" + "${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/simple_order_management_system", + "${workspaceFolder}/workspaces/ballerina/ballerina-extension/test/data/ai_datamapper" ], "env": { "LS_EXTENSIONS_PATH": "", @@ -294,4 +295,4 @@ "preLaunchTask": "npm: watch-apk" }, ] -} +} \ No newline at end of file diff --git a/workspaces/api-designer/api-designer-extension/package.json b/workspaces/api-designer/api-designer-extension/package.json index 72a2b6ddeea..b52074ee9bf 100644 --- a/workspaces/api-designer/api-designer-extension/package.json +++ b/workspaces/api-designer/api-designer-extension/package.json @@ -83,7 +83,7 @@ "clean": "rimraf ./dist", "compile": "tsc -p .", "watch": "tsc -p . -w", - "package": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi", + "package": "node ../../common-libs/scripts/package-vsix.js", "build": "pnpm clean && pnpm run copyFonts && webpack --mode production --devtool hidden-source-map && pnpm run package && pnpm run postbuild", "compile-tests": "pnpm run compile", "watch-tests": "pnpm run watch", diff --git a/workspaces/apk/apk-extension/package.json b/workspaces/apk/apk-extension/package.json index cd3478bc546..f08b7fffdf4 100644 --- a/workspaces/apk/apk-extension/package.json +++ b/workspaces/apk/apk-extension/package.json @@ -51,7 +51,7 @@ "pretest": "npm run compile && npm run lint", "lint": "eslint src --ext ts", "test": "node ./out/test/runTest.js", - "build": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi && pnpm run postbuild", + "build": "node ../../common-libs/scripts/package-vsix.js && pnpm run postbuild", "postbuild": "pnpm run copyVSIX", "copyVSIX": "copyfiles *.vsix ./vsix", "copyVSIXToRoot": "copyfiles -f ./vsix/* ../../.." diff --git a/workspaces/ballerina/ballerina-core/src/interfaces/constants.ts b/workspaces/ballerina/ballerina-core/src/interfaces/constants.ts index 5c8388e5777..0266888301a 100644 --- a/workspaces/ballerina/ballerina-core/src/interfaces/constants.ts +++ b/workspaces/ballerina/ballerina-core/src/interfaces/constants.ts @@ -32,7 +32,6 @@ export const BI_COMMANDS = { BI_RUN_PROJECT: 'BI.project.run', BI_DEBUG_PROJECT: 'BI.project.debug', REFRESH_COMMAND: 'BI.project-explorer.refresh', - FOCUS_PROJECT_EXPLORER: 'BI.project-explorer.focus', PROJECT_EXPLORER: 'BI.project-explorer', ADD_CONNECTIONS: 'BI.project-explorer.add-connection', ADD_CUSTOM_CONNECTOR: 'BI.project-explorer.add-custom-connector', @@ -52,6 +51,8 @@ export const BI_COMMANDS = { BI_EDIT_TEST_FUNCTION_DEF: 'BI.test.edit.function.def', ADD_NATURAL_FUNCTION: 'BI.project-explorer.add-natural-function', TOGGLE_TRACE_LOGS: 'BI.toggle.trace.logs', + CREATE_BI_PROJECT: 'BI.project.createBIProjectPure', + CREATE_BI_MIGRATION_PROJECT: 'BI.project.createBIProjectMigration', ADD_INTEGRATION: 'BI.project-explorer.add-integration', NOTIFY_PROJECT_EXPLORER: 'BI.project-explorer.notify', }; diff --git a/workspaces/ballerina/ballerina-extension/package.json b/workspaces/ballerina/ballerina-extension/package.json index b7128735175..bd1ca3fac32 100644 --- a/workspaces/ballerina/ballerina-extension/package.json +++ b/workspaces/ballerina/ballerina-extension/package.json @@ -765,7 +765,8 @@ }, { "view": "testing", - "contents": "[Add Unit Test](command:BI.test.add.function)" + "contents": "[Add Unit Test](command:BI.test.add.function)", + "when": "isBIProject || isBallerinaProject" } ], "viewsContainers": { @@ -809,7 +810,7 @@ }, { "command": "BI.test.add.function", - "when": "view == workbench.view.testing", + "when": "(isBIProject || isBallerinaProject) && view == workbench.view.testing", "group": "navigation" }, { @@ -1175,7 +1176,7 @@ "test-coverage": "cross-env COVER_CONFIG=html pnpm run test", "build-tm-grammar": "js-yaml grammar/ballerina-grammar/syntaxes/ballerina.tmLanguage.yaml > grammar/ballerina-grammar/syntaxes/ballerina.tmLanguage.json", "lint": "tslint --fix 'src/**/*{.ts,.tsx}'", - "package": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi", + "package": "node ../../common-libs/scripts/package-vsix.js", "copyFonts": "copyfiles -f ./node_modules/@wso2/font-wso2-vscode/dist/* ./resources/font-wso2-vscode/dist/", "copyVSIX": "copyfiles *.vsix ./vsix", "copyVSIXToRoot": "copyfiles -f ./vsix/*.vsix ../../..", diff --git a/workspaces/ballerina/ballerina-extension/src/features/bi/activator.ts b/workspaces/ballerina/ballerina-extension/src/features/bi/activator.ts index a1ada5a98bb..82f8ea4605c 100644 --- a/workspaces/ballerina/ballerina-extension/src/features/bi/activator.ts +++ b/workspaces/ballerina/ballerina-extension/src/features/bi/activator.ts @@ -35,6 +35,7 @@ import { readFileSync, readdirSync, statSync } from "fs"; import path from "path"; import { isPositionEqual, isPositionWithinDeletedComponent } from "../../utils/history/util"; import { startDebugging } from "../editor-support/activator"; +import { createBIProjectFromMigration, createBIProjectPure } from "../../utils/bi"; import { createVersionNumber, isSupportedSLVersion } from ".././../utils"; import { extension } from "../../BalExtensionContext"; @@ -60,7 +61,7 @@ function handleCommandWithContext( // Scenario 1: Multi-package workspace invoked from command palette if (isBalWorkspace && !item) { const packageList = StateMachine.context().projectInfo?.children.map((child) => child.projectPath); - + if (!packageList || packageList.length === 0) { openView(EVENT_TYPE.OPEN_VIEW, { view, ...additionalViewParams }); return; @@ -70,10 +71,10 @@ function handleCommandWithContext( placeHolder: "Select a package" }).then((selectedPackage) => { if (selectedPackage) { - openView(EVENT_TYPE.OPEN_VIEW, { - view, - projectPath: selectedPackage, - ...additionalViewParams + openView(EVENT_TYPE.OPEN_VIEW, { + view, + projectPath: selectedPackage, + ...additionalViewParams }); } }); @@ -81,12 +82,12 @@ function handleCommandWithContext( // Scenario 2: Invoked from tree view with item context else if (item?.resourceUri) { const projectPath = item.resourceUri.fsPath; - openView(EVENT_TYPE.OPEN_VIEW, { - view, - projectPath, - ...additionalViewParams + openView(EVENT_TYPE.OPEN_VIEW, { + view, + projectPath, + ...additionalViewParams }); - } + } // Scenario 3: Default - no specific context else { openView(EVENT_TYPE.OPEN_VIEW, { view, ...additionalViewParams }); @@ -95,7 +96,7 @@ function handleCommandWithContext( export function activate(context: BallerinaExtension) { const isWorkspaceSupported = isSupportedSLVersion(extension.ballerinaExtInstance, createVersionNumber(2201, 13, 0)); - + // Set context for command visibility commands.executeCommand('setContext', 'ballerina.bi.workspaceSupported', isWorkspaceSupported); @@ -154,7 +155,7 @@ export function activate(context: BallerinaExtension) { window.showErrorMessage('This command requires Ballerina version 2201.13.0 or higher. '); return; } - + const projectPath = StateMachine.context().projectPath || StateMachine.context().workspacePath; if (projectPath) { openView(EVENT_TYPE.OPEN_VIEW, { view: MACHINE_VIEW.BIAddProjectForm }); @@ -173,6 +174,14 @@ export function activate(context: BallerinaExtension) { commands.registerCommand(BI_COMMANDS.TOGGLE_TRACE_LOGS, toggleTraceLogs); + commands.registerCommand(BI_COMMANDS.CREATE_BI_PROJECT, (params) => { + return createBIProjectPure(params); + }); + + commands.registerCommand(BI_COMMANDS.CREATE_BI_MIGRATION_PROJECT, (params) => { + return createBIProjectFromMigration(params); + }); + commands.registerCommand(BI_COMMANDS.DELETE_COMPONENT, async (item?: TreeItem & { info?: string }) => { // Guard: DELETE requires a tree item context if (!item) { diff --git a/workspaces/bi/bi-extension/package.json b/workspaces/bi/bi-extension/package.json index 29ae6fc4928..b553ab1fb24 100644 --- a/workspaces/bi/bi-extension/package.json +++ b/workspaces/bi/bi-extension/package.json @@ -67,7 +67,8 @@ "ballerina-integrator": [ { "id": "BI.project-explorer", - "name": "" + "name": "", + "when": "!config.integrator.defaultIntegrator" } ] }, @@ -162,7 +163,7 @@ "lint": "eslint src --ext ts", "test": "node ./out/test/runTest.js", "build": "pnpm run compile && pnpm run lint && pnpm run postbuild", - "package": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi", + "package": "node ../../common-libs/scripts/package-vsix.js", "copyFonts": "copyfiles -f ./node_modules/@wso2/font-wso2-vscode/dist/* ./resources/font-wso2-vscode/dist/", "rebuild": "pnpm run clean && pnpm run compile && pnpm run postbuild", "postbuild": "pnpm run copyFonts && pnpm run package && pnpm run copyVSIX", @@ -200,4 +201,4 @@ "@playwright/test": "~1.55.1", "@wso2/playwright-vscode-tester": "workspace:*" } -} +} \ No newline at end of file diff --git a/workspaces/bi/bi-extension/src/constants/index.ts b/workspaces/bi/bi-extension/src/constants/index.ts index 182bfeda524..e3a9354dcea 100644 --- a/workspaces/bi/bi-extension/src/constants/index.ts +++ b/workspaces/bi/bi-extension/src/constants/index.ts @@ -16,4 +16,10 @@ * under the License. */ +import { BI_COMMANDS } from "@wso2/ballerina-core"; + // ADD ALL THE NON-SHARED BI ONLY ATTRIBUTES HERE. +export const WI_EXTENSION_ID = 'wso2.wso2-integrator'; +export const WI_PROJECT_EXPLORER_VIEW_ID = 'wso2-integrator.explorer'; +export const WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND = 'wso2-integrator.explorer.refresh'; +export const BI_PROJECT_EXPLORER_VIEW_ID = BI_COMMANDS.PROJECT_EXPLORER; diff --git a/workspaces/bi/bi-extension/src/project-explorer/activate.ts b/workspaces/bi/bi-extension/src/project-explorer/activate.ts index 5db56952cb2..9bdcecea664 100644 --- a/workspaces/bi/bi-extension/src/project-explorer/activate.ts +++ b/workspaces/bi/bi-extension/src/project-explorer/activate.ts @@ -20,6 +20,7 @@ import { SHARED_COMMANDS, BI_COMMANDS, MACHINE_VIEW, NodePosition } from '@wso2/ import { ProjectExplorerEntry, ProjectExplorerEntryProvider } from './project-explorer-provider'; import { ExtensionContext, TreeView, commands, window, workspace } from 'vscode'; import { extension } from '../biExtentionContext'; +import { BI_PROJECT_EXPLORER_VIEW_ID, WI_PROJECT_EXPLORER_VIEW_ID, WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND } from '../constants'; interface ExplorerActivationConfig { context: ExtensionContext; @@ -27,25 +28,27 @@ interface ExplorerActivationConfig { isBallerinaPackage?: boolean; isBallerinaWorkspace?: boolean; isEmptyWorkspace?: boolean; + isInWI: boolean; } export function activateProjectExplorer(config: ExplorerActivationConfig) { - const { context, isBI, isBallerinaPackage, isBallerinaWorkspace, isEmptyWorkspace } = config; + const { context, isBI, isBallerinaPackage, isBallerinaWorkspace, isEmptyWorkspace, isInWI } = config; if (extension.langClient && extension.biSupported) { setLoadingStatus(); } + const treeviewId = isInWI ? WI_PROJECT_EXPLORER_VIEW_ID : BI_PROJECT_EXPLORER_VIEW_ID; const projectExplorerDataProvider = new ProjectExplorerEntryProvider(); - const projectTree = createProjectTree(projectExplorerDataProvider); + const projectTree = createProjectTree(projectExplorerDataProvider, treeviewId); projectExplorerDataProvider.setTreeView(projectTree); // Always register core commands so they're available to the Ballerina extension - registerCoreCommands(projectExplorerDataProvider); + registerCoreCommands(projectExplorerDataProvider, isInWI); if (isBallerinaPackage || isBallerinaWorkspace) { - registerBallerinaCommands(projectExplorerDataProvider, isBI, isBallerinaWorkspace, isEmptyWorkspace); + registerBallerinaCommands(projectExplorerDataProvider, isBI, isInWI, isBallerinaWorkspace, isEmptyWorkspace); } handleVisibilityChangeEvents( @@ -62,11 +65,11 @@ function setLoadingStatus() { commands.executeCommand('setContext', 'BI.status', 'loading'); } -function createProjectTree(dataProvider: ProjectExplorerEntryProvider) { - return window.createTreeView(BI_COMMANDS.PROJECT_EXPLORER, { treeDataProvider: dataProvider }); +function createProjectTree(dataProvider: ProjectExplorerEntryProvider, treeviewId: string) { + return window.createTreeView(treeviewId, { treeDataProvider: dataProvider }); } -function registerCoreCommands(dataProvider: ProjectExplorerEntryProvider) { +function registerCoreCommands(dataProvider: ProjectExplorerEntryProvider, isInWI: boolean) { // Register the notify command that's called by the Ballerina extension commands.registerCommand( BI_COMMANDS.NOTIFY_PROJECT_EXPLORER, @@ -81,12 +84,13 @@ function registerCoreCommands(dataProvider: ProjectExplorerEntryProvider) { ); // Register the refresh command - commands.registerCommand(BI_COMMANDS.REFRESH_COMMAND, () => dataProvider.refresh()); + commands.registerCommand(isInWI ? WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND : BI_COMMANDS.REFRESH_COMMAND, () => dataProvider.refresh()); } function registerBallerinaCommands( dataProvider: ProjectExplorerEntryProvider, isBI: boolean, + isInWI: boolean, isBallerinaWorkspace?: boolean, isEmptyWorkspace?: boolean ) { @@ -99,7 +103,7 @@ function registerBallerinaCommands( } } if (isBI) { - registerBICommands(); + registerBICommands(isInWI); } } @@ -153,8 +157,9 @@ function handleNonBallerinaVisibility() { commands.executeCommand(SHARED_COMMANDS.OPEN_BI_WELCOME); } -function registerBICommands() { - commands.executeCommand(BI_COMMANDS.FOCUS_PROJECT_EXPLORER); +function registerBICommands(isInWI) { + const treeViewId = isInWI ? WI_PROJECT_EXPLORER_VIEW_ID : BI_PROJECT_EXPLORER_VIEW_ID; + commands.executeCommand(`${treeViewId}.focus`); commands.executeCommand(SHARED_COMMANDS.SHOW_VISUALIZER); commands.executeCommand('setContext', 'BI.project', true); } diff --git a/workspaces/bi/bi-extension/src/stateMachine.ts b/workspaces/bi/bi-extension/src/stateMachine.ts index d82d8eb9f22..43b5dcbf251 100644 --- a/workspaces/bi/bi-extension/src/stateMachine.ts +++ b/workspaces/bi/bi-extension/src/stateMachine.ts @@ -20,12 +20,15 @@ import { assign, createMachine, interpret } from 'xstate'; import { activateProjectExplorer } from './project-explorer/activate'; import { extension } from './biExtentionContext'; import { fetchProjectInfo, ProjectInfo } from './utils'; +import { WI_EXTENSION_ID } from './constants'; +import * as vscode from 'vscode'; interface MachineContext { isBI: boolean; isBallerinaPackage?: boolean; isBallerinaWorkspace?: boolean; isEmptyWorkspace?: boolean; + isInWI: boolean; } const stateMachine = createMachine({ @@ -34,7 +37,8 @@ const stateMachine = createMachine({ initial: 'initialize', predictableActionArguments: true, context: { - isBI: false + isBI: false, + isInWI: vscode.extensions.getExtension(WI_EXTENSION_ID) ? true : false }, states: { initialize: { @@ -71,7 +75,8 @@ const stateMachine = createMachine({ isBI: context.isBI, isBallerinaPackage: context.isBallerinaPackage, isBallerinaWorkspace: context.isBallerinaWorkspace, - isEmptyWorkspace: context.isEmptyWorkspace + isEmptyWorkspace: context.isEmptyWorkspace, + isInWI: context.isInWI }); } }, diff --git a/workspaces/common-libs/rpc-generator/index.js b/workspaces/common-libs/rpc-generator/index.js index e273ab6cf5f..a2c4bed7d6e 100644 --- a/workspaces/common-libs/rpc-generator/index.js +++ b/workspaces/common-libs/rpc-generator/index.js @@ -324,7 +324,6 @@ const handlerFunction = handlerSourceFile.addFunction({ }] }); handleImportStatment(handlerSourceFile, 'vscode-messenger', 'Messenger'); - // Add statements to the function const managerObject = `const rpcManger = new ${managerClassName}();` handlerFunction.addStatements(managerObject); @@ -332,6 +331,7 @@ typeMethods.forEach(value => { handleMessengerTypes(handlerFunction, value, handlerSourceFile); }) +console.log(`Adding handler function: ${headerComment}...`); handleImportStatment(handlerSourceFile, './rpc-manager', managerClassName); // Format imports into new lines diff --git a/workspaces/common-libs/rpc-generator/package.json b/workspaces/common-libs/rpc-generator/package.json index 6e2766b61dc..e4f03d514c3 100644 --- a/workspaces/common-libs/rpc-generator/package.json +++ b/workspaces/common-libs/rpc-generator/package.json @@ -4,11 +4,11 @@ "description": "Generate rpc-manager,rpc-handler and rpc-client ts files in relevant libraries", "main": "index.js", "config": { - "CORE_RPC_TYPE_FILE": "ai-panel/index.ts", - "CORE_RPC_TYPE_DIR": "../../ballerina/ballerina-core/", - "EXT_RPC_MANAGER_DIR": "../../ballerina/ballerina-extension/", - "RPC_CLIENT_DIR": "../../ballerina/ballerina-rpc-client/", - "CORE_MODULE_NAME": "@wso2/ballerina-core" + "CORE_RPC_TYPE_FILE": "main/index.ts", + "CORE_RPC_TYPE_DIR": "../../wi/wi-core/", + "EXT_RPC_MANAGER_DIR": "../../wi/wi-extension/", + "RPC_CLIENT_DIR": "../../wi/wi-rpc-client/", + "CORE_MODULE_NAME": "@wso2/wi-core" }, "scripts": { "generate": "node index.js" diff --git a/workspaces/common-libs/scripts/package-vsix.js b/workspaces/common-libs/scripts/package-vsix.js new file mode 100644 index 00000000000..99516c70eeb --- /dev/null +++ b/workspaces/common-libs/scripts/package-vsix.js @@ -0,0 +1,24 @@ +const { spawnSync } = require('child_process'); + +const isPreRelease = process.env.isPreRelease === 'true'; +const args = ['vsce', 'package', '--no-dependencies']; + +if (isPreRelease) { + args.push('--pre-release'); +} + +console.log(`Packaging VSIX with args: ${args.join(' ')}`); + +const result = spawnSync('npx', args, { stdio: 'inherit' }); + +if (result.error) { + console.error(`Failed to spawn vsce: ${result.error.message}`); + process.exit(1); +} + +if (result.status === null) { + console.error('vsce process was terminated by a signal'); + process.exit(1); +} + +process.exit(result.status); diff --git a/workspaces/mcp-inspector/mcp-inspector-extension/package.json b/workspaces/mcp-inspector/mcp-inspector-extension/package.json index 80659e1768c..b410d3ac893 100644 --- a/workspaces/mcp-inspector/mcp-inspector-extension/package.json +++ b/workspaces/mcp-inspector/mcp-inspector-extension/package.json @@ -60,7 +60,7 @@ "lint": "eslint src", "test": "node ./out/test/runTest.js", "build": "pnpm run compile && pnpm run lint && pnpm run postbuild", - "package": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi", + "package": "node ../../common-libs/scripts/package-vsix.js", "rebuild": "pnpm run clean && pnpm run compile && pnpm run postbuild", "postbuild": "pnpm run package && pnpm run copyVSIX", "copyVSIX": "copyfiles *.vsix ./vsix", diff --git a/workspaces/mi/mi-extension/package.json b/workspaces/mi/mi-extension/package.json index ac46d86ef0a..84d5213ef39 100644 --- a/workspaces/mi/mi-extension/package.json +++ b/workspaces/mi/mi-extension/package.json @@ -191,13 +191,15 @@ "micro-integrator": [ { "id": "MI.project-explorer", - "name": "Project Explorer" + "name": "Project Explorer", + "when": "!config.integrator.defaultIntegrator" } ], "test": [ { "id": "MI.mock-services", - "name": "Mock Services" + "name": "Mock Services", + "when": "MI.status == 'projectLoaded'" } ] }, @@ -205,26 +207,37 @@ { "view": "MI.project-explorer", "contents": "Loading...", - "when": "MI.status != 'unknownProject' && MI.status != 'projectLoaded' && MI.status != 'disabled' && MI.status != 'notSetUp'" + "when": "!config.integrator.defaultIntegrator && (MI.status != 'unknownProject' && MI.status != 'projectLoaded' && MI.status != 'disabled' && MI.status != 'notSetUp')" }, { "view": "MI.project-explorer", "contents": "Welcome to WSO2 Integrator: MI. You can open a folder containing a MI project or create a new project.\n[Open MI Project](command:MI.openProject)\n[Create New Project](command:MI.project-explorer.create-project)\nTo learn more about how to use WSO2 Integrator: MI in VS Code, [read our docs](https://mi.docs.wso2.com/en/4.3.0/develop/mi-for-vscode/mi-for-vscode-overview/).", - "when": "MI.status == 'unknownProject'" + "when": "!config.integrator.defaultIntegrator && MI.status == 'unknownProject'" }, { "view": "MI.project-explorer", "contents": "Some errors occurred while activating the extension. Please check the output channel for more information.", - "when": "MI.status == 'disabled'" + "when": "!config.integrator.defaultIntegrator && MI.status == 'disabled'" }, { - "view": "testing", - "contents": "[Add Unit Test](command:MI.test.add.suite)" + "view": "MI.project-explorer", + "contents": "WSO2 Integrator: MI is not set up. Please set up the MI server and Java home to continue.", + "when": "!config.integrator.defaultIntegrator && MI.status == 'notSetUp'" }, { - "view": "MI.project-explorer", + "view": "wso2-integrator.explorer", + "contents": "Loading...", + "when": "config.integrator.defaultIntegrator != '' && (MI.status != 'unknownProject' && MI.status != 'projectLoaded' && MI.status != 'disabled' && MI.status != 'notSetUp')" + }, + { + "view": "wso2-integrator.explorer", + "contents": "Some errors occurred while activating the extension. Please check the output channel for more information.", + "when": "config.integrator.defaultIntegrator != '' && MI.status == 'disabled'" + }, + { + "view": "wso2-integrator.explorer", "contents": "WSO2 Integrator: MI is not set up. Please set up the MI server and Java home to continue.", - "when": "MI.status == 'notSetUp'" + "when": "config.integrator.defaultIntegrator != '' && MI.status == 'notSetUp'" } ], "commands": [ @@ -920,7 +933,7 @@ { "command": "MI.test.add.case", "group": "inline", - "when": "testId in test.suites" + "when": "MI.status == 'projectLoaded' && testId in test.suites" }, { "command": "MI.test.edit.case", @@ -961,7 +974,7 @@ "clean": "rimraf ./dist", "compile": "tsc -p .", "watch": "tsc -p . -w", - "package": "if [ $isPreRelease = true ]; then vsce package --no-dependencies --pre-release; else vsce package --no-dependencies; fi", + "package": "node ../../common-libs/scripts/package-vsix.js", "download-ls": "node ./scripts/download-ls.js", "build": "pnpm clean && pnpm run download-ls && pnpm run copyJSLibs && pnpm run copyLSLibs && pnpm run copyFonts && pnpm run copyDMUtils && pnpm run renameDMUtils && webpack --mode production --devtool hidden-source-map && pnpm run package && pnpm run postbuild", "compile-tests": "pnpm run compile", diff --git a/workspaces/mi/mi-extension/src/constants/index.ts b/workspaces/mi/mi-extension/src/constants/index.ts index 9be0c37ae38..32118a05e28 100644 --- a/workspaces/mi/mi-extension/src/constants/index.ts +++ b/workspaces/mi/mi-extension/src/constants/index.ts @@ -74,7 +74,6 @@ export const COMMANDS = { CREATE_PROJECT_COMMAND: 'MI.project-explorer.create-project', IMPORT_PROJECT_COMMAND: 'MI.project-explorer.import-project', REVEAL_ITEM_COMMAND: 'MI.project-explorer.revealItem', - FOCUS_PROJECT_EXPLORER: 'MI.project-explorer.focus', OPEN_SERVICE_DESIGNER: 'MI.project-explorer.open-service-designer', OPEN_PROJECT_OVERVIEW: 'MI.project-explorer.open-project-overview', ADD_REGISTERY_RESOURCE_COMMAND: 'MI.project-explorer.add-registry-resource', @@ -204,3 +203,8 @@ export const DEFAULT_ICON = "https://mi-connectors.wso2.com/icons/wordpress.gif" export const ERROR_MESSAGES = { ERROR_DOWNLOADING_MODULES: "Unable to download the default modules. These modules can be added after project creation. Do you wish to skip them now and proceed with the project creation?", }; + +export const WI_EXTENSION_ID = 'wso2.wso2-integrator'; +export const WI_PROJECT_EXPLORER_VIEW_ID = 'wso2-integrator.explorer'; +export const WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND = 'wso2-integrator.explorer.refresh'; +export const MI_PROJECT_EXPLORER_VIEW_ID = 'MI.project-explorer'; diff --git a/workspaces/mi/mi-extension/src/project-explorer/activate.ts b/workspaces/mi/mi-extension/src/project-explorer/activate.ts index dbd74d9f170..b07795cf1f3 100644 --- a/workspaces/mi/mi-extension/src/project-explorer/activate.ts +++ b/workspaces/mi/mi-extension/src/project-explorer/activate.ts @@ -20,7 +20,7 @@ import * as vscode from 'vscode'; import { ProjectExplorerEntry, ProjectExplorerEntryProvider } from './project-explorer-provider'; import { getStateMachine, openView, refreshUI } from '../stateMachine'; import { EVENT_TYPE, MACHINE_VIEW, VisualizerLocation } from '@wso2/mi-core'; -import { COMMANDS } from '../constants'; +import { COMMANDS, WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND } from '../constants'; import { ExtensionContext, TreeItem, Uri, ViewColumn, commands, window, workspace } from 'vscode'; import path = require("path"); import { deleteRegistryResource, deleteDataMapperResources, deleteSchemaResources } from '../util/fileOperations'; @@ -34,11 +34,10 @@ import { compareVersions } from '../util/onboardingUtils'; import { removeFromHistory } from '../history'; import * as fs from "fs"; import { webviews } from '../visualizer/webview'; -import { log } from '../util/logger'; import { MILanguageClient } from '../lang-client/activator'; let isProjectExplorerInitialized = false; -export async function activateProjectExplorer(context: ExtensionContext, lsClient: ExtendedLanguageClient) { +export async function activateProjectExplorer(treeviewId: string, context: ExtensionContext, lsClient: ExtendedLanguageClient, isInWI: boolean) { if (isProjectExplorerInitialized) { return; } @@ -47,13 +46,13 @@ export async function activateProjectExplorer(context: ExtensionContext, lsClien const projectExplorerDataProvider = new ProjectExplorerEntryProvider(context); await projectExplorerDataProvider.refresh(); let registryExplorerDataProvider; - const projectTree = window.createTreeView('MI.project-explorer', { treeDataProvider: projectExplorerDataProvider }); + const projectTree = window.createTreeView(treeviewId, { treeDataProvider: projectExplorerDataProvider }); const projectDetailsRes = await lsClient?.getProjectDetails(); const runtimeVersion = projectDetailsRes.primaryDetails.runtimeVersion.value; const isRegistrySupported = compareVersions(runtimeVersion, RUNTIME_VERSION_440) < 0; - commands.registerCommand(COMMANDS.REFRESH_COMMAND, () => { return projectExplorerDataProvider.refresh(); }); + commands.registerCommand(isInWI ? WI_PROJECT_EXPLORER_VIEW_REFRESH_COMMAND : COMMANDS.REFRESH_COMMAND, () => { return projectExplorerDataProvider.refresh(); }); commands.registerCommand(COMMANDS.ADD_ARTIFACT_COMMAND, (entry: ProjectExplorerEntry) => { openView(EVENT_TYPE.OPEN_VIEW, { view: MACHINE_VIEW.ADD_ARTIFACT, projectUri: entry.info?.path }); @@ -635,7 +634,7 @@ export async function activateProjectExplorer(context: ExtensionContext, lsClien if (projectUri) { const currentLocation = getStateMachine(projectUri).context(); if (currentLocation.documentUri === file) { - openView(EVENT_TYPE.REPLACE_VIEW, { view: MACHINE_VIEW.Overview, projectUri }); + openView(EVENT_TYPE.REPLACE_VIEW, { view: MACHINE_VIEW.Overview, projectUri }); } else if (currentLocation?.view === MACHINE_VIEW.Overview) { refreshUI(projectUri); } diff --git a/workspaces/mi/mi-extension/src/stateMachine.ts b/workspaces/mi/mi-extension/src/stateMachine.ts index 94e29008ffd..1b8b46c8a7c 100644 --- a/workspaces/mi/mi-extension/src/stateMachine.ts +++ b/workspaces/mi/mi-extension/src/stateMachine.ts @@ -18,10 +18,10 @@ import { ExtendedLanguageClient } from './lang-client/ExtendedLanguageClient'; import { VisualizerWebview, webviews } from './visualizer/webview'; import { RPCLayer } from './RPCLayer'; import { history } from './history/activator'; -import { COMMANDS } from './constants'; +import { COMMANDS, MI_PROJECT_EXPLORER_VIEW_ID, WI_EXTENSION_ID, WI_PROJECT_EXPLORER_VIEW_ID } from './constants'; import { activateProjectExplorer } from './project-explorer/activate'; import { MockService, STNode, UnitTest, Task, InboundEndpoint } from '../../syntax-tree/lib/src'; -import { logDebug } from './util/logger'; +import { log, logDebug } from './util/logger'; import { deriveConfigName, getSources } from './util/dataMapper'; import { fileURLToPath } from 'url'; import path = require('path'); @@ -36,10 +36,10 @@ const fs = require('fs'); interface MachineContext extends VisualizerLocation { langClient: ExtendedLanguageClient | null; dependenciesResolved?: boolean; + isInWI: boolean; } const stateMachine = createMachine({ - /** @xstate-layout N4IgpgJg5mDOIC5QFsCWA6VA7VAXVAhgDaoBeYAxBAPZZiZYBu1A1vQMYAWY7LACgCdqAKx64A2gAYAuolAAHarDypackAA9EAJm0A2dJICs2yQE49k7QEYT1vXoA0IAJ469ADnTWPAdiOSDkY+gX4AvmHOaAwqxGSUNHQMzGzoXDz8QqLsEtaySCCKyvhqBVoINgbGphZWtpVOrojW-uhGetomehYWHtpmRhFRGNixJORUtPTYKRzcvIIiYuLa+QpKKqWg5aZVJuaWNnYOzm4IfehmAMy+ACz+vleS1mbaV9pDINGj+HETidMmKw5hlFtkJFc1oUNiUsOodlc9jVDvV7I0zlcBug7k9btdfHpbHjPt8cL9xgkpslgWl5pkljlxLcoUVNnCyjpbkiDnVjujEITtOgPCKRf1Xo9jCSRmTCBSKGABEIBOh5EQCLgAGbUATIWmgrLLGTqVmw+GIEynZoedroLmPW67PoEjzStK0Og5HUASTJkySMxp0XYHrEPrJCED7A1qiwUmk8ZNMNj5oQvjMt0Mt3svg8xl8L35FSMV28RjMjxMHgs7w8ejd8kNOQAImBcGJIP7AbN0NFGwzcK32zlIJGgdHYfHEwVTSmOQgOlaEPYWpc9I8M9ZbpJbqK3dQiBAwWIhx2IF3qalogej03B22z2PmBPY1PjTPk1tNIhfNol7ZfEkO112zHcrm3FpfDdIhYF9PAL0DK8MBguDcCfagX1oN8WU-dltkQe4jGxQCPExDxbluTEzGsf8iXQJ4jBLSwAj0K4Xmg2C-QBS96GiFCIyjGMsJkcQ8iTYo53whAuSI3wSLIiiqJoppl0Cax0E8Yx2kRG1JFdSIvmQzj4MVZVVXVLUdT1PjjLQwTJxE991gkr9ykI4i9IUyizGo-9CQMbo9BLEtAiMPo3QEMACAgFx0AIHJUEYDUwAAeVwbgBAAMSi3AAFdItgBCgSQ9BIui2L4vwJL2zSjLso1fK4HQzC40cnCXLw79VOubxbjCm4rhFDpJF8f9fy8UijD68jrCsfRBgM6Iypi9BGFQMAAHcABlqGi7AoCKnslqila1s2na9qwKBmqE1qEyc6EOtTWwOmFPRpu0G08QGUaVPsIxfHQbRfwzbcnjzFoIpO2Kzo2zLsAgfbDqDDBlph9a4YR-aboc+72rZZ6My8V5uhuEUKxuIw-PA7FZsdDxbERK4rgW4ZSuh1aMYAZVweKWCR7jEN41GOdhnm+ex+zXza8SCfnN4bDtewKLkl5Qb8gGgZBijJHB54oMWkXys5zaAFV5AgZLz0F4rhfZ43YfNy32wgHHpbx2WzXnFpWOFZmXkkQOt06P8-sU4DdfA9MOlJqGHYxgA5Ag1qgK3kZKtGTY2pOU6tt3hI9j8nvl951Ozd77gLHyKP-d4hW8rkgjCkw49OjGACVoYoFK+AAUQTgB9AA1b1e4AdWnZy5ak2aeq3frHiG0xfrOexmaB2abgeaj3tZwz7bbzbO-Kih297vgtoAQQAYV74fR4nh7Z1c5pzFLefSMXutl--EtAeb-oIEGZWH0mzTOsNj4xQoAnS+I8ADil8AAqvdJ6PWnl1We79poDSXiNf8FF1K1BZiHIK5Y97HXjkfLumVvRbTvr3Zs3pEGoOfp1comDeoL0Gt-PBf1TBAR8BmQk9xtykWsK3dGm1e6I3wFdCgDCmED2bClBOKCn64Wei8UsZhqxBXXBWOs1hQ6ry3GYDS1ZsxvApgDchGA6AbWPDkLOF1EZyJtkdOxm1HG4GcbtVx10pYFxYRo+cDN1KWEdC0AYg0WYrx-FYei9wbAZmop9DMbp7HeKzpAlw3c+6DxHuPYJxcpLfzaGxYGgR9C2GuEuSwBhfy6FmjYfwoMIgGSwNQCAcB1BoE9pJLqABaIswzDCB3GRMoOW43Q-DlPEfpL9pLGJ-LoNo1hMSfReFNVitw3QhiwJ6XA4Y8ALLYRaN4Gl54+WIdYZWS5OjqW4dROm2ZfwswbHeU8I4ICnOejueu9xqIUUdGFe5wR6Lk1uTuV5bxbHoBvN4r5LtfnzmCKWYR5Zrh2DuSpBm3gHDrlmoHLemIOKoRRVJYGQpej+CsISNeyzlzlnReBYwEFczMQkRSrqjwDCYjCv0Fo-RcweH-FUtougGb9CmuBBwEi4oJWqqldKip6p5QKty8ouZMz8r6NREGIqxo7jaHUHwn1WmgP3uAjGLj9qauaMzMxfgAgMyjqYq41NqWYksJiPSLR3jythvDLA-j7XLgJKWUibEzDjODpaP6rEvVEJjQzR4HxDYH0kRtcWvA7VF3QTsW5hCfLkXAv1KanrLjet1im-16awGiwxk7K2YaXpeCeKYIxu5tzbPwdmcxAxZqMT0npS1FDD7Z2TqgVOyL81e0pcEPlFcTA2EpoyrcFFvDVmCFpEdIpA0d2hmG6sgNA79D6l29ZBJaKvTrHmZ4LNmZsQPVImReap7zowY64UtLXX3HdbRMKWtgYlmos8PqbpEawAIAAIyIJAMNu8N5+FzKYci5Fbj-lImYhwfguRckCCCjJXi7xhuCpcvqjx-adFBSpYIZjGKMQ2UK+wY7PEOLvL4y6UAyOkQowDJ9RjGKipUoSJ1Qm2U7OBsRjjA5slHrnQM9hzwhQAzSc8Ewry6k3DenmKa5YCwvANhEIAA */ id: 'mi', initial: 'initialize', predictableActionArguments: true, @@ -48,7 +48,8 @@ const stateMachine = createMachine({ langClient: null, errors: [], view: MACHINE_VIEW.Welcome, - dependenciesResolved: false + dependenciesResolved: false, + isInWI: false }, states: { initialize: { @@ -73,7 +74,7 @@ const stateMachine = createMachine({ view: (context, event) => MACHINE_VIEW.UnsupportedProject, projectUri: (context, event) => event.data.projectUri, isOldProject: (context, event) => true, - displayOverview: (context, event) => true, + displayOverview: (context, event) => true }) }, { @@ -84,7 +85,7 @@ const stateMachine = createMachine({ actions: assign({ view: (context, event) => MACHINE_VIEW.UnsupportedWorkspace, projectUri: (context, event) => event.data.projectUri, - displayOverview: (context, event) => true, + displayOverview: (context, event) => true }) }, { @@ -95,14 +96,13 @@ const stateMachine = createMachine({ view: (context, event) => event.data.view, customProps: (context, event) => event.data.customProps, projectUri: (context, event) => event.data.projectUri, - isOldProject: (context, event) => event.data.isOldProject, displayOverview: (context, event) => event.data.displayOverview }) }, { target: 'newProject', // Assuming false means new project - cond: (context, event) => event.data.isProject === false && event.data.isOldProject === false, + cond: (context, event) => !context.isInWI && event.data.isProject === false && event.data.isOldProject === false, actions: assign({ view: (context, event) => MACHINE_VIEW.Welcome }) @@ -113,7 +113,7 @@ const stateMachine = createMachine({ target: 'disabled', actions: assign({ view: (context, event) => MACHINE_VIEW.Disabled, - errors: (context, event) => event.data + errors: (context, event) => event.data, }) } } @@ -391,7 +391,8 @@ const stateMachine = createMachine({ return new Promise(async (resolve, reject) => { console.log("Waiting for LS to be ready " + new Date().toLocaleTimeString()); try { - vscode.commands.executeCommand(COMMANDS.FOCUS_PROJECT_EXPLORER); + const treeViewId = context.isInWI ? WI_PROJECT_EXPLORER_VIEW_ID : MI_PROJECT_EXPLORER_VIEW_ID; + vscode.commands.executeCommand(`${treeViewId}.focus`); const instance = await MILanguageClient.getInstance(context.projectUri!); const errors = instance.getErrors(); if (errors.length) { @@ -414,6 +415,7 @@ const stateMachine = createMachine({ if (!context?.projectUri) { return reject(new Error("Project URI is not defined")); } + if (!webviews.has(context.projectUri)) { const panel = new VisualizerWebview(context.view!, context.projectUri, extension.webviewReveal); webviews.set(context.projectUri!, panel); @@ -653,7 +655,8 @@ const stateMachine = createMachine({ activateOtherFeatures: (context, event) => { return new Promise(async (resolve, reject) => { const ls = await MILanguageClient.getInstance(context.projectUri!); - await activateProjectExplorer(extension.context, ls.languageClient!); + const treeviewId = context.isInWI ? WI_PROJECT_EXPLORER_VIEW_ID : MI_PROJECT_EXPLORER_VIEW_ID; + await activateProjectExplorer(treeviewId, extension.context, ls.languageClient!, context.isInWI); await activateTestExplorer(extension.context); resolve(true); }); @@ -667,7 +670,8 @@ const stateMachine = createMachine({ }, focusProjectExplorer: (context, event) => { return new Promise(async (resolve, reject) => { - vscode.commands.executeCommand(COMMANDS.FOCUS_PROJECT_EXPLORER); + const treeViewId = context.isInWI ? WI_PROJECT_EXPLORER_VIEW_ID : MI_PROJECT_EXPLORER_VIEW_ID; + vscode.commands.executeCommand(`${treeViewId}.focus`); resolve(true); }); } @@ -691,11 +695,13 @@ export const getStateMachine = (projectUri: string, context?: VisualizerLocation if (!workspaces) { console.warn('No workspace folder is open.'); } + log(vscode.extensions.all.map(ext => ext.id).join(', ')); stateService = interpret(stateMachine.withContext({ projectUri: projectUri, langClient: null, errors: [], view: MACHINE_VIEW.Overview, + isInWI: vscode.extensions.getExtension(WI_EXTENSION_ID) ? true : false, ...context })).start(); stateMachines.set(projectUri, stateService); diff --git a/workspaces/mi/mi-extension/src/visualizer/activate.ts b/workspaces/mi/mi-extension/src/visualizer/activate.ts index a1d53917360..37ac5300459 100644 --- a/workspaces/mi/mi-extension/src/visualizer/activate.ts +++ b/workspaces/mi/mi-extension/src/visualizer/activate.ts @@ -39,65 +39,80 @@ import { getHash } from '../util/fileOperations'; export function activateVisualizer(context: vscode.ExtensionContext, firstProject: string) { context.subscriptions.push( - vscode.commands.registerCommand(COMMANDS.OPEN_PROJECT, () => { - window.showOpenDialog({ canSelectFolders: true, canSelectFiles: true, filters: { 'CAPP': ['car', 'zip'] }, openLabel: 'Open MI Project' }) - .then(uri => { - if (uri && uri[0]) { - const handleOpenProject = (folderUri: vscode.Uri) => { - window.showInformationMessage('Where would you like to open the project?', - { modal: true }, - 'Current Window', - 'New Window' - ).then(selection => { - if (selection === "Current Window") { - const workspaceFolders = workspace.workspaceFolders || []; - if (!workspaceFolders.some(folder => folder.uri.fsPath === folderUri.fsPath)) { - workspace.updateWorkspaceFolders(workspaceFolders.length, 0, { uri: folderUri }); - } - } else if (selection === "New Window") { - commands.executeCommand('vscode.openFolder', folderUri); + vscode.commands.registerCommand(COMMANDS.OPEN_PROJECT, (providedUri?: vscode.Uri) => { + const processUri = (uri: vscode.Uri[] | undefined) => { + if (uri && uri[0]) { + const handleOpenProject = (folderUri: vscode.Uri) => { + window.showInformationMessage('Where would you like to open the project?', + { modal: true }, + 'Current Window', + 'New Window' + ).then(selection => { + if (selection === "Current Window") { + const workspaceFolders = workspace.workspaceFolders || []; + if (!workspaceFolders.some(folder => folder.uri.fsPath === folderUri.fsPath)) { + workspace.updateWorkspaceFolders(workspaceFolders.length, 0, { uri: folderUri }); } - }); - }; - if (uri[0].fsPath.endsWith('.car') || uri[0].fsPath.endsWith('.zip')) { - window.showInformationMessage('A car file (CAPP) is selected.\n Do you want to extract it?', { modal: true }, 'Extract') - .then(option => { - if (option === 'Extract') { - window.showOpenDialog({ canSelectFolders: true, canSelectFiles: false, title: 'Select the location to extract the CAPP', openLabel: 'Select Folder' }) - .then(extractUri => { - if (extractUri && extractUri[0]) { - importCapp({ source: uri[0].fsPath, directory: extractUri[0].fsPath, open: false }); - handleOpenProject(extractUri[0]); + } else if (selection === "New Window") { + commands.executeCommand('vscode.openFolder', folderUri); + } + }); + }; + if (uri[0].fsPath.endsWith('.car') || uri[0].fsPath.endsWith('.zip')) { + window.showInformationMessage('A car file (CAPP) is selected.\n Do you want to extract it?', { modal: true }, 'Extract') + .then(option => { + if (option === 'Extract') { + window.showOpenDialog({ canSelectFolders: true, canSelectFiles: false, title: 'Select the location to extract the CAPP', openLabel: 'Select Folder' }) + .then(async extractUri => { + if (extractUri && extractUri[0]) { + try { + const result = await importCapp({ source: uri[0].fsPath, directory: extractUri[0].fsPath, open: false }); + if (result.filePath) { + handleOpenProject(extractUri[0]); + } else { + window.showErrorMessage('Failed to import CAPP. Please check the file and try again.'); + } + } catch (error: any) { + window.showErrorMessage(`CAPP import failed: ${error.message}`); } - }); - } - }); + } + }); + } + }); + } else { + const webview = [...webviews.values()].find(webview => webview.getWebview()?.active) || [...webviews.values()][0]; + const projectUri = webview ? webview.getProjectUri() : firstProject; + const projectOpened = getStateMachine(projectUri).context().projectOpened; + if (projectOpened) { + handleOpenProject(uri[0]); } else { - const webview = [...webviews.values()].find(webview => webview.getWebview()?.active) || [...webviews.values()][0]; - const projectUri = webview ? webview.getProjectUri() : firstProject; - const projectOpened = getStateMachine(projectUri).context().projectOpened; - if (projectOpened) { - handleOpenProject(uri[0]); - } else { - commands.executeCommand('vscode.openFolder', uri[0]); - } + commands.executeCommand('vscode.openFolder', uri[0]); } } - }); + } + }; + + if (providedUri) { + processUri([providedUri]); + } else { + window.showOpenDialog({ canSelectFolders: true, canSelectFiles: true, filters: { 'CAPP': ['car', 'zip'] }, openLabel: 'Open MI Project' }) + .then(processUri); + } }), commands.registerCommand(COMMANDS.CREATE_PROJECT_COMMAND, async (args) => { if (args && args.name && args.path && args.scope) { const rpcManager = new MiDiagramRpcManager(""); if (rpcManager) { - await rpcManager.createProject( + const result = await rpcManager.createProject( { directory: path.dirname(args.path), name: path.basename(args.path), - open: false, + open: args.open ?? false, miVersion: "4.4.0" } ); await createSettingsFile(args); + return result; } async function createSettingsFile(args) {