Skip to content

Commit

Permalink
Fix remarks
Browse files Browse the repository at this point in the history
Signed-off-by: Anatoliy Bazko <abazko@redhat.com>
  • Loading branch information
tolusha committed Dec 17, 2018
1 parent 3df1645 commit a805e75
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 37 deletions.
38 changes: 30 additions & 8 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ export interface PlatformSpecificAdapterContribution {
* This interface describes a package.json debuggers contribution section object.
*/
export interface PluginPackageDebuggersContribution extends PlatformSpecificAdapterContribution {
type: string,
label?: string,
languages?: string[],
enableBreakpointsFor?: { languageIds: string[] },
configurationAttributes: { [request: string]: IJSONSchema },
configurationSnippets: IJSONSchemaSnippet[],
variables?: ScopeMap,
adapterExecutableCommand?: string
type: string;
label?: string;
languages?: string[];
enableBreakpointsFor?: { languageIds: string[] };
configurationAttributes: { [request: string]: IJSONSchema };
configurationSnippets: IJSONSchemaSnippet[];
variables?: ScopeMap;
adapterExecutableCommand?: string;
win?: PlatformSpecificAdapterContribution;
winx86?: PlatformSpecificAdapterContribution;
windows?: PlatformSpecificAdapterContribution;
Expand Down Expand Up @@ -338,6 +338,7 @@ export interface PluginContribution {
views?: { [location: string]: View[] };
menus?: { [location: string]: Menu[] };
keybindings?: Keybinding[];
debuggers?: DebuggerContribution[];
}

export interface GrammarsContribution {
Expand Down Expand Up @@ -374,6 +375,27 @@ export interface LanguageConfiguration {
wordPattern?: string;
}

/**
* This interface describes a package.json debuggers contribution section object.
*/
export interface DebuggerContribution extends PlatformSpecificAdapterContribution {
type: string,
label?: string,
languages?: string[],
enableBreakpointsFor?: {
languageIds: string[]
},
configurationAttributes?: IJSONSchema[],
configurationSnippets?: IJSONSchemaSnippet[],
variables?: ScopeMap,
adapterExecutableCommand?: string
win?: PlatformSpecificAdapterContribution;
winx86?: PlatformSpecificAdapterContribution;
windows?: PlatformSpecificAdapterContribution;
osx?: PlatformSpecificAdapterContribution;
linux?: PlatformSpecificAdapterContribution;
}

export interface IndentationRules {
increaseIndentPattern: string;
decreaseIndentPattern: string;
Expand Down
20 changes: 19 additions & 1 deletion packages/plugin-ext/src/hosted/node/plugin-reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ export class HostedPluginReader implements BackendApplicationContribution {
return undefined;
}

const plugin: PluginPackage = require(packageJsonPath);
let rawData = fs.readFileSync(packageJsonPath).toString();
rawData = this.localize(rawData, path);

const plugin: PluginPackage = JSON.parse(rawData);
plugin.packagePath = path;
const pluginMetadata = this.scanner.getPluginMetadata(plugin);
if (pluginMetadata.model.entryPoint.backend) {
Expand All @@ -95,6 +98,21 @@ export class HostedPluginReader implements BackendApplicationContribution {
return pluginMetadata;
}

private localize(rawData: string, pluginPath: string): string {
const nlsPath = pluginPath + 'package.nls.json';
if (fs.existsSync(nlsPath)) {
const nlsMap: {
[key: string]: string
} = require(nlsPath);
for (const key of Object.keys(nlsMap)) {
const value = nlsMap[key].replace(/\"/g, '\\"');
rawData = rawData.split('%' + key + '%').join(value);
}
}

return rawData;
}

getPlugin(): PluginMetadata | undefined {
return this.plugin;
}
Expand Down
133 changes: 132 additions & 1 deletion packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,30 @@ import {
View,
PluginPackageView,
Menu,
PluginPackageMenu
PluginPackageMenu,
PluginPackageDebuggersContribution,
DebuggerContribution
} from '../../../common/plugin-protocol';
import * as fs from 'fs';
import * as path from 'path';
import { isObject } from 'util';
import { GrammarsReader } from './grammars-reader';
import { CharacterPair } from '../../../api/plugin-api';
import * as jsoncparser from 'jsonc-parser';
import { IJSONSchema } from '@theia/core/lib/common/json-schema';
import { deepClone } from '@theia/core/lib/common/objects';

namespace nls {
export function localize(key: string, _default: string) {
return _default;
}
}

const INTERNAL_CONSOLE_OPTIONS_SCHEMA = {
enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart'],
default: 'openOnFirstSessionStart',
description: nls.localize('internalConsoleOptions', 'Controls when the internal debug console should open.')
};

@injectable()
export class TheiaPluginScanner implements PluginScanner {
Expand Down Expand Up @@ -146,6 +162,12 @@ export class TheiaPluginScanner implements PluginScanner {
if (rawPlugin.contributes && rawPlugin.contributes.keybindings) {
contributions.keybindings = rawPlugin.contributes.keybindings.map(rawKeybinding => this.readKeybinding(rawKeybinding));
}

if (rawPlugin.contributes!.debuggers) {
const debuggers = this.readDebuggers(rawPlugin.contributes.debuggers!);
contributions.debuggers = debuggers;
}

return contributions;
}

Expand Down Expand Up @@ -242,6 +264,115 @@ export class TheiaPluginScanner implements PluginScanner {

}

private readDebuggers(rawDebuggers: PluginPackageDebuggersContribution[]): DebuggerContribution[] {
return rawDebuggers.map(rawDebug => this.readDebugger(rawDebug));
}

private readDebugger(rawDebugger: PluginPackageDebuggersContribution): DebuggerContribution {
const result: DebuggerContribution = {
type: rawDebugger.type,
label: rawDebugger.label,
languages: rawDebugger.languages,
enableBreakpointsFor: rawDebugger.enableBreakpointsFor,
variables: rawDebugger.variables,
adapterExecutableCommand: rawDebugger.adapterExecutableCommand,
configurationSnippets: rawDebugger.configurationSnippets,
win: rawDebugger.win,
winx86: rawDebugger.winx86,
windows: rawDebugger.windows,
osx: rawDebugger.osx,
linux: rawDebugger.linux,
program: rawDebugger.program,
args: rawDebugger.args,
runtime: rawDebugger.runtime,
runtimeArgs: rawDebugger.runtimeArgs
};

result.configurationAttributes = rawDebugger.configurationAttributes
&& this.resolveSchemaAttributes(rawDebugger.type, rawDebugger.configurationAttributes);

return result;
}

protected resolveSchemaAttributes(type: string, configurationAttributes: { [request: string]: IJSONSchema }): IJSONSchema[] {
const taskSchema = {};
return Object.keys(configurationAttributes).map(request => {
const attributes: IJSONSchema = deepClone(configurationAttributes[request]);
const defaultRequired = ['name', 'type', 'request'];
attributes.required = attributes.required && attributes.required.length ? defaultRequired.concat(attributes.required) : defaultRequired;
attributes.additionalProperties = false;
attributes.type = 'object';
if (!attributes.properties) {
attributes.properties = {};
}
const properties = attributes.properties;
properties['type'] = {
enum: [type],
description: nls.localize('debugType', 'Type of configuration.'),
pattern: '^(?!node2)',
errorMessage: nls.localize('debugTypeNotRecognised',
'The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled.'),
patternErrorMessage: nls.localize('node2NotSupported',
'"node2" is no longer supported, use "node" instead and set the "protocol" attribute to "inspector".')
};
properties['name'] = {
type: 'string',
description: nls.localize('debugName', 'Name of configuration; appears in the launch configuration drop down menu.'),
default: 'Launch'
};
properties['request'] = {
enum: [request],
description: nls.localize('debugRequest', 'Request type of configuration. Can be "launch" or "attach".'),
};
properties['debugServer'] = {
type: 'number',
description: nls.localize('debugServer',
'For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode'),
default: 4711
};
properties['preLaunchTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
}],
default: '',
description: nls.localize('debugPrelaunchTask', 'Task to run before debug session starts.')
};
properties['postDebugTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
}],
default: '',
description: nls.localize('debugPostDebugTask', 'Task to run after debug session ends.')
};
properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA;

const osProperties = Object.assign({}, properties);
properties['windows'] = {
type: 'object',
description: nls.localize('debugWindowsConfiguration', 'Windows specific launch configuration attributes.'),
properties: osProperties
};
properties['osx'] = {
type: 'object',
description: nls.localize('debugOSXConfiguration', 'OS X specific launch configuration attributes.'),
properties: osProperties
};
properties['linux'] = {
type: 'object',
description: nls.localize('debugLinuxConfiguration', 'Linux specific launch configuration attributes.'),
properties: osProperties
};
Object.keys(attributes.properties).forEach(name => {
// Use schema allOf property to get independent error reporting #21113
attributes!.properties![name].pattern = attributes!.properties![name].pattern || '^(?!.*\\$\\{(env|config|command)\\.)';
attributes!.properties![name].patternErrorMessage = attributes!.properties![name].patternErrorMessage ||
nls.localize('deprecatedVariables', "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.");
});

return attributes;
});
}

private extractValidAutoClosingPairs(langId: string, configuration: PluginPackageLanguageContributionConfiguration): AutoClosingPairConditional[] | undefined {
const source = configuration.autoClosingPairs;
if (typeof source === 'undefined') {
Expand Down
12 changes: 6 additions & 6 deletions packages/plugin-ext/src/plugin/node/debug/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { DebuggerDescription } from '@theia/debug/lib/common/debug-service';
import { DebugProtocol } from 'vscode-debugprotocol';
import { PluginPackageDebuggersContribution } from '../../../common';
import { DebuggerContribution } from '../../../common';
import { DebugAdapterSessionImpl } from '@theia/debug/lib/node/debug-adapter-session';
import { ChildProcess, spawn, fork } from 'child_process';
import { ConnectionExtImpl } from '../../connection-ext';
Expand Down Expand Up @@ -113,19 +113,19 @@ export class DebugExtImpl implements DebugExt {
registerDebugConfigurationProvider(
debugType: string,
provider: theia.DebugConfigurationProvider,
packageContribution: PluginPackageDebuggersContribution,
debuggerContribution: DebuggerContribution,
pluginPath: string): Disposable {

const contributionId = uuid.v4();
const contribution = new PluginDebugAdapterContribution(
const adapterContribution = new PluginDebugAdapterContribution(
debugType,
provider,
packageContribution,
debuggerContribution,
this.commandRegistryExt,
pluginPath);
this.contributions.set(contributionId, contribution);
this.contributions.set(contributionId, adapterContribution);

const description: DebuggerDescription = { type: debugType, label: packageContribution.label || debugType };
const description: DebuggerDescription = { type: debugType, label: debuggerContribution.label || debugType };
this.proxy.$registerDebugConfigurationProvider(contributionId, description);

return Disposable.create(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import * as theia from '@theia/plugin';
import * as path from 'path';
import { DebugConfiguration } from '@theia/debug/lib/common/debug-configuration';
import { PluginPackageDebuggersContribution, PlatformSpecificAdapterContribution } from '../../../common';
import { PlatformSpecificAdapterContribution, DebuggerContribution } from '../../../common';
import { DebugAdapterExecutable } from '@theia/debug/lib/node/debug-model';
import { CommandRegistryImpl } from '../../command-registry';
import { IJSONSchemaSnippet, IJSONSchema } from '@theia/core/lib/common/json-schema';
Expand All @@ -27,7 +27,7 @@ export class PluginDebugAdapterContribution {
constructor(
protected readonly debugType: string,
protected readonly provider: theia.DebugConfigurationProvider,
protected readonly packageContribution: PluginPackageDebuggersContribution,
protected readonly debuggerContribution: DebuggerContribution,
protected readonly commandRegistryExt: CommandRegistryImpl,
protected readonly pluginPath: string) {
}
Expand All @@ -49,26 +49,26 @@ export class PluginDebugAdapterContribution {
}

async getSupportedLanguages(): Promise<string[]> {
return this.packageContribution.languages || [];
return this.debuggerContribution.languages || [];
}

async provideDebugAdapterExecutable(debugConfiguration: theia.DebugConfiguration): Promise<DebugAdapterExecutable> {
if (this.packageContribution.adapterExecutableCommand) {
return await this.commandRegistryExt.executeCommand(this.packageContribution.adapterExecutableCommand, []) as DebugAdapterExecutable;
if (this.debuggerContribution.adapterExecutableCommand) {
return await this.commandRegistryExt.executeCommand(this.debuggerContribution.adapterExecutableCommand, []) as DebugAdapterExecutable;
}

const info = this.toPlatformInfo(this.packageContribution);
let program = (info && info.program || this.packageContribution.program);
const info = this.toPlatformInfo(this.debuggerContribution);
let program = (info && info.program || this.debuggerContribution.program);
if (!program) {
throw new Error('It is not possible to provide debug adapter executable. Program not found.');
}
program = path.join(this.pluginPath, program);
const programArgs = info && info.args || this.packageContribution.args || [];
let runtime = info && info.runtime || this.packageContribution.runtime;
const programArgs = info && info.args || this.debuggerContribution.args || [];
let runtime = info && info.runtime || this.debuggerContribution.runtime;
if (runtime && runtime.indexOf('./') === 0) {
runtime = path.join(this.pluginPath, runtime);
}
const runtimeArgs = info && info.runtimeArgs || this.packageContribution.runtimeArgs || [];
const runtimeArgs = info && info.runtimeArgs || this.debuggerContribution.runtimeArgs || [];
const command = runtime ? runtime : program;
const args = runtime ? [...runtimeArgs, program, ...programArgs] : programArgs;
return {
Expand All @@ -78,19 +78,14 @@ export class PluginDebugAdapterContribution {
}

async getSchemaAttributes(): Promise<IJSONSchema[]> {
const configurationSnippets = this.packageContribution.configurationSnippets;
if (configurationSnippets) {
return [];
}

return Object.keys(configurationSnippets).map(request => configurationSnippets[request]);
return this.debuggerContribution.configurationSnippets || [];
}

async getConfigurationSnippets(): Promise<IJSONSchemaSnippet[]> {
return this.packageContribution.configurationSnippets || [];
return this.debuggerContribution.configurationSnippets || [];
}

protected toPlatformInfo(executable: PluginPackageDebuggersContribution): PlatformSpecificAdapterContribution | undefined {
protected toPlatformInfo(executable: DebuggerContribution): PlatformSpecificAdapterContribution | undefined {
if (isWindows && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')) {
return executable.winx86 || executable.win || executable.windows;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import { ConnectionExtImpl } from './connection-ext';
import { WebviewsExtImpl } from './webviews';
import { TasksExtImpl } from './tasks/tasks';
import { DebugExtImpl } from './node/debug/debug';
import { PluginPackageDebuggersContribution } from '../common';
import { DebuggerContribution } from '../common';

export function createAPIFactory(
rpc: RPCProtocol,
Expand Down Expand Up @@ -513,9 +513,9 @@ export function createAPIFactory(
return debugExt.onDidChangeBreakpoints;
},
registerDebugConfigurationProvider(debugType: string, provider: theia.DebugConfigurationProvider): Disposable {
const debuggersContribution = plugin.rawModel.contributes && plugin.rawModel.contributes.debuggers;
const debuggersContribution = plugin.model.contributes && plugin.model.contributes.debuggers;
if (debuggersContribution) {
const contribution = debuggersContribution.filter((value: PluginPackageDebuggersContribution) => value.type === debugType)[0];
const contribution = debuggersContribution.filter((value: DebuggerContribution) => value.type === debugType)[0];
if (contribution) {
console.info(`Registered debug contribution provider: '${debugType}'`);
return debugExt.registerDebugConfigurationProvider(debugType, provider, contribution, plugin.pluginFolder);
Expand Down

0 comments on commit a805e75

Please sign in to comment.