deploy: current vibn theia state
Some checks failed
Playwright Tests / Playwright Tests (ubuntu-22.04, Node.js 22.x) (push) Has been cancelled
3PP License Check / 3PP License Check (11, 22.x, ubuntu-22.04) (push) Has been cancelled
Publish packages to NPM / Perform Publishing (push) Has been cancelled

Made-with: Cursor
This commit is contained in:
2026-02-27 12:01:08 -08:00
commit 8bb5110148
3782 changed files with 640947 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: [
'../../configs/build.eslintrc.json'
],
parserOptions: {
tsconfigRootDir: __dirname,
project: 'tsconfig.json'
}
};

View File

@@ -0,0 +1,32 @@
<div align='center'>
<br />
<img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
<h2>ECLIPSE THEIA - PLUGIN-EXT-VSCODE EXTENSION</h2>
<hr />
</div>
## Description
The `@theia/plugin-ext-vscode` extension contributes functionality to be able to successfully run VS Code extensions in the application.
The extension is mandatory for any application which requires VS Code extension support.
## Additional Information
- [API documentation for `@theia/plugin-ext-vscode`](https://eclipse-theia.github.io/theia/docs/next/modules/_theia_plugin-ext-vscode.html)
- [Theia - GitHub](https://github.com/eclipse-theia/theia)
- [Theia - Website](https://theia-ide.org/)
## License
- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
## Trademark
"Theia" is a trademark of the Eclipse Foundation
<https://www.eclipse.org/theia>

View File

@@ -0,0 +1,65 @@
{
"name": "@theia/plugin-ext-vscode",
"version": "1.68.0",
"description": "Theia - Plugin Extension for VsCode",
"dependencies": {
"@theia/callhierarchy": "1.68.0",
"@theia/core": "1.68.0",
"@theia/editor": "1.68.0",
"@theia/filesystem": "1.68.0",
"@theia/monaco": "1.68.0",
"@theia/monaco-editor-core": "1.96.302",
"@theia/navigator": "1.68.0",
"@theia/outline-view": "1.68.0",
"@theia/plugin": "1.68.0",
"@theia/plugin-ext": "1.68.0",
"@theia/scm": "1.68.0",
"@theia/terminal": "1.68.0",
"@theia/typehierarchy": "1.68.0",
"@theia/userstorage": "1.68.0",
"@theia/workspace": "1.68.0",
"decompress": "^4.2.1",
"filenamify": "^4.1.0",
"tslib": "^2.6.2"
},
"publishConfig": {
"access": "public"
},
"theiaExtensions": [
{
"backend": "lib/node/plugin-vscode-backend-module",
"frontend": "lib/browser/plugin-vscode-frontend-module"
}
],
"keywords": [
"theia-extension"
],
"license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
"repository": {
"type": "git",
"url": "https://github.com/eclipse-theia/theia.git"
},
"bugs": {
"url": "https://github.com/eclipse-theia/theia/issues"
},
"homepage": "https://github.com/eclipse-theia/theia",
"files": [
"lib",
"src"
],
"scripts": {
"build": "theiaext build",
"clean": "theiaext clean",
"compile": "theiaext compile",
"lint": "theiaext lint",
"test": "theiaext test",
"watch": "theiaext watch"
},
"devDependencies": {
"@theia/ext-scripts": "1.68.0"
},
"nyc": {
"extends": "../../configs/nyc.json"
},
"gitHead": "21358137e41342742707f660b8e222f940a27652"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
// *****************************************************************************
// Copyright (C) 2020 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable } from '@theia/core/shared/inversify';
import { UserStorageUri } from '@theia/userstorage/lib/browser/user-storage-uri';
import { FileServiceContribution, FileService } from '@theia/filesystem/lib/browser/file-service';
import { Schemes } from '@theia/plugin-ext/lib/common/uri-components';
import { DelegatingFileSystemProvider } from '@theia/filesystem/lib/common/delegating-file-system-provider';
@injectable()
export class PluginVSCodeContribution implements FileServiceContribution {
registerFileSystemProviders(service: FileService): void {
this.mapSchemas(service, Schemes.vscodeRemote, 'file');
this.mapSchemas(service, Schemes.userData, UserStorageUri.scheme);
}
protected mapSchemas(service: FileService, from: string, to: string): void {
service.onWillActivateFileSystemProvider(event => {
if (event.scheme === from) {
event.waitUntil((async () => {
const provider = await service.activateProvider(to);
service.registerProvider(from, new DelegatingFileSystemProvider(provider, {
uriConverter: {
to: resource => resource.withScheme(to),
from: resource => resource.withScheme(from)
}
}));
})());
}
});
}
}

View File

@@ -0,0 +1,30 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { ContainerModule } from '@theia/core/shared/inversify';
import { CommandContribution } from '@theia/core';
import { PluginVscodeCommandsContribution } from './plugin-vscode-commands-contribution';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
import { PluginVSCodeContribution } from './plugin-vscode-contribution';
import { FileServiceContribution } from '@theia/filesystem/lib/browser/file-service';
export default new ContainerModule(bind => {
bind(PluginVSCodeEnvironment).toSelf().inSingletonScope();
bind(PluginVscodeCommandsContribution).toSelf().inSingletonScope();
bind(CommandContribution).toService(PluginVscodeCommandsContribution);
bind(PluginVSCodeContribution).toSelf().inSingletonScope();
bind(FileServiceContribution).toService(PluginVSCodeContribution);
});

View File

@@ -0,0 +1,59 @@
// *****************************************************************************
// Copyright (C) 2020 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable, inject } from '@theia/core/shared/inversify';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import URI from '@theia/core/lib/common/uri';
@injectable()
export class PluginVSCodeEnvironment {
@inject(EnvVariablesServer)
protected readonly environments: EnvVariablesServer;
protected _userExtensionsDirUri: URI | undefined;
protected _deployedPluginsUri: URI | undefined;
protected _tmpDirUri: URI | undefined;
async getUserExtensionsDirUri(): Promise<URI> {
if (!this._userExtensionsDirUri) {
const configDir = new URI(await this.environments.getConfigDirUri());
this._userExtensionsDirUri = configDir.resolve('extensions');
}
return this._userExtensionsDirUri;
}
async getDeploymentDirUri(): Promise<URI> {
if (!this._deployedPluginsUri) {
const configDir = new URI(await this.environments.getConfigDirUri());
this._deployedPluginsUri = configDir.resolve('deployedPlugins');
}
return this._deployedPluginsUri;
}
async getTempDirUri(prefix?: string): Promise<URI> {
if (!this._tmpDirUri) {
const configDir: URI = new URI(await this.environments.getConfigDirUri());
this._tmpDirUri = configDir.resolve('tmp');
}
if (prefix) {
return this._tmpDirUri.resolve(prefix);
}
return this._tmpDirUri;
}
}

View File

@@ -0,0 +1,20 @@
// *****************************************************************************
// Copyright (C) 2020 Ericsson and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { DEFAULT_SUPPORTED_API_VERSION } from '@theia/core/shared/@theia/application-package/lib/api';
export const VSCODE_DEFAULT_API_VERSION = DEFAULT_SUPPORTED_API_VERSION;
export const VSX_REGISTRY_URL_DEFAULT = 'https://open-vsx.org';

View File

@@ -0,0 +1,45 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import URI from '@theia/core/lib/common/uri';
/**
* Static methods for identifying a plugin as the target of the VSCode deployment system.
* In practice, this means that it will be resolved and deployed by the Open-VSX system.
*/
export namespace VSCodeExtensionUri {
export const SCHEME = 'vscode-extension';
export function fromId(id: string, version?: string): URI {
if (typeof version === 'string') {
return new URI().withScheme(VSCodeExtensionUri.SCHEME).withAuthority(id).withPath(`/${version}`);
} else {
return new URI().withScheme(VSCodeExtensionUri.SCHEME).withAuthority(id);
}
}
export function fromVersionedId(versionedId: string): URI {
const versionAndId = versionedId.split('@');
return fromId(versionAndId[0], versionAndId[1]);
}
export function toId(uri: URI): { id: string, version?: string } | undefined {
if (uri.scheme === VSCodeExtensionUri.SCHEME) {
return { id: uri.authority, version: uri.path.isRoot ? undefined : uri.path.base };
}
return undefined;
}
}

View File

@@ -0,0 +1,43 @@
// *****************************************************************************
// Copyright (C) 2022 Arm and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const _scope = (this as any);
_scope.exports = {};
const _getModule = () => {
if (!_scope[_scope.frontendModuleName]) {
_scope[_scope.frontendModuleName] = {};
}
return _scope[_scope.frontendModuleName];
};
Object.defineProperty(_scope.exports, 'activate', {
set: value => _getModule().activate = value
});
Object.defineProperty(_scope.exports, 'deactivate', {
set: value => _getModule().deactivate = value
});
_scope.require = (moduleName: string) => {
const vscodeModuleName = 'vscode';
if (moduleName === vscodeModuleName) {
// Return the defaultApi
return _scope.theia._empty;
}
};

View File

@@ -0,0 +1,51 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import * as path from 'path';
import { inject, injectable } from '@theia/core/shared/inversify';
import { PluginDeployerResolverContext } from '@theia/plugin-ext';
import { LocalPluginDeployerResolver } from '@theia/plugin-ext/lib/main/node/resolvers/local-plugin-deployer-resolver';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
import { isVSCodePluginFile } from './plugin-vscode-file-handler';
import { existsInDeploymentDir, unpackToDeploymentDir } from './plugin-vscode-utils';
@injectable()
export class LocalVSIXFilePluginDeployerResolver extends LocalPluginDeployerResolver {
static LOCAL_FILE = 'local-file';
static FILE_EXTENSION = '.vsix';
@inject(PluginVSCodeEnvironment) protected readonly environment: PluginVSCodeEnvironment;
protected get supportedScheme(): string {
return LocalVSIXFilePluginDeployerResolver.LOCAL_FILE;
}
override accept(pluginId: string): boolean {
return super.accept(pluginId) && isVSCodePluginFile(pluginId);
}
async resolveFromLocalPath(pluginResolverContext: PluginDeployerResolverContext, localPath: string): Promise<void> {
const extensionId = path.basename(localPath, LocalVSIXFilePluginDeployerResolver.FILE_EXTENSION);
if (await existsInDeploymentDir(this.environment, extensionId)) {
console.log(`[${pluginResolverContext.getOriginId()}]: Target dir already exists in plugin deployment dir`);
return;
}
const extensionDeploymentDir = await unpackToDeploymentDir(this.environment, localPath, extensionId);
pluginResolverContext.addPlugin(extensionId, extensionDeploymentDir);
}
}

View File

@@ -0,0 +1,28 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
/* note: this bogus test file is required so that
we are able to run mocha unit tests on this
package, without having any actual unit tests in it.
This way a coverage report will be generated,
showing 0% coverage, instead of no report.
This file can be removed once we have real unit
tests in place. */
describe('plugin-ext-vscode package', () => {
it('support code coverage statistics', () => true);
});

View File

@@ -0,0 +1,46 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { ContainerModule } from '@theia/core/shared/inversify';
import {
PluginDeployerFileHandler, PluginDeployerDirectoryHandler, PluginScanner, PluginDeployerParticipant, PluginDeployerResolver
} from '@theia/plugin-ext';
import { PluginVsCodeFileHandler } from './plugin-vscode-file-handler';
import { PluginVsCodeDirectoryHandler } from './plugin-vscode-directory-handler';
import { VsCodePluginScanner } from './scanner-vscode';
import { PluginVsCodeCliContribution } from './plugin-vscode-cli-contribution';
import { CliContribution } from '@theia/core/lib/node';
import { PluginHostEnvironmentVariable } from '@theia/plugin-ext/lib/common';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
import { PluginVSCodeDeployerParticipant } from './plugin-vscode-deployer-participant';
import { LocalVSIXFilePluginDeployerResolver } from './local-vsix-file-plugin-deployer-resolver';
export default new ContainerModule(bind => {
bind(PluginVSCodeEnvironment).toSelf().inSingletonScope();
bind(PluginVSCodeDeployerParticipant).toSelf().inSingletonScope();
bind(PluginDeployerParticipant).toService(PluginVSCodeDeployerParticipant);
bind(PluginDeployerFileHandler).to(PluginVsCodeFileHandler).inSingletonScope();
bind(PluginDeployerDirectoryHandler).to(PluginVsCodeDirectoryHandler).inSingletonScope();
bind(PluginScanner).to(VsCodePluginScanner).inSingletonScope();
bind(PluginVsCodeCliContribution).toSelf().inSingletonScope();
bind(CliContribution).toService(PluginVsCodeCliContribution);
bind(PluginHostEnvironmentVariable).toService(PluginVsCodeCliContribution);
bind(PluginDeployerResolver).to(LocalVSIXFilePluginDeployerResolver).inSingletonScope();
});

View File

@@ -0,0 +1,64 @@
// *****************************************************************************
// Copyright (C) 2019 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable } from '@theia/core/shared/inversify';
import { Argv, Arguments } from '@theia/core/shared/yargs';
import { CliContribution } from '@theia/core/lib/node/cli';
import { PluginHostEnvironmentVariable } from '@theia/plugin-ext/lib/common';
import { VSCODE_DEFAULT_API_VERSION } from '../common/plugin-vscode-types';
import { Deferred } from '@theia/core/lib/common/promise-util';
/**
* CLI Contribution allowing to override the VS Code API version which is returned by `vscode.version` API call.
*/
@injectable()
export class PluginVsCodeCliContribution implements CliContribution, PluginHostEnvironmentVariable {
/**
* CLI argument name to define the supported VS Code API version.
*/
static VSCODE_API_VERSION = 'vscode-api-version';
protected vsCodeApiVersion?: string;
protected vsCodeApiVersionDeferred = new Deferred<string>();
get vsCodeApiVersionPromise(): Promise<string> {
return this.vsCodeApiVersionDeferred.promise;
}
configure(conf: Argv): void {
conf.option(PluginVsCodeCliContribution.VSCODE_API_VERSION, {
// eslint-disable-next-line max-len
description: `Overrides the version returned by VSCode API 'vscode.version'. Example: --${PluginVsCodeCliContribution.VSCODE_API_VERSION}=<Wanted Version>. Default [${VSCODE_DEFAULT_API_VERSION}]`,
type: 'string',
nargs: 1
});
}
setArguments(args: Arguments): void {
const arg = args[PluginVsCodeCliContribution.VSCODE_API_VERSION] as string | undefined;
this.vsCodeApiVersion = arg?.trim() || process.env['VSCODE_API_VERSION']?.trim() || VSCODE_DEFAULT_API_VERSION;
process.env['VSCODE_API_VERSION'] = this.vsCodeApiVersion;
this.vsCodeApiVersionDeferred.resolve(this.vsCodeApiVersion);
}
process(env: NodeJS.ProcessEnv): void {
if (this.vsCodeApiVersion) {
env['VSCODE_API_VERSION'] = this.vsCodeApiVersion;
}
}
}

View File

@@ -0,0 +1,48 @@
// *****************************************************************************
// Copyright (C) 2020 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable, inject } from '@theia/core/shared/inversify';
import * as fs from '@theia/core/shared/fs-extra';
import { FileUri } from '@theia/core/lib/node';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
import { PluginDeployerParticipant, PluginDeployerStartContext } from '@theia/plugin-ext/lib/common/plugin-protocol';
import { LocalVSIXFilePluginDeployerResolver } from './local-vsix-file-plugin-deployer-resolver';
@injectable()
export class PluginVSCodeDeployerParticipant implements PluginDeployerParticipant {
@inject(PluginVSCodeEnvironment)
protected readonly environments: PluginVSCodeEnvironment;
async onWillStart(context: PluginDeployerStartContext): Promise<void> {
const extensionDeploymentDirUri = await this.environments.getDeploymentDirUri();
context.userEntries.push(extensionDeploymentDirUri.withScheme('local-dir').toString());
const userExtensionDirUri = await this.environments.getUserExtensionsDirUri();
const userExtensionDirPath = FileUri.fsPath(userExtensionDirUri);
if (await fs.pathExists(userExtensionDirPath)) {
const files = await fs.readdir(userExtensionDirPath);
for (const file of files) {
if (file.endsWith(LocalVSIXFilePluginDeployerResolver.FILE_EXTENSION)) {
const extensionUri = userExtensionDirUri.resolve(file).withScheme('local-file').toString();
console.log(`found drop-in extension "${extensionUri}"`);
context.userEntries.push(extensionUri);
}
}
}
}
}

View File

@@ -0,0 +1,123 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import * as path from 'path';
import * as fs from '@theia/core/shared/fs-extra';
import { inject, injectable } from '@theia/core/shared/inversify';
import type { RecursivePartial, URI } from '@theia/core';
import { Deferred, firstTrue } from '@theia/core/lib/common/promise-util';
import {
PluginDeployerDirectoryHandler, PluginDeployerEntry, PluginDeployerDirectoryHandlerContext,
PluginDeployerEntryType, PluginPackage, PluginIdentifiers
} from '@theia/plugin-ext';
import { PluginCliContribution } from '@theia/plugin-ext/lib/main/node/plugin-cli-contribution';
import { TMP_DIR_PREFIX } from './plugin-vscode-utils';
@injectable()
export class PluginVsCodeDirectoryHandler implements PluginDeployerDirectoryHandler {
protected readonly deploymentDirectory: Deferred<URI>;
@inject(PluginCliContribution) protected readonly pluginCli: PluginCliContribution;
async accept(plugin: PluginDeployerEntry): Promise<boolean> {
console.debug(`Resolving "${plugin.id()}" as a VS Code extension...`);
if (plugin.path().startsWith(TMP_DIR_PREFIX)) {
// avoid adding corrupted plugins from temporary directories
return false;
}
return this.attemptResolution(plugin);
}
protected async attemptResolution(plugin: PluginDeployerEntry): Promise<boolean> {
if (this.resolvePackage(plugin)) {
return true;
}
return this.deriveMetadata(plugin);
}
protected async deriveMetadata(plugin: PluginDeployerEntry): Promise<boolean> {
return firstTrue(
this.resolveFromSources(plugin),
this.resolveFromVSIX(plugin),
this.resolveFromNpmTarball(plugin)
);
}
async handle(context: PluginDeployerDirectoryHandlerContext): Promise<void> {
const types: PluginDeployerEntryType[] = [];
const packageJson: PluginPackage = context.pluginEntry().getValue('package.json');
if (packageJson.browser) {
types.push(PluginDeployerEntryType.FRONTEND);
}
if (packageJson.main || !packageJson.browser) {
types.push(PluginDeployerEntryType.BACKEND);
}
context.pluginEntry().accept(...types);
}
protected async resolveFromSources(plugin: PluginDeployerEntry): Promise<boolean> {
const pluginPath = plugin.path();
const pck = await this.requirePackage(pluginPath);
return this.resolvePackage(plugin, { pluginPath, pck });
}
protected async resolveFromVSIX(plugin: PluginDeployerEntry): Promise<boolean> {
if (!(await fs.pathExists(path.join(plugin.path(), 'extension.vsixmanifest')))) {
return false;
}
const pluginPath = path.join(plugin.path(), 'extension');
const pck = await this.requirePackage(pluginPath);
return this.resolvePackage(plugin, { pluginPath, pck });
}
protected async resolveFromNpmTarball(plugin: PluginDeployerEntry): Promise<boolean> {
const pluginPath = path.join(plugin.path(), 'package');
const pck = await this.requirePackage(pluginPath);
return this.resolvePackage(plugin, { pluginPath, pck });
}
protected resolvePackage(plugin: PluginDeployerEntry, options?: {
pluginPath: string
pck?: RecursivePartial<PluginPackage>
}): boolean {
const { pluginPath, pck } = options || {
pluginPath: plugin.path(),
pck: plugin.getValue('package.json')
};
if (!pck || !pck.name || !pck.version || !pck.engines || !pck.engines.vscode) {
return false;
}
pck.publisher ??= PluginIdentifiers.UNPUBLISHED;
if (options) {
plugin.storeValue('package.json', pck);
plugin.rootPath = plugin.path();
plugin.updatePath(pluginPath);
}
console.debug(`Resolved "${plugin.id()}" to a VS Code extension "${pck.name}@${pck.version}" with engines:`, pck.engines);
return true;
}
protected async requirePackage(pluginPath: string): Promise<PluginPackage | undefined> {
try {
const plugin: PluginPackage = await fs.readJSON(path.join(pluginPath, 'package.json'));
plugin.publisher ??= PluginIdentifiers.UNPUBLISHED;
return plugin;
} catch {
return undefined;
}
}
}

View File

@@ -0,0 +1,62 @@
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { PluginDeployerFileHandler, PluginDeployerEntry, PluginDeployerFileHandlerContext } from '@theia/plugin-ext';
import * as filenamify from 'filenamify';
import { inject, injectable } from '@theia/core/shared/inversify';
import * as fs from '@theia/core/shared/fs-extra';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
import { FileUri } from '@theia/core/lib/common/file-uri';
import { unpackToDeploymentDir } from './plugin-vscode-utils';
export const isVSCodePluginFile = (pluginPath?: string) => Boolean(pluginPath && (pluginPath.endsWith('.vsix') || pluginPath.endsWith('.tgz')));
@injectable()
export class PluginVsCodeFileHandler implements PluginDeployerFileHandler {
@inject(PluginVSCodeEnvironment)
protected readonly environment: PluginVSCodeEnvironment;
async accept(resolvedPlugin: PluginDeployerEntry): Promise<boolean> {
return resolvedPlugin.isFile().then(file => {
if (!file) {
return false;
}
return isVSCodePluginFile(resolvedPlugin.path());
});
}
async handle(context: PluginDeployerFileHandlerContext): Promise<void> {
const id = this.getNormalizedExtensionId(context.pluginEntry().id());
const extensionDeploymentDir = await unpackToDeploymentDir(this.environment, context.pluginEntry().path(), id);
context.pluginEntry().updatePath(extensionDeploymentDir);
console.log(`root path: ${context.pluginEntry().rootPath}`);
const originalPath = context.pluginEntry().originalPath();
if (originalPath && originalPath !== extensionDeploymentDir) {
const tempDirUri = await this.environment.getTempDirUri();
if (originalPath.startsWith(FileUri.fsPath(tempDirUri))) {
try {
await fs.remove(FileUri.fsPath(originalPath));
} catch (e) {
console.error(`[${id}]: failed to remove temporary files: "${originalPath}"`, e);
}
}
}
}
protected getNormalizedExtensionId(pluginId: string): string {
return filenamify(pluginId, { replacement: '_' }).replace(/\.vsix$/, '');
}
}

View File

@@ -0,0 +1,80 @@
// *****************************************************************************
// Copyright (C) 2018-2019 Red Hat, Inc.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as theia from '@theia/plugin';
import { BackendInitializationFn, PluginAPIFactory, Plugin, emptyPlugin } from '@theia/plugin-ext';
import { VSCODE_DEFAULT_API_VERSION } from '../common/plugin-vscode-types';
process.env['VSCODE_PID'] = process.env['THEIA_PARENT_PID'];
const pluginsApiImpl = new Map<string, typeof theia>();
const plugins = new Array<Plugin>();
let defaultApi: typeof theia;
let isLoadOverride = false;
let pluginApiFactory: PluginAPIFactory;
export const doInitialization: BackendInitializationFn = (apiFactory: PluginAPIFactory, plugin: Plugin) => {
pluginsApiImpl.set(plugin.model.id, createVSCodeAPI(apiFactory, plugin));
plugins.push(plugin);
pluginApiFactory = apiFactory;
if (!isLoadOverride) {
overrideInternalLoad();
isLoadOverride = true;
}
};
function createVSCodeAPI(apiFactory: PluginAPIFactory, plugin: Plugin): typeof theia {
const vscode = apiFactory(plugin);
// override the version for vscode to be a VSCode version
(<any>vscode).version = process.env['VSCODE_API_VERSION'] || VSCODE_DEFAULT_API_VERSION;
return vscode;
}
function overrideInternalLoad(): void {
const module = require('module');
const vscodeModuleName = 'vscode';
// save original load method
const internalLoad = module._load;
// if we try to resolve theia module, return the filename entry to use cache.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
module._load = function (request: string, parent: any, isMain: {}): any {
if (request !== vscodeModuleName) {
return internalLoad.apply(this, arguments);
}
const plugin = findPlugin(parent.filename);
if (plugin) {
const apiImpl = pluginsApiImpl.get(plugin.model.id);
return apiImpl;
}
if (!defaultApi) {
console.warn(`Could not identify plugin for 'Theia' require call from ${parent.filename}`);
defaultApi = createVSCodeAPI(pluginApiFactory, emptyPlugin);
}
return defaultApi;
};
}
function findPlugin(filePath: string): Plugin | undefined {
return plugins.find(plugin => filePath.startsWith(plugin.pluginFolder));
}

View File

@@ -0,0 +1,101 @@
// *****************************************************************************
// Copyright (C) 2023 STMicroelectronics and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import * as decompress from 'decompress';
import * as path from 'path';
import * as filenamify from 'filenamify';
import { FileUri } from '@theia/core/lib/node';
import * as fs from '@theia/core/shared/fs-extra';
import { PluginVSCodeEnvironment } from '../common/plugin-vscode-environment';
export async function decompressExtension(sourcePath: string, destPath: string): Promise<boolean> {
try {
await decompress(sourcePath, destPath);
if (sourcePath.endsWith('.tgz')) {
// unzip node_modules from built-in extensions, see https://github.com/eclipse-theia/theia/issues/5756
const extensionPath = path.join(destPath, 'package');
const vscodeNodeModulesPath = path.join(extensionPath, 'vscode_node_modules.zip');
if (await fs.pathExists(vscodeNodeModulesPath)) {
await decompress(vscodeNodeModulesPath, path.join(extensionPath, 'node_modules'));
}
}
return true;
} catch (error) {
console.error(`Failed to decompress ${sourcePath} to ${destPath}: ${error}`);
throw error;
}
}
export async function existsInDeploymentDir(env: PluginVSCodeEnvironment, extensionId: string): Promise<boolean> {
return fs.pathExists(await getExtensionDeploymentDir(env, extensionId));
}
export const TMP_DIR_PREFIX = 'tmp-vscode-unpacked-';
export async function unpackToDeploymentDir(env: PluginVSCodeEnvironment, sourcePath: string, extensionId: string): Promise<string> {
const extensionDeploymentDir = await getExtensionDeploymentDir(env, extensionId);
if (await fs.pathExists(extensionDeploymentDir)) {
console.log(`[${extensionId}]: deployment dir "${extensionDeploymentDir}" already exists`);
return extensionDeploymentDir;
}
const tempDir = await getTempDir(env, TMP_DIR_PREFIX);
try {
console.log(`[${extensionId}]: trying to decompress "${sourcePath}" into "${tempDir}"...`);
if (!await decompressExtension(sourcePath, tempDir)) {
await fs.remove(tempDir);
const msg = `[${extensionId}]: decompressing "${sourcePath}" to "${tempDir}" failed`;
console.error(msg);
throw new Error(msg);
}
} catch (e) {
await fs.remove(tempDir);
const msg = `[${extensionId}]: error while decompressing "${sourcePath}" to "${tempDir}"`;
console.error(msg, e);
throw e;
}
console.log(`[${extensionId}]: decompressed to temp dir "${tempDir}"`);
try {
console.log(`[${extensionId}]: renaming to extension dir "${extensionDeploymentDir}"...`);
await fs.rename(tempDir, extensionDeploymentDir);
return extensionDeploymentDir;
} catch (e) {
await fs.remove(tempDir);
console.error(`[${extensionId}]: error while renaming "${tempDir}" to "${extensionDeploymentDir}"`, e);
throw e;
}
}
export async function getExtensionDeploymentDir(env: PluginVSCodeEnvironment, extensionId: string): Promise<string> {
const deployedPluginsDirUri = await env.getDeploymentDirUri();
const normalizedExtensionId = filenamify(extensionId, { replacement: '_' });
const extensionDeploymentDirPath = FileUri.fsPath(deployedPluginsDirUri.resolve(normalizedExtensionId));
return extensionDeploymentDirPath;
}
export async function getTempDir(env: PluginVSCodeEnvironment, prefix: string): Promise<string> {
const deploymentDirPath = FileUri.fsPath(await env.getDeploymentDirUri());
try {
if (!await fs.pathExists(deploymentDirPath)) {
console.log(`Creating deployment dir ${deploymentDirPath}`);
await fs.mkdirs(deploymentDirPath);
}
return await fs.mkdtemp(path.join(deploymentDirPath, prefix));
} catch (error) {
console.error(`Failed to create deployment dir ${deploymentDirPath}: ${error}`);
throw error;
}
}

View File

@@ -0,0 +1,113 @@
// *****************************************************************************
// Copyright (C) 2015-2021 Red Hat, Inc.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import * as path from 'path';
import { injectable } from '@theia/core/shared/inversify';
import { PluginScanner, PluginEngine, PluginPackage, PluginModel, PluginLifecycle, PluginEntryPoint, buildFrontendModuleName, UIKind, PluginIdentifiers } from '@theia/plugin-ext';
import { TheiaPluginScanner } from '@theia/plugin-ext/lib/hosted/node/scanners/scanner-theia';
import { environment } from '@theia/core/shared/@theia/application-package/lib/environment';
import { VSCodeExtensionUri } from '../common/plugin-vscode-uri';
const uiKind = environment.electron.is() ? UIKind.Desktop : UIKind.Web;
@injectable()
export class VsCodePluginScanner extends TheiaPluginScanner implements PluginScanner {
private readonly VSCODE_TYPE: PluginEngine = 'vscode';
override get apiType(): PluginEngine {
return this.VSCODE_TYPE;
}
override getModel(plugin: PluginPackage): PluginModel {
// publisher can be empty on vscode extension development
const publisher = plugin.publisher ?? PluginIdentifiers.UNPUBLISHED;
// Only one entrypoint is valid in vscode extensions
// Mimic choosing frontend (web extension) and backend (local/remote extension) as described here:
// https://code.visualstudio.com/api/advanced-topics/extension-host#preferred-extension-location
const entryPoint: PluginEntryPoint = {};
// Act like codespaces when run in the browser (UIKind === 'web' and extensionKind is ['ui'])
const preferFrontend = uiKind === UIKind.Web && (plugin.extensionKind?.length === 1 && plugin.extensionKind[0] === 'ui');
if (plugin.browser && (!plugin.main || preferFrontend)) {
// Use frontend if available and there is no backend or frontend is preferred
entryPoint.frontend = plugin.browser;
} else {
// Default to using backend
entryPoint.backend = plugin.main;
}
if (plugin.theiaPlugin?.headless) {
// Support the Theia-specific extension for headless plugins
entryPoint.headless = plugin.theiaPlugin?.headless;
}
const result: PluginModel = {
packagePath: plugin.packagePath,
packageUri: this.pluginUriFactory.createUri(plugin).toString(),
// see id definition: https://github.com/microsoft/vscode/blob/15916055fe0cb9411a5f36119b3b012458fe0a1d/src/vs/platform/extensions/common/extensions.ts#L167-L169
id: `${publisher.toLowerCase()}.${plugin.name.toLowerCase()}`,
name: plugin.name,
publisher: publisher,
version: plugin.version,
displayName: plugin.displayName,
description: plugin.description,
engine: {
type: this.VSCODE_TYPE,
version: plugin.engines[this.VSCODE_TYPE]
},
entryPoint,
iconUrl: plugin.icon && PluginPackage.toPluginUrl(plugin, plugin.icon),
l10n: plugin.l10n,
readmeUrl: this.getReadmeUrl(plugin),
licenseUrl: this.getLicenseUrl(plugin)
};
return result;
}
/**
* Maps extension dependencies to deployable extension dependencies.
*/
override getDependencies(plugin: PluginPackage): Map<string, string> | undefined {
// Store the list of dependencies.
const dependencies = new Map<string, string>();
// Iterate through the list of dependencies from `extensionDependencies` and `extensionPack`.
for (const dependency of [plugin.extensionDependencies, plugin.extensionPack]) {
if (dependency !== undefined) {
// Iterate over the list of dependencies present, and add them to the collection.
dependency.forEach((dep: string) => {
const dependencyId = dep.toLowerCase();
dependencies.set(dependencyId, VSCodeExtensionUri.fromId(dependencyId).toString());
});
}
}
// Return the map of dependencies if present, else `undefined`.
return dependencies.size > 0 ? dependencies : undefined;
}
override getLifecycle(plugin: PluginPackage): PluginLifecycle {
return {
startMethod: 'activate',
stopMethod: 'deactivate',
frontendModuleName: buildFrontendModuleName(plugin),
frontendInitPath: 'plugin-vscode-init-fe.js',
backendInitPath: path.join(__dirname, 'plugin-vscode-init'),
};
}
}

View File

@@ -0,0 +1,60 @@
{
"extends": "../../configs/base.tsconfig",
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "lib",
"lib": [
"es6",
"dom",
"webworker"
]
},
"include": [
"src"
],
"references": [
{
"path": "../callhierarchy"
},
{
"path": "../core"
},
{
"path": "../editor"
},
{
"path": "../filesystem"
},
{
"path": "../monaco"
},
{
"path": "../navigator"
},
{
"path": "../outline-view"
},
{
"path": "../plugin"
},
{
"path": "../plugin-ext"
},
{
"path": "../scm"
},
{
"path": "../terminal"
},
{
"path": "../typehierarchy"
},
{
"path": "../userstorage"
},
{
"path": "../workspace"
}
]
}