提交 58f23957 编写于 作者: D Dirk Baeumer

Fixes #5387: Risky dependency from DebugService to TaskService

上级 3a3c6b34
......@@ -9,7 +9,6 @@ import 'vs/css!./media/task.contribution';
import 'vs/workbench/parts/tasks/browser/taskQuickOpen';
import * as nls from 'vs/nls';
import * as Env from 'vs/base/common/flags';
import { TPromise, Promise } from 'vs/base/common/winjs.base';
import Severity from 'vs/base/common/severity';
......@@ -72,13 +71,27 @@ class AbstractTaskAction extends Action {
protected taskService: ITaskService;
protected telemetryService: ITelemetryService;
private messageService: IMessageService;
private contextService: IWorkspaceContextService;
constructor(id:string, label:string, @ITaskService taskService:ITaskService,
@ITelemetryService telemetryService: ITelemetryService) {
@ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService,
@IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label);
this.taskService = taskService;
this.telemetryService = telemetryService;
this.messageService = messageService;
this.contextService = contextService;
}
protected canRun(): boolean {
if (!this.contextService.getWorkspace()) {
this.messageService.show(Severity.Info, nls.localize('AbstractTaskAction.noWorkspace', 'Tasks are only available on a workspace folder.'));
return false;
}
return true;
}
}
......@@ -86,11 +99,15 @@ class BuildAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.build';
public static TEXT = nls.localize('BuildAction.label','Run Build Task');
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService) {
super(id, label, taskService, telemetryService);
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
}
public run(): Promise {
public run(): TPromise<ITaskSummary> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.taskService.build();
}
}
......@@ -99,11 +116,15 @@ class TestAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.test';
public static TEXT = nls.localize('TestAction.label','Run Test Task');
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService) {
super(id, label, taskService, telemetryService);
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
}
public run(): Promise {
public run(): TPromise<ITaskSummary> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.taskService.runTest();
}
}
......@@ -112,11 +133,15 @@ class RebuildAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.rebuild';
public static TEXT = nls.localize('RebuildAction.label', 'Run Rebuild Task');
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService) {
super(id, label, taskService, telemetryService);
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
}
public run(): Promise {
public run(): TPromise<ITaskSummary> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.taskService.rebuild();
}
}
......@@ -125,11 +150,15 @@ class CleanAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.clean';
public static TEXT = nls.localize('CleanAction.label', 'Run Clean Task');
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService) {
super(id, label, taskService, telemetryService);
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
}
public run(): Promise {
public run(): TPromise<ITaskSummary> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.taskService.clean();
}
}
......@@ -240,7 +269,7 @@ class CloseMessageAction extends Action {
constructor() {
super(CloseMessageAction.ID, CloseMessageAction.TEXT);
}
public run(): Promise {
public run(): TPromise<void> {
if (this.closeFunction) {
this.closeFunction();
}
......@@ -252,11 +281,15 @@ class TerminateAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.terminate';
public static TEXT = nls.localize('TerminateAction.label', 'Terminate Running Task');
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService) {
super(id, label, taskService, telemetryService);
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
}
public run(): Promise {
public run(): TPromise<TerminateResponse> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.taskService.isActive().then((active) => {
if (active) {
return this.taskService.terminate().then((response) => {
......@@ -278,29 +311,38 @@ class ShowLogAction extends AbstractTaskAction {
private outputService: IOutputService;
constructor(id: string, label: string, @ITaskService taskService:ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService,
@IOutputService outputService:IOutputService) {
super(id, label, taskService, telemetryService);
super(id, label, taskService, telemetryService, messageService, contextService);
this.outputService = outputService;
}
public run(): Promise {
public run(): TPromise<IEditor> {
if (!this.canRun()) {
return TPromise.as(undefined);
}
return this.outputService.getChannel(TaskService.OutputChannelId).show();
}
}
class RunTaskAction extends Action {
class RunTaskAction extends AbstractTaskAction {
public static ID = 'workbench.action.tasks.runTask';
public static TEXT = nls.localize('RunTaskAction.label', "Run Task");
private quickOpenService: IQuickOpenService;
constructor(id: string, label: string, @IQuickOpenService quickOpenService:IQuickOpenService) {
super(id, label);
constructor(id: string, label: string, @IQuickOpenService quickOpenService:IQuickOpenService,
@ITaskService taskService: ITaskService, @ITelemetryService telemetryService: ITelemetryService,
@IMessageService messageService:IMessageService, @IWorkspaceContextService contextService: IWorkspaceContextService) {
super(id, label, taskService, telemetryService, messageService, contextService);
this.quickOpenService = quickOpenService;
}
public run(event?:any): Promise {
if (!this.canRun()) {
return TPromise.as(undefined);
}
this.quickOpenService.show('task ');
return TPromise.as(null);
}
......@@ -447,6 +489,49 @@ interface TaskServiceEventData {
error?: any;
}
class NullTaskSystem extends EventEmitter implements ITaskSystem {
public build(): ITaskRunResult {
return {
promise: TPromise.as<ITaskSummary>({})
};
}
public rebuild(): ITaskRunResult {
return {
promise: TPromise.as<ITaskSummary>({})
};
}
public clean(): ITaskRunResult {
return {
promise: TPromise.as<ITaskSummary>({})
};
}
public runTest(): ITaskRunResult {
return {
promise: TPromise.as<ITaskSummary>({})
};
}
public run(taskIdentifier: string): ITaskRunResult {
return {
promise: TPromise.as<ITaskSummary>({})
};
}
public isActive(): TPromise<boolean> {
return TPromise.as(false);
}
public isActiveSync(): boolean {
return false;
}
public canAutoTerminate(): boolean {
return true;
}
public terminate(): TPromise<TerminateResponse> {
return TPromise.as<TerminateResponse>({ success: true });
}
public tasks(): TPromise<TaskDescription[]> {
return TPromise.as<TaskDescription[]>([]);
}
}
class TaskService extends EventEmitter implements ITaskService {
public serviceId = ITaskService;
public static SERVICE_ID: string = 'taskService';
......@@ -532,83 +617,88 @@ class TaskService extends EventEmitter implements ITaskService {
private get taskSystemPromise(): TPromise<ITaskSystem> {
if (!this._taskSystemPromise) {
let variables = new SystemVariables(this.editorService, this.contextService);
let clearOutput = true;
this._taskSystemPromise = TPromise.as(this.configurationService.getConfiguration<TaskConfiguration>('tasks')).then((config: TaskConfiguration) => {
let parseErrors: string[] = config ? (<any>config).$parseErrors : null;
if (parseErrors) {
let isAffected = false;
for (let i = 0; i < parseErrors.length; i++) {
if (/tasks\.json$/.test(parseErrors[i])) {
isAffected = true;
break;
if (!this.contextService.getWorkspace()) {
this._taskSystem = new NullTaskSystem();
this._taskSystemPromise = TPromise.as(this._taskSystem);
} else {
let variables = new SystemVariables(this.editorService, this.contextService);
let clearOutput = true;
this._taskSystemPromise = TPromise.as(this.configurationService.getConfiguration<TaskConfiguration>('tasks')).then((config: TaskConfiguration) => {
let parseErrors: string[] = config ? (<any>config).$parseErrors : null;
if (parseErrors) {
let isAffected = false;
for (let i = 0; i < parseErrors.length; i++) {
if (/tasks\.json$/.test(parseErrors[i])) {
isAffected = true;
break;
}
}
if (isAffected) {
this.outputChannel.append(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n'));
this.outputChannel.show(true);
return TPromise.wrapError({});
}
}
if (isAffected) {
this.outputChannel.append(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n'));
this.outputChannel.show(true);
return TPromise.wrapError({});
}
}
let configPromise: TPromise<TaskConfiguration>;
if (config) {
if (this.isRunnerConfig(config) && this.hasDetectorSupport(<FileConfig.ExternalTaskRunnerConfiguration>config)) {
let fileConfig = <FileConfig.ExternalTaskRunnerConfiguration>config;
configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, variables, fileConfig).detect(true).then((value) => {
clearOutput = this.printStderr(value.stderr);
let detectedConfig = value.config;
if (!detectedConfig) {
return config;
}
let result: FileConfig.ExternalTaskRunnerConfiguration = Objects.clone(fileConfig);
let configuredTasks: IStringDictionary<FileConfig.TaskDescription> = Object.create(null);
if (!result.tasks) {
if (detectedConfig.tasks) {
result.tasks = detectedConfig.tasks;
let configPromise: TPromise<TaskConfiguration>;
if (config) {
if (this.isRunnerConfig(config) && this.hasDetectorSupport(<FileConfig.ExternalTaskRunnerConfiguration>config)) {
let fileConfig = <FileConfig.ExternalTaskRunnerConfiguration>config;
configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, variables, fileConfig).detect(true).then((value) => {
clearOutput = this.printStderr(value.stderr);
let detectedConfig = value.config;
if (!detectedConfig) {
return config;
}
} else {
result.tasks.forEach(task => configuredTasks[task.taskName] = task);
detectedConfig.tasks.forEach((task) => {
if (!configuredTasks[task.taskName]) {
result.tasks.push(task);
let result: FileConfig.ExternalTaskRunnerConfiguration = Objects.clone(fileConfig);
let configuredTasks: IStringDictionary<FileConfig.TaskDescription> = Object.create(null);
if (!result.tasks) {
if (detectedConfig.tasks) {
result.tasks = detectedConfig.tasks;
}
});
}
return result;
});
} else {
result.tasks.forEach(task => configuredTasks[task.taskName] = task);
detectedConfig.tasks.forEach((task) => {
if (!configuredTasks[task.taskName]) {
result.tasks.push(task);
}
});
}
return result;
});
} else {
configPromise = TPromise.as<TaskConfiguration>(config);
}
} else {
configPromise = TPromise.as<TaskConfiguration>(config);
configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, variables).detect(true).then((value) => {
clearOutput = this.printStderr(value.stderr);
return value.config;
});
}
} else {
configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, variables).detect(true).then((value) => {
clearOutput = this.printStderr(value.stderr);
return value.config;
return configPromise.then((config) => {
if (!config) {
this._taskSystemPromise = null;
throw new TaskError(Severity.Info, nls.localize('TaskSystem.noConfiguration', 'No task runner configured.'), TaskErrors.NotConfigured);
}
let result: ITaskSystem = null;
if (config.buildSystem === 'service') {
result = new LanguageServiceTaskSystem(<LanguageServiceTaskConfiguration>config, this.telemetryService, this.modeService);
} else if (this.isRunnerConfig(config)) {
result = new ProcessRunnerSystem(<FileConfig.ExternalTaskRunnerConfiguration>config, variables, this.markerService, this.modelService, this.telemetryService, this.outputService, TaskService.OutputChannelId, clearOutput);
}
if (result === null) {
this._taskSystemPromise = null;
throw new TaskError(Severity.Info, nls.localize('TaskSystem.noBuildType', "No valid task runner configured. Supported task runners are 'service' and 'program'."), TaskErrors.NoValidTaskRunner);
}
this.taskSystemListeners.push(result.addListener(TaskSystemEvents.Active, (event) => this.emit(TaskServiceEvents.Active, event)));
this.taskSystemListeners.push(result.addListener(TaskSystemEvents.Inactive, (event) => this.emit(TaskServiceEvents.Inactive, event)));
this._taskSystem = result;
return result;
}, (err: any) => {
this.handleError(err);
return Promise.wrapError(err);
});
}
return configPromise.then((config) => {
if (!config) {
this._taskSystemPromise = null;
throw new TaskError(Severity.Info, nls.localize('TaskSystem.noConfiguration', 'No task runner configured.'), TaskErrors.NotConfigured);
}
let result: ITaskSystem = null;
if (config.buildSystem === 'service') {
result = new LanguageServiceTaskSystem(<LanguageServiceTaskConfiguration>config, this.telemetryService, this.modeService);
} else if (this.isRunnerConfig(config)) {
result = new ProcessRunnerSystem(<FileConfig.ExternalTaskRunnerConfiguration>config, variables, this.markerService, this.modelService, this.telemetryService, this.outputService, TaskService.OutputChannelId, clearOutput);
}
if (result === null) {
this._taskSystemPromise = null;
throw new TaskError(Severity.Info, nls.localize('TaskSystem.noBuildType', "No valid task runner configured. Supported task runners are 'service' and 'program'."), TaskErrors.NoValidTaskRunner);
}
this.taskSystemListeners.push(result.addListener(TaskSystemEvents.Active, (event) => this.emit(TaskServiceEvents.Active, event)));
this.taskSystemListeners.push(result.addListener(TaskSystemEvents.Inactive, (event) => this.emit(TaskServiceEvents.Inactive, event)));
this._taskSystem = result;
return result;
}, (err: any) => {
this.handleError(err);
return Promise.wrapError(err);
});
});
}
}
return this._taskSystemPromise;
}
......@@ -769,7 +859,7 @@ class TaskService extends EventEmitter implements ITaskService {
let closeAction = new CloseMessageAction();
let action = needsConfig
? this.configureAction()
: new TerminateAction(TerminateAction.ID, TerminateAction.TEXT, this, this.telemetryService);
: new TerminateAction(TerminateAction.ID, TerminateAction.TEXT, this, this.telemetryService, this.messageService, this.contextService);
closeAction.closeFunction = this.messageService.show(buildError.severity, { message: buildError.message, actions: [closeAction, action ] });
} else {
......@@ -792,434 +882,430 @@ class TaskService extends EventEmitter implements ITaskService {
let tasksCategory = nls.localize('tasksCategory', "Tasks");
let workbenchActionsRegistry = <IWorkbenchActionRegistry>Registry.as(WorkbenchActionExtensions.WorkbenchActions);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureTaskRunnerAction, ConfigureTaskRunnerAction.ID, ConfigureTaskRunnerAction.TEXT), tasksCategory, ['configure', 'task', 'runner']);
if (Env.enableTasks) {
// Task Service
registerSingleton(ITaskService, TaskService);
// Actions
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(BuildAction, BuildAction.ID, BuildAction.TEXT, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_B }), tasksCategory, ['run', 'build', 'task']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(TestAction, TestAction.ID, TestAction.TEXT, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_T }), tasksCategory, ['run', 'test', 'talk']);
// workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(RebuildAction, RebuildAction.ID, RebuildAction.TEXT), tasksCategory);
// workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CleanAction, CleanAction.ID, CleanAction.TEXT), tasksCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminateAction, TerminateAction.ID, TerminateAction.TEXT), tasksCategory, ['terminate', 'running', 'task']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowLogAction, ShowLogAction.ID, ShowLogAction.TEXT), tasksCategory, ['task', 'log']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunTaskAction, RunTaskAction.ID, RunTaskAction.TEXT), tasksCategory, ['run', 'task']);
// Register Quick Open
(<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/tasks/browser/taskQuickOpen',
'QuickOpenHandler',
'task ',
nls.localize('taskCommands', "Run Task")
)
);
// Status bar
let statusbarRegistry = <IStatusbarRegistry>Registry.as(StatusbarExtensions.Statusbar);
statusbarRegistry.registerStatusbarItem(new StatusbarItemDescriptor(StatusBarItem, StatusbarAlignment.LEFT, 50 /* Medium Priority */));
// Output channel
let outputChannelRegistry = <IOutputChannelRegistry>Registry.as(OutputExt.OutputChannels);
outputChannelRegistry.registerChannel(TaskService.OutputChannelId, TaskService.OutputChannelLabel);
// (<IWorkbenchContributionsRegistry>Registry.as(WorkbenchExtensions.Workbench)).registerWorkbenchContribution(TaskServiceParticipant);
// tasks.json validation
let schemaId = 'vscode://schemas/tasks';
let schema : IJSONSchema =
{
'id': schemaId,
'description': 'Task definition file',
'type': 'object',
'default': {
'version': '0.1.0',
'command': 'myCommand',
'isShellCommand': false,
'args': [],
'showOutput': 'always',
'tasks': [
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(BuildAction, BuildAction.ID, BuildAction.TEXT, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_B }), tasksCategory, ['run', 'build', 'task']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(TestAction, TestAction.ID, TestAction.TEXT, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_T }), tasksCategory, ['run', 'test', 'talk']);
// workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(RebuildAction, RebuildAction.ID, RebuildAction.TEXT), tasksCategory);
// workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CleanAction, CleanAction.ID, CleanAction.TEXT), tasksCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminateAction, TerminateAction.ID, TerminateAction.TEXT), tasksCategory, ['terminate', 'running', 'task']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowLogAction, ShowLogAction.ID, ShowLogAction.TEXT), tasksCategory, ['task', 'log']);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(RunTaskAction, RunTaskAction.ID, RunTaskAction.TEXT), tasksCategory, ['run', 'task']);
// Task Service
registerSingleton(ITaskService, TaskService);
// Register Quick Open
(<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/tasks/browser/taskQuickOpen',
'QuickOpenHandler',
'task ',
nls.localize('taskCommands', "Run Task")
)
);
// Status bar
let statusbarRegistry = <IStatusbarRegistry>Registry.as(StatusbarExtensions.Statusbar);
statusbarRegistry.registerStatusbarItem(new StatusbarItemDescriptor(StatusBarItem, StatusbarAlignment.LEFT, 50 /* Medium Priority */));
// Output channel
let outputChannelRegistry = <IOutputChannelRegistry>Registry.as(OutputExt.OutputChannels);
outputChannelRegistry.registerChannel(TaskService.OutputChannelId, TaskService.OutputChannelLabel);
// (<IWorkbenchContributionsRegistry>Registry.as(WorkbenchExtensions.Workbench)).registerWorkbenchContribution(TaskServiceParticipant);
// tasks.json validation
let schemaId = 'vscode://schemas/tasks';
let schema : IJSONSchema =
{
'id': schemaId,
'description': 'Task definition file',
'type': 'object',
'default': {
'version': '0.1.0',
'command': 'myCommand',
'isShellCommand': false,
'args': [],
'showOutput': 'always',
'tasks': [
{
'taskName': 'build',
'showOutput': 'silent',
'isBuildCommand': true,
'problemMatcher': ['$tsc', '$lessCompile']
}
]
},
'definitions': {
'showOutputType': {
'type': 'string',
'enum': ['always', 'silent', 'never'],
'default': 'silent'
},
'patternType': {
'anyOf': [
{
'taskName': 'build',
'showOutput': 'silent',
'isBuildCommand': true,
'problemMatcher': ['$tsc', '$lessCompile']
'type': 'string',
'enum': ['$tsc', '$tsc-watch' ,'$msCompile', '$lessCompile', '$gulp-tsc', '$cpp', '$csc', '$vb', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
},
{
'$ref': '#/definitions/pattern'
},
{
'type': 'array',
'items': {
'$ref': '#/definitions/pattern'
}
}
]
},
'definitions': {
'showOutputType': {
'type': 'string',
'enum': ['always', 'silent', 'never'],
'default': 'silent'
'pattern': {
'default': {
'regexp': '^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$',
'file': 1,
'location': 2,
'message': 3
},
'patternType': {
'anyOf': [
{
'type': 'string',
'enum': ['$tsc', '$tsc-watch' ,'$msCompile', '$lessCompile', '$gulp-tsc', '$cpp', '$csc', '$vb', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
},
{
'$ref': '#/definitions/pattern'
},
{
'type': 'array',
'items': {
'$ref': '#/definitions/pattern'
}
}
]
},
'pattern': {
'default': {
'regexp': '^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$',
'file': 1,
'location': 2,
'message': 3
'additionalProperties': false,
'properties': {
'regexp': {
'type': 'string',
'description': nls.localize('JsonSchema.pattern.regexp', 'The regular expression to find an error, warning or info in the output.')
},
'additionalProperties': false,
'properties': {
'regexp': {
'type': 'string',
'description': nls.localize('JsonSchema.pattern.regexp', 'The regular expression to find an error, warning or info in the output.')
},
'file': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.file', 'The match group index of the filename. If omitted 1 is used.')
},
'location': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and column is assumed.')
},
'line': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.line', 'The match group index of the problem\'s line. Defaults to 2')
},
'column': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.column', 'The match group index of the problem\'s column. Defaults to 3')
},
'endLine': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.endLine', 'The match group index of the problem\'s end line. Defaults to undefined')
},
'endColumn': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.endColumn', 'The match group index of the problem\'s end column. Defaults to undefined')
},
'severity': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.severity', 'The match group index of the problem\'s severity. Defaults to undefined')
},
'code': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.code', 'The match group index of the problem\'s code. Defaults to undefined')
},
'message': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.message', 'The match group index of the message. If omitted it defaults to 4 if location is specified. Otherwise it defaults to 5.')
},
'loop': {
'type': 'boolean',
'description': nls.localize('JsonSchema.pattern.loop', 'In a multi line matcher loop indicated whether this pattern is executed in a loop as long as it matches. Can only specified on a last pattern in a multi line pattern.')
}
}
},
'problemMatcherType': {
'oneOf': [
{
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
},
{
'$ref': '#/definitions/problemMatcher'
},
{
'type': 'array',
'items': {
'anyOf': [
{
'$ref': '#/definitions/problemMatcher'
},
{
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
}
]
}
}
]
},
'watchingPattern': {
'type': 'object',
'additionalProperties': false,
'properties': {
'regexp': {
'type': 'string',
'description': nls.localize('JsonSchema.watchingPattern.regexp', 'The regular expression to detect the begin or end of a watching task.')
},
'file': {
'type': 'integer',
'description': nls.localize('JsonSchema.watchingPattern.file', 'The match group index of the filename. Can be omitted.')
},
'file': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.file', 'The match group index of the filename. If omitted 1 is used.')
},
'location': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted line and column is assumed.')
},
'line': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.line', 'The match group index of the problem\'s line. Defaults to 2')
},
'column': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.column', 'The match group index of the problem\'s column. Defaults to 3')
},
'endLine': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.endLine', 'The match group index of the problem\'s end line. Defaults to undefined')
},
'endColumn': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.endColumn', 'The match group index of the problem\'s end column. Defaults to undefined')
},
'severity': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.severity', 'The match group index of the problem\'s severity. Defaults to undefined')
},
'code': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.code', 'The match group index of the problem\'s code. Defaults to undefined')
},
'message': {
'type': 'integer',
'description': nls.localize('JsonSchema.pattern.message', 'The match group index of the message. If omitted it defaults to 4 if location is specified. Otherwise it defaults to 5.')
},
'loop': {
'type': 'boolean',
'description': nls.localize('JsonSchema.pattern.loop', 'In a multi line matcher loop indicated whether this pattern is executed in a loop as long as it matches. Can only specified on a last pattern in a multi line pattern.')
}
},
'problemMatcher': {
'type': 'object',
'additionalProperties': false,
'properties': {
'base': {
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go'],
'description': nls.localize('JsonSchema.problemMatcher.base', 'The name of a base problem matcher to use.')
},
'owner': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.owner', 'The owner of the problem inside Code. Can be omitted if base is specified. Defaults to \'external\' if omitted and base is not specified.')
},
'severity': {
'type': 'string',
'enum': ['error', 'warning', 'info'],
'description': nls.localize('JsonSchema.problemMatcher.severity', 'The default severity for captures problems. Is used if the pattern doesn\'t define a match group for severity.')
},
'applyTo': {
'type': 'string',
'enum': ['allDocuments', 'openDocuments', 'closedDocuments'],
'description': nls.localize('JsonSchema.problemMatcher.applyTo', 'Controls if a problem reported on a text document is applied only to open, closed or all documents.')
},
'pattern': {
'$ref': '#/definitions/patternType',
'description': nls.localize('JsonSchema.problemMatcher.pattern', 'A problem pattern or the name of a predefined problem pattern. Can be omitted if base is specified.')
},
'fileLocation': {
'oneOf': [
}
},
'problemMatcherType': {
'oneOf': [
{
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
},
{
'$ref': '#/definitions/problemMatcher'
},
{
'type': 'array',
'items': {
'anyOf': [
{
'type': 'string',
'enum': ['absolute', 'relative']
'$ref': '#/definitions/problemMatcher'
},
{
'type': 'array',
'items': {
'type': 'string'
}
}
],
'description': nls.localize('JsonSchema.problemMatcher.fileLocation', 'Defines how file names reported in a problem pattern should be interpreted.')
},
'watching': {
'type': 'object',
'additionalProperties': false,
'properties': {
'activeOnStart': {
'type': 'boolean',
'description': nls.localize('JsonSchema.problemMatcher.watching.activeOnStart', 'If set to true the watcher is in active mode when the task starts. This is equals of issuing a line that matches the beginPattern')
},
'beginsPattern': {
'oneOf': [
{
'type': 'string'
},
{
'type': '#/definitions/watchingPattern'
}
],
'description': nls.localize('JsonSchema.problemMatcher.watching.beginsPattern', 'If matched in the output the start of a watching task is signaled.')
},
'endsPattern': {
'oneOf': [
{
'type': 'string'
},
{
'type': '#/definitions/watchingPattern'
}
],
'description': nls.localize('JsonSchema.problemMatcher.watching.endsPattern', 'If matched in the output the end of a watching task is signaled.')
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go']
}
}
},
'watchedTaskBeginsRegExp': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.watchedBegin', 'A regular expression signaling that a watched tasks begins executing triggered through file watching.')
},
'watchedTaskEndsRegExp': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.watchedEnd', 'A regular expression signaling that a watched tasks ends executing.')
]
}
}
},
'baseTaskRunnerConfiguration': {
'type': 'object',
'properties': {
'command': {
'type': 'string',
'description': nls.localize('JsonSchema.command', 'The command to be executed. Can be an external program or a shell command.')
},
'isShellCommand': {
'type': 'boolean',
'default': true,
'description': nls.localize('JsonSchema.shell', 'Specifies whether the command is a shell command or an external program. Defaults to false if omitted.')
},
'args': {
'type': 'array',
'description': nls.localize('JsonSchema.args', 'Additional arguments passed to the command.'),
'items': {
'type': 'string'
]
},
'watchingPattern': {
'type': 'object',
'additionalProperties': false,
'properties': {
'regexp': {
'type': 'string',
'description': nls.localize('JsonSchema.watchingPattern.regexp', 'The regular expression to detect the begin or end of a watching task.')
},
'file': {
'type': 'integer',
'description': nls.localize('JsonSchema.watchingPattern.file', 'The match group index of the filename. Can be omitted.')
},
}
},
'problemMatcher': {
'type': 'object',
'additionalProperties': false,
'properties': {
'base': {
'type': 'string',
'enum': ['$tsc', '$tsc-watch', '$msCompile', '$lessCompile', '$gulp-tsc', '$jshint', '$jshint-stylish', '$eslint-compact', '$eslint-stylish', '$go'],
'description': nls.localize('JsonSchema.problemMatcher.base', 'The name of a base problem matcher to use.')
},
'owner': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.owner', 'The owner of the problem inside Code. Can be omitted if base is specified. Defaults to \'external\' if omitted and base is not specified.')
},
'severity': {
'type': 'string',
'enum': ['error', 'warning', 'info'],
'description': nls.localize('JsonSchema.problemMatcher.severity', 'The default severity for captures problems. Is used if the pattern doesn\'t define a match group for severity.')
},
'applyTo': {
'type': 'string',
'enum': ['allDocuments', 'openDocuments', 'closedDocuments'],
'description': nls.localize('JsonSchema.problemMatcher.applyTo', 'Controls if a problem reported on a text document is applied only to open, closed or all documents.')
},
'pattern': {
'$ref': '#/definitions/patternType',
'description': nls.localize('JsonSchema.problemMatcher.pattern', 'A problem pattern or the name of a predefined problem pattern. Can be omitted if base is specified.')
},
'fileLocation': {
'oneOf': [
{
'type': 'string',
'enum': ['absolute', 'relative']
},
{
'type': 'array',
'items': {
'type': 'string'
}
}
},
'options': {
'type': 'object',
'description': nls.localize('JsonSchema.options', 'Additional command options'),
'properties': {
'cwd': {
'type': 'string',
'description': nls.localize('JsonSchema.options.cwd', 'The current working directory of the executed program or script. If omitted Code\'s current workspace root is used.')
},
'env': {
'type': 'object',
'additionalProperties': {
],
'description': nls.localize('JsonSchema.problemMatcher.fileLocation', 'Defines how file names reported in a problem pattern should be interpreted.')
},
'watching': {
'type': 'object',
'additionalProperties': false,
'properties': {
'activeOnStart': {
'type': 'boolean',
'description': nls.localize('JsonSchema.problemMatcher.watching.activeOnStart', 'If set to true the watcher is in active mode when the task starts. This is equals of issuing a line that matches the beginPattern')
},
'beginsPattern': {
'oneOf': [
{
'type': 'string'
},
'description': nls.localize('JsonSchema.options.env', 'The environment of the executed program or shell. If omitted the parent process\' environment is used.')
}
{
'type': '#/definitions/watchingPattern'
}
],
'description': nls.localize('JsonSchema.problemMatcher.watching.beginsPattern', 'If matched in the output the start of a watching task is signaled.')
},
'additionalProperties': {
'type': ['string', 'array', 'object']
}
},
'showOutput': {
'$ref': '#/definitions/showOutputType',
'description': nls.localize('JsonSchema.showOutput', 'Controls whether the output of the running task is shown or not. If omitted \'always\' is used.')
},
'isWatching': {
'type': 'boolean',
'description': nls.localize('JsonSchema.watching', 'Whether the executed task is kept alive and is watching the file system.'),
'default': true
},
'promptOnClose': {
'type': 'boolean',
'description': nls.localize('JsonSchema.promptOnClose', 'Whether the user is prompted when VS Code closes with a running background task.'),
'default': false
},
'echoCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.echoCommand', 'Controls whether the executed command is echoed to the output. Default is false.'),
'default': true
},
'suppressTaskName': {
'type': 'boolean',
'description': nls.localize('JsonSchema.suppressTaskName', 'Controls whether the task name is added as an argument to the command. Default is false.'),
'default': true
},
'taskSelector': {
'type': 'string',
'description': nls.localize('JsonSchema.taskSelector', 'Prefix to indicate that an argument is task.')
},
'problemMatcher': {
'$ref': '#/definitions/problemMatcherType',
'description': nls.localize('JsonSchema.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.')
},
'tasks': {
'type': 'array',
'description': nls.localize('JsonSchema.tasks', 'The task configurations. Usually these are enrichments of task already defined in the external task runner.'),
'items': {
'type': 'object',
'$ref': '#/definitions/taskDescription'
'endsPattern': {
'oneOf': [
{
'type': 'string'
},
{
'type': '#/definitions/watchingPattern'
}
],
'description': nls.localize('JsonSchema.problemMatcher.watching.endsPattern', 'If matched in the output the end of a watching task is signaled.')
}
}
},
'watchedTaskBeginsRegExp': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.watchedBegin', 'A regular expression signaling that a watched tasks begins executing triggered through file watching.')
},
'watchedTaskEndsRegExp': {
'type': 'string',
'description': nls.localize('JsonSchema.problemMatcher.watchedEnd', 'A regular expression signaling that a watched tasks ends executing.')
}
},
'taskDescription': {
'type': 'object',
'required': ['taskName'],
'additionalProperties': false,
'properties': {
'taskName': {
'type': 'string',
'description': nls.localize('JsonSchema.tasks.taskName', "The task's name")
},
'args': {
'type': 'array',
'description': nls.localize('JsonSchema.tasks.args', 'Additional arguments passed to the command when this task is invoked.'),
'items': {
'type': 'string'
}
},
'baseTaskRunnerConfiguration': {
'type': 'object',
'properties': {
'command': {
'type': 'string',
'description': nls.localize('JsonSchema.command', 'The command to be executed. Can be an external program or a shell command.')
},
'isShellCommand': {
'type': 'boolean',
'default': true,
'description': nls.localize('JsonSchema.shell', 'Specifies whether the command is a shell command or an external program. Defaults to false if omitted.')
},
'args': {
'type': 'array',
'description': nls.localize('JsonSchema.args', 'Additional arguments passed to the command.'),
'items': {
'type': 'string'
}
},
'options': {
'type': 'object',
'description': nls.localize('JsonSchema.options', 'Additional command options'),
'properties': {
'cwd': {
'type': 'string',
'description': nls.localize('JsonSchema.options.cwd', 'The current working directory of the executed program or script. If omitted Code\'s current workspace root is used.')
},
'env': {
'type': 'object',
'additionalProperties': {
'type': 'string'
},
'description': nls.localize('JsonSchema.options.env', 'The environment of the executed program or shell. If omitted the parent process\' environment is used.')
}
},
'suppressTaskName': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.suppressTaskName', 'Controls whether the task name is added as an argument to the command. If omitted the globally defined value is used.'),
'default': true
},
'showOutput': {
'$ref': '#/definitions/showOutputType',
'description': nls.localize('JsonSchema.tasks.showOutput', 'Controls whether the output of the running task is shown or not. If omitted the globally defined value is used.')
},
'echoCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.echoCommand', 'Controls whether the executed command is echoed to the output. Default is false.'),
'default': true
},
'isWatching': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.watching', 'Whether the executed task is kept alive and is watching the file system.'),
'default': true
},
'isBuildCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.build', 'Maps this task to Code\'s default build command.'),
'default': true
},
'isTestCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.test', 'Maps this task to Code\'s default test command.'),
'default': true
},
'problemMatcher': {
'$ref': '#/definitions/problemMatcherType',
'description': nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.')
'additionalProperties': {
'type': ['string', 'array', 'object']
}
},
'defaultSnippets': [
{
'label': 'Empty task',
'body': {
'taskName': '{{taskName}}'
}
'showOutput': {
'$ref': '#/definitions/showOutputType',
'description': nls.localize('JsonSchema.showOutput', 'Controls whether the output of the running task is shown or not. If omitted \'always\' is used.')
},
'isWatching': {
'type': 'boolean',
'description': nls.localize('JsonSchema.watching', 'Whether the executed task is kept alive and is watching the file system.'),
'default': true
},
'promptOnClose': {
'type': 'boolean',
'description': nls.localize('JsonSchema.promptOnClose', 'Whether the user is prompted when VS Code closes with a running background task.'),
'default': false
},
'echoCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.echoCommand', 'Controls whether the executed command is echoed to the output. Default is false.'),
'default': true
},
'suppressTaskName': {
'type': 'boolean',
'description': nls.localize('JsonSchema.suppressTaskName', 'Controls whether the task name is added as an argument to the command. Default is false.'),
'default': true
},
'taskSelector': {
'type': 'string',
'description': nls.localize('JsonSchema.taskSelector', 'Prefix to indicate that an argument is task.')
},
'problemMatcher': {
'$ref': '#/definitions/problemMatcherType',
'description': nls.localize('JsonSchema.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.')
},
'tasks': {
'type': 'array',
'description': nls.localize('JsonSchema.tasks', 'The task configurations. Usually these are enrichments of task already defined in the external task runner.'),
'items': {
'type': 'object',
'$ref': '#/definitions/taskDescription'
}
]
}
}
},
'allOf': [
{
'type': 'object',
'required': ['version'],
'properties': {
'version': {
'type': 'string',
'enum': ['0.1.0'],
'description': nls.localize('JsonSchema.version', 'The config\'s version number')
},
'windows': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.windows', 'Windows specific build configuration')
},
'osx': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.mac', 'Mac specific build configuration')
},
'linux': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.linux', 'Linux specific build configuration')
'taskDescription': {
'type': 'object',
'required': ['taskName'],
'additionalProperties': false,
'properties': {
'taskName': {
'type': 'string',
'description': nls.localize('JsonSchema.tasks.taskName', "The task's name")
},
'args': {
'type': 'array',
'description': nls.localize('JsonSchema.tasks.args', 'Additional arguments passed to the command when this task is invoked.'),
'items': {
'type': 'string'
}
},
'suppressTaskName': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.suppressTaskName', 'Controls whether the task name is added as an argument to the command. If omitted the globally defined value is used.'),
'default': true
},
'showOutput': {
'$ref': '#/definitions/showOutputType',
'description': nls.localize('JsonSchema.tasks.showOutput', 'Controls whether the output of the running task is shown or not. If omitted the globally defined value is used.')
},
'echoCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.echoCommand', 'Controls whether the executed command is echoed to the output. Default is false.'),
'default': true
},
'isWatching': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.watching', 'Whether the executed task is kept alive and is watching the file system.'),
'default': true
},
'isBuildCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.build', 'Maps this task to Code\'s default build command.'),
'default': true
},
'isTestCommand': {
'type': 'boolean',
'description': nls.localize('JsonSchema.tasks.test', 'Maps this task to Code\'s default test command.'),
'default': true
},
'problemMatcher': {
'$ref': '#/definitions/problemMatcherType',
'description': nls.localize('JsonSchema.tasks.matchers', 'The problem matcher(s) to use. Can either be a string or a problem matcher definition or an array of strings and problem matchers.')
}
},
{
'$ref': '#/definitions/baseTaskRunnerConfiguration'
'defaultSnippets': [
{
'label': 'Empty task',
'body': {
'taskName': '{{taskName}}'
}
}
]
}
},
'allOf': [
{
'type': 'object',
'required': ['version'],
'properties': {
'version': {
'type': 'string',
'enum': ['0.1.0'],
'description': nls.localize('JsonSchema.version', 'The config\'s version number')
},
'windows': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.windows', 'Windows specific build configuration')
},
'osx': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.mac', 'Mac specific build configuration')
},
'linux': {
'$ref': '#/definitions/baseTaskRunnerConfiguration',
'description': nls.localize('JsonSchema.linux', 'Linux specific build configuration')
}
}
]
};
let jsonRegistry = <jsonContributionRegistry.IJSONContributionRegistry>Registry.as(jsonContributionRegistry.Extensions.JSONContribution);
jsonRegistry.registerSchema(schemaId, schema);
jsonRegistry.addSchemaFileAssociation('/.vscode/tasks.json', schemaId);
}
},
{
'$ref': '#/definitions/baseTaskRunnerConfiguration'
}
]
};
let jsonRegistry = <jsonContributionRegistry.IJSONContributionRegistry>Registry.as(jsonContributionRegistry.Extensions.JSONContribution);
jsonRegistry.registerSchema(schemaId, schema);
jsonRegistry.addSchemaFileAssociation('/.vscode/tasks.json', schemaId);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册