deploy: current vibn theia state
Made-with: Cursor
This commit is contained in:
10
packages/variable-resolver/.eslintrc.js
Normal file
10
packages/variable-resolver/.eslintrc.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: [
|
||||
'../../configs/build.eslintrc.json'
|
||||
],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: 'tsconfig.json'
|
||||
}
|
||||
};
|
||||
110
packages/variable-resolver/README.md
Normal file
110
packages/variable-resolver/README.md
Normal file
@@ -0,0 +1,110 @@
|
||||
<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 - VARIABLE-RESOLVER EXTENSION</h2>
|
||||
|
||||
<hr />
|
||||
|
||||
</div>
|
||||
|
||||
## Description
|
||||
|
||||
The `@theia/variable-resolved` extension provides variable substitution mechanism inside of strings using `${variableName}` syntax.
|
||||
|
||||
### Variable Contribution Point
|
||||
|
||||
Extension provides a hook that allows any extensions to contribute its own variables.
|
||||
Here's the example of contributing two variables:
|
||||
|
||||
- `${file}` - returns the name of the file opened in the current editor
|
||||
- `${lineNumber}` - returns the current line number in the current file
|
||||
|
||||
```typescript
|
||||
@injectable()
|
||||
export class EditorVariableContribution implements VariableContribution {
|
||||
|
||||
constructor(
|
||||
@inject(EditorManager) protected readonly editorManager: EditorManager
|
||||
) { }
|
||||
|
||||
registerVariables(variables: VariableRegistry): void {
|
||||
variables.registerVariable({
|
||||
name: 'file',
|
||||
description: 'The name of the file opened in the current editor',
|
||||
resolve: () => {
|
||||
const currentEditor = this.getCurrentEditor();
|
||||
if (currentEditor) {
|
||||
return currentEditor.uri.displayName;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'lineNumber',
|
||||
description: 'The current line number in the current file',
|
||||
resolve: () => {
|
||||
const currentEditor = this.getCurrentEditor();
|
||||
if (currentEditor) {
|
||||
return `${currentEditor.cursor.line + 1}`;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected getCurrentEditor(): TextEditor | undefined {
|
||||
const currentEditor = this.editorManager.currentEditor;
|
||||
if (currentEditor) {
|
||||
return currentEditor.editor;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that a Variable is resolved to `MaybePromise<string | undefined>` which means that it can be resolved synchronously or within a Promise.
|
||||
|
||||
### Using the Variable Resolver Service
|
||||
|
||||
There's the example of how one can use Variable Resolver Service in its own plugin:
|
||||
|
||||
```typescript
|
||||
@injectable()
|
||||
export class MyService {
|
||||
|
||||
constructor(
|
||||
@inject(VariableResolverService) protected readonly variableResolver: VariableResolverService
|
||||
) { }
|
||||
|
||||
async resolve(): Promise<void> {
|
||||
const text = 'cursor is in file ${file} on line ${lineNumber}';
|
||||
const resolved = await this.variableResolver.resolve(text);
|
||||
console.log(resolved);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If `package.json` file is currently opened and cursor is on line 5 then the following output will be logged to the console:
|
||||
|
||||
```sh
|
||||
cursor is in file package.json on line 5
|
||||
```
|
||||
|
||||
## Additional Information
|
||||
|
||||
- [API documentation for `@theia/variable-resolver`](https://eclipse-theia.github.io/theia/docs/next/modules/_theia_variable-resolver.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>
|
||||
54
packages/variable-resolver/package.json
Normal file
54
packages/variable-resolver/package.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "@theia/variable-resolver",
|
||||
"version": "1.68.0",
|
||||
"description": "Theia - Variable Resolver Extension",
|
||||
"dependencies": {
|
||||
"@theia/core": "1.68.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"theiaExtensions": [
|
||||
{
|
||||
"frontend": "lib/browser/variable-resolver-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",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Artem Zatsarynnyi",
|
||||
"email": "azatsary@redhat.com"
|
||||
}
|
||||
],
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// *****************************************************************************
|
||||
// Copyright (C) 2019 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, optional } from '@theia/core/shared/inversify';
|
||||
import { VariableContribution, VariableRegistry } from './variable';
|
||||
import { ApplicationServer } from '@theia/core/lib/common/application-protocol';
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { CommandService } from '@theia/core/lib/common/command';
|
||||
import { OS } from '@theia/core/lib/common/os';
|
||||
import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
|
||||
import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
|
||||
import { VariableInput } from './variable-input';
|
||||
import { QuickInputService, QuickPickValue } from '@theia/core/lib/browser';
|
||||
import { MaybeArray, RecursivePartial } from '@theia/core/lib/common/types';
|
||||
import { cancelled } from '@theia/core/lib/common/cancellation';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
|
||||
@injectable()
|
||||
export class CommonVariableContribution implements VariableContribution {
|
||||
|
||||
@inject(EnvVariablesServer)
|
||||
protected readonly env: EnvVariablesServer;
|
||||
|
||||
@inject(CommandService)
|
||||
protected readonly commands: CommandService;
|
||||
|
||||
@inject(PreferenceService)
|
||||
protected readonly preferences: PreferenceService;
|
||||
|
||||
@inject(ResourceContextKey)
|
||||
protected readonly resourceContextKey: ResourceContextKey;
|
||||
|
||||
@inject(QuickInputService) @optional()
|
||||
protected readonly quickInputService: QuickInputService;
|
||||
|
||||
@inject(ApplicationServer)
|
||||
protected readonly appServer: ApplicationServer;
|
||||
|
||||
async registerVariables(variables: VariableRegistry): Promise<void> {
|
||||
const execPath = await this.env.getExecPath();
|
||||
variables.registerVariable({
|
||||
name: 'execPath',
|
||||
resolve: () => execPath
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'pathSeparator',
|
||||
resolve: () => OS.backend.isWindows ? '\\' : '/'
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'env',
|
||||
resolve: async (_, envVariableName) => {
|
||||
const envVariable = envVariableName && await this.env.getValue(envVariableName);
|
||||
const envValue = envVariable && envVariable.value;
|
||||
return envValue || '';
|
||||
}
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'config',
|
||||
resolve: (resourceUri = new URI(this.resourceContextKey.get()), preferenceName) => {
|
||||
if (!preferenceName) {
|
||||
return undefined;
|
||||
}
|
||||
return this.preferences.get(preferenceName, undefined, resourceUri && resourceUri.toString());
|
||||
}
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'command',
|
||||
resolve: async (contextUri, commandId, configurationSection, commandIdVariables, configuration) => {
|
||||
if (commandId) {
|
||||
if (commandIdVariables?.[commandId]) {
|
||||
commandId = commandIdVariables[commandId];
|
||||
}
|
||||
const result = await this.commands.executeCommand(commandId, configuration);
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
if (result === null) {
|
||||
throw cancelled();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'input',
|
||||
resolve: async (resourceUri = new URI(this.resourceContextKey.get()), variable, section) => {
|
||||
if (!variable || !section) {
|
||||
return undefined;
|
||||
}
|
||||
const configuration = this.preferences.get<RecursivePartial<{ inputs: MaybeArray<VariableInput> }>>(section, undefined, resourceUri && resourceUri.toString());
|
||||
const inputs = !!configuration && 'inputs' in configuration ? configuration.inputs : undefined;
|
||||
const input = Array.isArray(inputs) && inputs.find(item => !!item && item.id === variable);
|
||||
if (!input) {
|
||||
return undefined;
|
||||
}
|
||||
if (input.type === 'promptString') {
|
||||
if (typeof input.description !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
return this.quickInputService?.input({
|
||||
prompt: input.description,
|
||||
value: input.default
|
||||
});
|
||||
}
|
||||
if (input.type === 'pickString') {
|
||||
if (typeof input.description !== 'string' || !Array.isArray(input.options)) {
|
||||
return undefined;
|
||||
}
|
||||
const elements: Array<QuickPickValue<string>> = [];
|
||||
for (const option of input.options) {
|
||||
if (typeof option !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
if (option === input.default) {
|
||||
elements.unshift({
|
||||
description: 'Default',
|
||||
label: option,
|
||||
value: option
|
||||
});
|
||||
} else {
|
||||
elements.push({
|
||||
label: option,
|
||||
value: option
|
||||
});
|
||||
}
|
||||
}
|
||||
const selectedPick = await this.quickInputService?.showQuickPick(elements, { placeholder: input.description });
|
||||
return selectedPick?.value;
|
||||
}
|
||||
if (input.type === 'command') {
|
||||
if (typeof input.command !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
return this.commands.executeCommand(input.command, input.args);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
19
packages/variable-resolver/src/browser/index.ts
Normal file
19
packages/variable-resolver/src/browser/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// *****************************************************************************
|
||||
// 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
|
||||
// *****************************************************************************
|
||||
|
||||
export * from './variable';
|
||||
export * from './variable-quick-open-service';
|
||||
export * from './variable-resolver-service';
|
||||
131
packages/variable-resolver/src/browser/variable-input-schema.ts
Normal file
131
packages/variable-resolver/src/browser/variable-input-schema.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
// *****************************************************************************
|
||||
// Copyright (C) 2019 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
|
||||
// *****************************************************************************
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
* copied from
|
||||
* https://github.com/microsoft/vscode/blob/0a34756cae4fc67739e60c708b04637089f8bb0d/src/vs/workbench/services/configurationResolver/common/configurationResolverSchema.ts#L23
|
||||
*/
|
||||
|
||||
const idDescription = "The input's id is used to associate an input with a variable of the form ${input:id}.";
|
||||
const typeDescription = 'The type of user input prompt to use.';
|
||||
const descriptionDescription = 'The description is shown when the user is prompted for input.';
|
||||
const defaultDescription = 'The default value for the input.';
|
||||
|
||||
import { IJSONSchema } from '@theia/core/lib/common/json-schema';
|
||||
|
||||
export const inputsSchema: IJSONSchema = {
|
||||
definitions: {
|
||||
inputs: {
|
||||
type: 'array',
|
||||
description: 'User inputs. Used for defining user input prompts, such as free string input or a choice from several options.',
|
||||
items: {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'object',
|
||||
required: ['id', 'type', 'description'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: idDescription
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description: typeDescription,
|
||||
enum: ['promptString'],
|
||||
enumDescriptions: [
|
||||
"The 'promptString' type opens an input box to ask the user for input."
|
||||
]
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: descriptionDescription
|
||||
},
|
||||
default: {
|
||||
type: 'string',
|
||||
description: defaultDescription
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
required: ['id', 'type', 'description', 'options'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: idDescription
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description: typeDescription,
|
||||
enum: ['pickString'],
|
||||
enumDescriptions: [
|
||||
"The 'pickString' type shows a selection list.",
|
||||
]
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: descriptionDescription
|
||||
},
|
||||
default: {
|
||||
type: 'string',
|
||||
description: defaultDescription
|
||||
},
|
||||
options: {
|
||||
type: 'array',
|
||||
description: 'An array of strings that defines the options for a quick pick.',
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
required: ['id', 'type', 'command'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: idDescription
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description: typeDescription,
|
||||
enum: ['command'],
|
||||
enumDescriptions: [
|
||||
"The 'command' type executes a command.",
|
||||
]
|
||||
},
|
||||
command: {
|
||||
type: 'string',
|
||||
description: 'The command to execute for this input variable.'
|
||||
},
|
||||
args: {
|
||||
type: 'object',
|
||||
description: 'Optional arguments passed to the command.'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
47
packages/variable-resolver/src/browser/variable-input.ts
Normal file
47
packages/variable-resolver/src/browser/variable-input.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// *****************************************************************************
|
||||
// Copyright (C) 2019 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
|
||||
// *****************************************************************************
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
* copied from
|
||||
* https://github.com/microsoft/vscode/blob/0a34756cae4fc67739e60c708b04637089f8bb0d/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts#L41-L63
|
||||
*/
|
||||
export interface VariablePromptStringInput {
|
||||
id: string;
|
||||
type: 'promptString';
|
||||
description: string;
|
||||
default?: string;
|
||||
}
|
||||
|
||||
export interface VariablePickStringInput {
|
||||
id: string;
|
||||
type: 'pickString';
|
||||
description: string;
|
||||
options: string[];
|
||||
default?: string;
|
||||
}
|
||||
|
||||
export interface VariableCommandInput {
|
||||
id: string;
|
||||
type: 'command';
|
||||
command: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args?: any;
|
||||
}
|
||||
|
||||
export type VariableInput = VariablePromptStringInput | VariablePickStringInput | VariableCommandInput;
|
||||
@@ -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 { inject, injectable, optional } from '@theia/core/shared/inversify';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { VariableRegistry, Variable } from './variable';
|
||||
import { VariableResolverService } from './variable-resolver-service';
|
||||
import { QuickPickItem, QuickInputService } from '@theia/core/lib/browser';
|
||||
|
||||
@injectable()
|
||||
export class VariableQuickOpenService {
|
||||
|
||||
protected items: Array<QuickPickItem>;
|
||||
|
||||
@inject(MessageService)
|
||||
protected readonly messages: MessageService;
|
||||
|
||||
@inject(QuickInputService) @optional()
|
||||
protected readonly quickInputService: QuickInputService;
|
||||
|
||||
@inject(VariableResolverService)
|
||||
protected readonly variableResolver: VariableResolverService;
|
||||
|
||||
constructor(
|
||||
@inject(VariableRegistry) protected readonly variableRegistry: VariableRegistry
|
||||
) { }
|
||||
|
||||
open(): void {
|
||||
this.items = this.variableRegistry.getVariables().map(v => ({
|
||||
label: '${' + v.name + '}',
|
||||
detail: v.description,
|
||||
execute: () => {
|
||||
setTimeout(() => this.showValue(v));
|
||||
}
|
||||
}));
|
||||
|
||||
this.quickInputService?.showQuickPick(this.items, { placeholder: 'Registered variables' });
|
||||
}
|
||||
|
||||
protected async showValue(variable: Variable): Promise<void> {
|
||||
const argument = await this.quickInputService?.input({
|
||||
placeHolder: 'Type a variable argument'
|
||||
});
|
||||
const value = await this.variableResolver.resolve('${' + variable.name + ':' + argument + '}');
|
||||
if (typeof value === 'string') {
|
||||
this.messages.info(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// *****************************************************************************
|
||||
// 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 { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
|
||||
|
||||
let disableJSDOM = enableJSDOM();
|
||||
|
||||
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
||||
FrontendApplicationConfigProvider.set({});
|
||||
|
||||
import * as chai from 'chai';
|
||||
import { Container, ContainerModule } from '@theia/core/shared/inversify';
|
||||
import { ILogger, bindContributionProvider } from '@theia/core/lib/common';
|
||||
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
||||
import { VariableContribution, VariableRegistry } from './variable';
|
||||
import { VariableQuickOpenService } from './variable-quick-open-service';
|
||||
import { VariableResolverFrontendContribution } from './variable-resolver-frontend-contribution';
|
||||
|
||||
disableJSDOM();
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
before(() => {
|
||||
chai.config.showDiff = true;
|
||||
chai.config.includeStack = true;
|
||||
});
|
||||
|
||||
describe('variable-resolver-frontend-contribution', () => {
|
||||
|
||||
let testContainer: Container;
|
||||
let variableRegistry: VariableRegistry;
|
||||
|
||||
before(() => {
|
||||
disableJSDOM = enableJSDOM();
|
||||
|
||||
testContainer = new Container();
|
||||
const module = new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bindContributionProvider(bind, VariableContribution);
|
||||
bind(VariableContribution).toConstantValue(new TestVariableContribution());
|
||||
|
||||
bind(ILogger).to(MockLogger);
|
||||
bind(VariableRegistry).toSelf().inSingletonScope();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
bind(VariableQuickOpenService).toConstantValue({} as any); // mock VariableQuickOpenService
|
||||
|
||||
bind(VariableResolverFrontendContribution).toSelf();
|
||||
});
|
||||
testContainer.load(module);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
disableJSDOM();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
variableRegistry = testContainer.get<VariableRegistry>(VariableRegistry);
|
||||
|
||||
const variableRegistrar = testContainer.get(VariableResolverFrontendContribution);
|
||||
variableRegistrar.onStart();
|
||||
});
|
||||
|
||||
it('should register all variables from the contribution points', () => {
|
||||
const variables = variableRegistry.getVariables();
|
||||
expect(variables.length).to.be.equal(2);
|
||||
expect(variables[0].name).to.be.equal('file');
|
||||
expect(variables[1].name).to.be.equal('lineNumber');
|
||||
});
|
||||
});
|
||||
|
||||
export class TestVariableContribution implements VariableContribution {
|
||||
|
||||
registerVariables(variables: VariableRegistry): void {
|
||||
variables.registerVariable({
|
||||
name: 'file',
|
||||
description: 'Resolves to file name opened in the current editor',
|
||||
resolve: () => Promise.resolve('package.json')
|
||||
});
|
||||
variables.registerVariable({
|
||||
name: 'lineNumber',
|
||||
description: 'Resolves to current line number',
|
||||
resolve: () => Promise.resolve('5')
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// *****************************************************************************
|
||||
// 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 { injectable, inject, named } from '@theia/core/shared/inversify';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
|
||||
import { Command, CommandContribution, CommandRegistry, ContributionProvider } from '@theia/core/lib/common';
|
||||
import { VariableContribution, VariableRegistry } from './variable';
|
||||
import { VariableQuickOpenService } from './variable-quick-open-service';
|
||||
|
||||
export const LIST_VARIABLES: Command = Command.toLocalizedCommand({
|
||||
id: 'variable.list',
|
||||
label: 'Variable: List All'
|
||||
}, 'theia/variableResolver/listAllVariables');
|
||||
|
||||
@injectable()
|
||||
export class VariableResolverFrontendContribution implements FrontendApplicationContribution, CommandContribution {
|
||||
|
||||
constructor(
|
||||
@inject(ContributionProvider) @named(VariableContribution)
|
||||
protected readonly contributionProvider: ContributionProvider<VariableContribution>,
|
||||
@inject(VariableRegistry) protected readonly variableRegistry: VariableRegistry,
|
||||
@inject(VariableQuickOpenService) protected readonly variableQuickOpenService: VariableQuickOpenService
|
||||
) { }
|
||||
|
||||
onStart(): void {
|
||||
this.contributionProvider.getContributions().forEach(contrib =>
|
||||
contrib.registerVariables(this.variableRegistry)
|
||||
);
|
||||
}
|
||||
|
||||
registerCommands(commands: CommandRegistry): void {
|
||||
commands.registerCommand(LIST_VARIABLES, {
|
||||
isEnabled: () => true,
|
||||
execute: () => this.variableQuickOpenService.open()
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// *****************************************************************************
|
||||
// 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 { bindContributionProvider, CommandContribution } from '@theia/core';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
|
||||
import { VariableRegistry, VariableContribution } from './variable';
|
||||
import { VariableQuickOpenService } from './variable-quick-open-service';
|
||||
import { VariableResolverFrontendContribution } from './variable-resolver-frontend-contribution';
|
||||
import { VariableResolverService } from './variable-resolver-service';
|
||||
import { CommonVariableContribution } from './common-variable-contribution';
|
||||
|
||||
export default new ContainerModule(bind => {
|
||||
bind(VariableRegistry).toSelf().inSingletonScope();
|
||||
bind(VariableResolverService).toSelf().inSingletonScope();
|
||||
bindContributionProvider(bind, VariableContribution);
|
||||
|
||||
bind(VariableResolverFrontendContribution).toSelf().inSingletonScope();
|
||||
for (const identifier of [FrontendApplicationContribution, CommandContribution]) {
|
||||
bind(identifier).toService(VariableResolverFrontendContribution);
|
||||
}
|
||||
|
||||
bind(VariableQuickOpenService).toSelf().inSingletonScope();
|
||||
|
||||
bind(CommonVariableContribution).toSelf().inSingletonScope();
|
||||
bind(VariableContribution).toService(CommonVariableContribution);
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
// *****************************************************************************
|
||||
// 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 chai from 'chai';
|
||||
import { Container } from '@theia/core/shared/inversify';
|
||||
import { cancelled } from '@theia/core/lib/common';
|
||||
import { VariableRegistry } from './variable';
|
||||
import { VariableResolverService } from './variable-resolver-service';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
before(() => {
|
||||
chai.config.showDiff = true;
|
||||
chai.config.includeStack = true;
|
||||
});
|
||||
|
||||
describe('variable-resolver-service', () => {
|
||||
|
||||
let testContainer: Container;
|
||||
let variableRegistry: VariableRegistry;
|
||||
let variableResolverService: VariableResolverService;
|
||||
|
||||
beforeEach(() => {
|
||||
testContainer = new Container();
|
||||
testContainer.bind(VariableRegistry).toSelf().inSingletonScope();
|
||||
testContainer.bind(VariableResolverService).toSelf().inSingletonScope();
|
||||
variableRegistry = testContainer.get(VariableRegistry);
|
||||
variableRegistry.registerVariable({
|
||||
name: 'file',
|
||||
description: 'current file',
|
||||
resolve: () => Promise.resolve('package.json')
|
||||
});
|
||||
variableRegistry.registerVariable({
|
||||
name: 'lineNumber',
|
||||
description: 'current line number',
|
||||
resolve: () => Promise.resolve('6')
|
||||
});
|
||||
variableResolverService = testContainer.get(VariableResolverService);
|
||||
});
|
||||
|
||||
it('should resolve known variables in a text', async () => {
|
||||
const resolved = await variableResolverService.resolve('file: ${file}; line: ${lineNumber}');
|
||||
expect(resolved).is.equal('file: package.json; line: 6');
|
||||
});
|
||||
|
||||
it('should resolve known variables in a string array', async () => {
|
||||
const resolved = await variableResolverService.resolveArray(['file: ${file}', 'line: ${lineNumber}']);
|
||||
expect(resolved!.length).to.be.equal(2);
|
||||
expect(resolved).to.contain('file: package.json');
|
||||
expect(resolved).to.contain('line: 6');
|
||||
});
|
||||
|
||||
it('should skip unknown variables', async () => {
|
||||
const resolved = await variableResolverService.resolve('workspace: ${workspaceRoot}; file: ${file}; line: ${lineNumber}');
|
||||
expect(resolved).is.equal('workspace: ${workspaceRoot}; file: package.json; line: 6');
|
||||
});
|
||||
|
||||
it('should return undefined when a variable throws with `cancelled()` while resolving', async () => {
|
||||
variableRegistry.registerVariable({
|
||||
name: 'command',
|
||||
resolve: (contextUri, commandId) => {
|
||||
if (commandId === 'testCommand') {
|
||||
throw cancelled();
|
||||
}
|
||||
}
|
||||
});
|
||||
const resolved = await variableResolverService.resolve('workspace: ${command:testCommand}; file: ${file}; line: ${lineNumber}');
|
||||
expect(resolved).equal(undefined);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,185 @@
|
||||
// *****************************************************************************
|
||||
// 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
|
||||
// *****************************************************************************
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
import { VariableRegistry } from './variable';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { CommandIdVariables } from '../common/variable-types';
|
||||
import { isCancelled } from '@theia/core';
|
||||
|
||||
export interface VariableResolveOptions {
|
||||
context?: URI;
|
||||
/**
|
||||
* Used for resolving inputs, see https://code.visualstudio.com/docs/editor/variables-reference#_input-variables
|
||||
*/
|
||||
configurationSection?: string;
|
||||
commandIdVariables?: CommandIdVariables;
|
||||
configuration?: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* The variable resolver service should be used to resolve variables in strings.
|
||||
*/
|
||||
@injectable()
|
||||
export class VariableResolverService {
|
||||
|
||||
protected static VAR_REGEXP = /\$\{(.*?)\}/g;
|
||||
|
||||
@inject(VariableRegistry) protected readonly variableRegistry: VariableRegistry;
|
||||
|
||||
/**
|
||||
* Resolve the variables in the given string array.
|
||||
* @param value The array of data to resolve variables in.
|
||||
* @param options Options of the variable resolution.
|
||||
* @returns Promise to array with variables resolved. Never rejects.
|
||||
*
|
||||
* @deprecated since 1.28.0 use {@link resolve} instead.
|
||||
*/
|
||||
resolveArray(value: string[], options: VariableResolveOptions = {}): Promise<string[] | undefined> {
|
||||
return this.resolve(value, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the variables for all strings found in the object and nested objects.
|
||||
* @param value Data to resolve variables in.
|
||||
* @param options Options of the variable resolution
|
||||
* @returns Promise to object with variables resolved. Returns `undefined` if a variable resolution was cancelled.
|
||||
*/
|
||||
async resolve<T>(value: T, options: VariableResolveOptions = {}): Promise<T | undefined> {
|
||||
const context = new VariableResolverService.Context(this.variableRegistry, options);
|
||||
try {
|
||||
return await this.doResolve(value, context);
|
||||
} catch (error) {
|
||||
if (isCancelled(error)) {
|
||||
return undefined;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
protected async doResolve(value: any, context: VariableResolverService.Context): Promise<any> {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
if (value === undefined || value === null) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return this.doResolveString(value, context);
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return this.doResolveArray(value, context);
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return this.doResolveObject(value, context);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected async doResolveObject(obj: object, context: VariableResolverService.Context): Promise<object> {
|
||||
const result: {
|
||||
[prop: string]: Object | undefined
|
||||
} = {};
|
||||
for (const name of Object.keys(obj)) {
|
||||
const value = (obj as any)[name];
|
||||
const resolved = await this.doResolve(value, context);
|
||||
result[name] = resolved;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async doResolveArray(values: Array<Object | undefined>, context: VariableResolverService.Context): Promise<Array<Object | undefined>> {
|
||||
const result: (Object | undefined)[] = [];
|
||||
for (const value of values) {
|
||||
const resolved = await this.doResolve(value, context);
|
||||
result.push(resolved);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async doResolveString(value: string, context: VariableResolverService.Context): Promise<string> {
|
||||
await this.resolveVariables(value, context);
|
||||
return value.replace(VariableResolverService.VAR_REGEXP, (match: string, varName: string) => {
|
||||
const varValue = context.get(varName);
|
||||
return varValue !== undefined ? varValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
protected async resolveVariables(value: string, context: VariableResolverService.Context): Promise<void> {
|
||||
const variableRegExp = new RegExp(VariableResolverService.VAR_REGEXP);
|
||||
let match;
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
while ((match = variableRegExp.exec(value)) !== null) {
|
||||
const variableName = match[1];
|
||||
await context.resolve(variableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
export namespace VariableResolverService {
|
||||
|
||||
export class Context {
|
||||
|
||||
protected readonly resolved = new Map<string, string | undefined>();
|
||||
|
||||
constructor(
|
||||
protected readonly variableRegistry: VariableRegistry,
|
||||
protected readonly options: VariableResolveOptions
|
||||
) { }
|
||||
|
||||
get(name: string): string | undefined {
|
||||
return this.resolved.get(name);
|
||||
}
|
||||
|
||||
async resolve(name: string): Promise<void> {
|
||||
if (this.resolved.has(name)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let variableName = name;
|
||||
let argument: string | undefined;
|
||||
const parts = name.split(':', 2);
|
||||
if (parts.length > 1) {
|
||||
variableName = parts[0];
|
||||
argument = parts[1];
|
||||
}
|
||||
const variable = this.variableRegistry.getVariable(variableName);
|
||||
const resolved = await variable?.resolve(
|
||||
this.options.context,
|
||||
argument,
|
||||
this.options.configurationSection,
|
||||
this.options.commandIdVariables,
|
||||
this.options.configuration
|
||||
);
|
||||
if (
|
||||
typeof resolved === 'bigint' ||
|
||||
typeof resolved === 'boolean' ||
|
||||
typeof resolved === 'number' ||
|
||||
typeof resolved === 'string'
|
||||
) {
|
||||
this.resolved.set(name, `${resolved}`);
|
||||
} else {
|
||||
this.resolved.set(name, undefined);
|
||||
}
|
||||
} catch (e) {
|
||||
if (isCancelled(e)) {
|
||||
throw e;
|
||||
}
|
||||
this.resolved.set(name, undefined);
|
||||
console.error(`Failed to resolve '${name}' variable:`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
packages/variable-resolver/src/browser/variable.spec.ts
Normal file
106
packages/variable-resolver/src/browser/variable.spec.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
// *****************************************************************************
|
||||
// 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 chai from 'chai';
|
||||
import { Container, ContainerModule } from '@theia/core/shared/inversify';
|
||||
import { ILogger, Disposable } from '@theia/core/lib/common';
|
||||
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
||||
import { Variable, VariableRegistry } from './variable';
|
||||
|
||||
const expect = chai.expect;
|
||||
let variableRegistry: VariableRegistry;
|
||||
|
||||
before(() => {
|
||||
chai.config.showDiff = true;
|
||||
chai.config.includeStack = true;
|
||||
});
|
||||
|
||||
describe('variable api', () => {
|
||||
let testContainer: Container;
|
||||
|
||||
before(() => {
|
||||
testContainer = new Container();
|
||||
const module = new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(ILogger).to(MockLogger);
|
||||
bind(VariableRegistry).toSelf();
|
||||
});
|
||||
testContainer.load(module);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
variableRegistry = testContainer.get<VariableRegistry>(VariableRegistry);
|
||||
});
|
||||
|
||||
it('should register and return variable', () => {
|
||||
registerTestVariable();
|
||||
|
||||
const variable = variableRegistry.getVariable(TEST_VARIABLE.name);
|
||||
expect(variable).is.not.undefined;
|
||||
if (variable) {
|
||||
expect(variable.name).is.equal(TEST_VARIABLE.name);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not register a variable for already existed name', () => {
|
||||
const variables: Variable[] = [
|
||||
{
|
||||
name: 'workspaceRoot',
|
||||
description: 'workspace root URI',
|
||||
resolve: () => Promise.resolve('')
|
||||
},
|
||||
{
|
||||
name: 'workspaceRoot',
|
||||
description: 'workspace root URI 2',
|
||||
resolve: () => Promise.resolve('')
|
||||
}
|
||||
];
|
||||
variables.forEach(v => variableRegistry.registerVariable(v));
|
||||
|
||||
const registeredVariables = variableRegistry.getVariables();
|
||||
expect(registeredVariables.length).to.be.equal(1);
|
||||
expect(registeredVariables[0].name).to.be.equal('workspaceRoot');
|
||||
expect(registeredVariables[0].description).to.be.equal('workspace root URI');
|
||||
});
|
||||
|
||||
it('should dispose variable', () => {
|
||||
const disposable = registerTestVariable();
|
||||
disposable.dispose();
|
||||
|
||||
const variable = variableRegistry.getVariable(TEST_VARIABLE.name);
|
||||
expect(variable).is.undefined;
|
||||
});
|
||||
|
||||
it('should unregister variables on dispose', () => {
|
||||
registerTestVariable();
|
||||
|
||||
let variables = variableRegistry.getVariables();
|
||||
expect(variables.length).to.be.equal(1);
|
||||
|
||||
variableRegistry.dispose();
|
||||
|
||||
variables = variableRegistry.getVariables();
|
||||
expect(variables.length).to.be.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
const TEST_VARIABLE: Variable = {
|
||||
name: 'workspaceRoot',
|
||||
resolve: () => Promise.resolve('')
|
||||
};
|
||||
|
||||
function registerTestVariable(): Disposable {
|
||||
return variableRegistry.registerVariable(TEST_VARIABLE);
|
||||
}
|
||||
111
packages/variable-resolver/src/browser/variable.ts
Normal file
111
packages/variable-resolver/src/browser/variable.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
// *****************************************************************************
|
||||
// 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 { injectable } from '@theia/core/shared/inversify';
|
||||
import { Disposable, DisposableCollection, MaybePromise } from '@theia/core';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { CommandIdVariables } from '../common/variable-types';
|
||||
|
||||
/**
|
||||
* Variable can be used inside of strings using ${variableName} syntax.
|
||||
*/
|
||||
export interface Variable {
|
||||
|
||||
/**
|
||||
* A unique name of this variable.
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* A human-readable description of this variable.
|
||||
*/
|
||||
readonly description?: string;
|
||||
|
||||
/**
|
||||
* Resolve to a string value of this variable or
|
||||
* `undefined` if variable cannot be resolved.
|
||||
* Never reject.
|
||||
*/
|
||||
resolve(
|
||||
context?: URI,
|
||||
argument?: string,
|
||||
configurationSection?: string,
|
||||
commandIdVariables?: CommandIdVariables,
|
||||
configuration?: unknown
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): MaybePromise<any>;
|
||||
}
|
||||
|
||||
export const VariableContribution = Symbol('VariableContribution');
|
||||
/**
|
||||
* The variable contribution should be implemented to register custom variables.
|
||||
*/
|
||||
export interface VariableContribution {
|
||||
registerVariables(variables: VariableRegistry): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* The variable registry manages variables.
|
||||
*/
|
||||
@injectable()
|
||||
export class VariableRegistry implements Disposable {
|
||||
|
||||
protected readonly variables: Map<string, Variable> = new Map();
|
||||
protected readonly toDispose = new DisposableCollection();
|
||||
|
||||
dispose(): void {
|
||||
this.toDispose.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given variable.
|
||||
* Do nothing if a variable is already registered for the given variable name.
|
||||
*/
|
||||
registerVariable(variable: Variable): Disposable {
|
||||
if (this.variables.has(variable.name)) {
|
||||
console.warn(`A variables with name ${variable.name} is already registered.`);
|
||||
return Disposable.NULL;
|
||||
}
|
||||
this.variables.set(variable.name, variable);
|
||||
const disposable = {
|
||||
dispose: () => this.variables.delete(variable.name)
|
||||
};
|
||||
this.toDispose.push(disposable);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered variables.
|
||||
*/
|
||||
getVariables(): Variable[] {
|
||||
return [...this.variables.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a variable for the given name or `undefined` if none.
|
||||
*/
|
||||
getVariable(name: string): Variable | undefined {
|
||||
return this.variables.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an array of variables.
|
||||
* Do nothing if a variable is already registered for the given variable name.
|
||||
*/
|
||||
registerVariables(variables: Variable[]): Disposable[] {
|
||||
return variables.map(v => this.registerVariable(v));
|
||||
}
|
||||
}
|
||||
23
packages/variable-resolver/src/common/variable-types.ts
Normal file
23
packages/variable-resolver/src/common/variable-types.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// *****************************************************************************
|
||||
// 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
|
||||
// *****************************************************************************
|
||||
|
||||
/**
|
||||
* Holds variable-names to command id mappings (e.g. Provided by specific plugins / extensions)
|
||||
* see "variables": https://code.visualstudio.com/api/references/contribution-points#contributes.debuggers
|
||||
*/
|
||||
export interface CommandIdVariables {
|
||||
[id: string]: string
|
||||
}
|
||||
16
packages/variable-resolver/tsconfig.json
Normal file
16
packages/variable-resolver/tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../configs/base.tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../core"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user