extHostApiCommands.ts 14.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle';
import * as vscode from 'vscode';
J
Johannes Rieken 已提交
11 12
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import * as types from 'vs/workbench/api/node/extHostTypes';
13
import {ISingleEditOperation} from 'vs/editor/common/editorCommon';
14
import * as modes from 'vs/editor/common/modes';
15
import {ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
J
Johannes Rieken 已提交
16
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
17
import {IQuickFix2} from 'vs/editor/contrib/quickFix/common/quickFix';
18
import {IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen';
B
Benjamin Pasero 已提交
19
import {ITypeBearing} from 'vs/workbench/parts/search/common/search';
J
Johannes Rieken 已提交
20
import {ICodeLensData} from 'vs/editor/contrib/codelens/common/codelens';
J
Johannes Rieken 已提交
21
import {IThreadService} from 'vs/platform/thread/common/thread';
J
Johannes Rieken 已提交
22

J
Johannes Rieken 已提交
23 24
export function registerApiCommands(threadService: IThreadService) {
	const commands = threadService.getRemotable(ExtHostCommands);
J
Johannes Rieken 已提交
25
	new ExtHostApiCommands(commands).registerCommands();
J
Johannes Rieken 已提交
26 27 28
}

class ExtHostApiCommands {
29

30
	private _commands: ExtHostCommands;
31 32
	private _disposables: IDisposable[] = [];

33
	constructor(commands: ExtHostCommands) {
34
		this._commands = commands;
J
Johannes Rieken 已提交
35
	}
36

J
Johannes Rieken 已提交
37
	registerCommands() {
38 39
		this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider, {
			description: 'Execute all workspace symbol provider.',
J
Johannes Rieken 已提交
40 41 42
			args: [{ name: 'query', constraint: String }],
			returns: 'A promise that resolves to an array of SymbolInformation-instances.'

43 44 45
		});
		this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider, {
			description: 'Execute all definition provider.',
J
Johannes Rieken 已提交
46 47 48 49 50
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
			],
			returns: 'A promise that resolves to an array of Location-instances.'
51 52 53
		});
		this._register('vscode.executeHoverProvider', this._executeHoverProvider, {
			description: 'Execute all definition provider.',
J
Johannes Rieken 已提交
54 55 56 57 58
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
			],
			returns: 'A promise that resolves to an array of Hover-instances.'
59 60 61
		});
		this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights, {
			description: 'Execute document highlight provider.',
J
Johannes Rieken 已提交
62 63 64 65 66
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position }
			],
			returns: 'A promise that resolves to an array of DocumentHighlight-instances.'
67
		});
68 69
		this._register('vscode.executeReferenceProvider', this._executeReferenceProvider, {
			description: 'Execute reference provider.',
J
Johannes Rieken 已提交
70 71 72 73 74
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position }
			],
			returns: 'A promise that resolves to an array of Location-instances.'
75 76 77
		});
		this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider, {
			description: 'Execute rename provider.',
J
Johannes Rieken 已提交
78 79 80 81 82 83
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position },
				{ name: 'newName', description: 'The new symbol name', constraint: String }
			],
			returns: 'A promise that resolves to a WorkspaceEdit.'
84 85 86
		});
		this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider, {
			description: 'Execute signature help provider.',
J
Johannes Rieken 已提交
87 88 89 90 91
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position }
			],
			returns: 'A promise that resolves to SignatureHelp.'
92 93 94
		});
		this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider, {
			description: 'Execute document symbol provider.',
J
Johannes Rieken 已提交
95 96 97 98
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI }
			],
			returns: 'A promise that resolves to an array of SymbolInformation-instances.'
99 100 101
		});
		this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider, {
			description: 'Execute completion item provider.',
J
Johannes Rieken 已提交
102 103 104 105
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position }
			],
106
			returns: 'A promise that resolves to a CompletionList-instance.'
107 108 109
		});
		this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider, {
			description: 'Execute code action provider.',
J
Johannes Rieken 已提交
110 111 112 113 114
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'range', description: 'Range in a text document', constraint: types.Range }
			],
			returns: 'A promise that resolves to an array of CompletionItem-instances.'
115 116 117
		});
		this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider, {
			description: 'Execute completion item provider.',
J
Johannes Rieken 已提交
118 119 120 121
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI }
			],
			returns: 'A promise that resolves to an array of Commands.'
122 123 124
		});
		this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider, {
			description: 'Execute document format provider.',
J
Johannes Rieken 已提交
125 126 127 128 129
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'options', description: 'Formatting options' }
			],
			returns: 'A promise that resolves to an array of TextEdits.'
130 131 132
		});
		this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider, {
			description: 'Execute range format provider.',
J
Johannes Rieken 已提交
133 134 135 136 137 138
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'range', description: 'Range in a text document', constraint: types.Range },
				{ name: 'options', description: 'Formatting options' }
			],
			returns: 'A promise that resolves to an array of TextEdits.'
139 140 141
		});
		this._register('vscode.executeFormatOnTypeProvider', this._executeFormatOnTypeProvider, {
			description: 'Execute document format provider.',
J
Johannes Rieken 已提交
142 143 144 145 146 147 148
			args: [
				{ name: 'uri', description: 'Uri of a text document', constraint: URI },
				{ name: 'position', description: 'Position in a text document', constraint: types.Position },
				{ name: 'ch', description: 'Character that got typed', constraint: String },
				{ name: 'options', description: 'Formatting options' }
			],
			returns: 'A promise that resolves to an array of TextEdits.'
149
		});
150 151 152 153 154 155 156 157 158 159 160 161 162


		this._register('vscode.previewHtml', (uri: URI, position?: vscode.ViewColumn) => {
			return this._commands.executeCommand('_workbench.previewHtml', uri,
				typeof position === 'number' ? typeConverters.fromViewColumn(position) : void 0);

		}, {
			description: 'Preview an html document.',
			args: [
				{ name: 'uri', description: 'Uri of the document to preview.', constraint: URI },
				{ name: 'column', description: '(optional) Column in which to preview.' },
			]
		});
163 164 165 166
	}

	// --- command impl

167 168 169
	private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void {
		let disposable = this._commands.registerCommand(id, handler, this, description);
		this._disposables.push(disposable);
J
Johannes Rieken 已提交
170 171
	}

172 173 174 175 176 177
	/**
	 * Execute workspace symbol provider.
	 *
	 * @param query Search string to match query symbol names
	 * @return A promise that resolves to an array of symbol information.
	 */
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
	private _executeWorkspaceSymbolProvider(query: string): Thenable<types.SymbolInformation[]> {
		return this._commands.executeCommand<ITypeBearing[]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
			if (Array.isArray(value)) {
				return value.map(typeConverters.toSymbolInformation);
			}
		});
	}

	private _executeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position)
		};
		return this._commands.executeCommand<modes.IReference[]>('_executeDefinitionProvider', args).then(value => {
			if (Array.isArray(value)) {
193
				return value.map(typeConverters.location.to);
194 195 196 197 198 199 200 201 202 203 204
			}
		});
	}

	private _executeHoverProvider(resource: URI, position: types.Position): Thenable<types.Hover[]> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position)
		};
		return this._commands.executeCommand<modes.IComputeExtraInfoResult[]>('_executeHoverProvider', args).then(value => {
			if (Array.isArray(value)) {
B
Benjamin Pasero 已提交
205
				return value.map(typeConverters.toHover);
206 207 208
			}
		});
	}
209 210 211 212 213 214 215 216

	private _executeDocumentHighlights(resource: URI, position: types.Position): Thenable<types.DocumentHighlight[]> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position)
		};
		return this._commands.executeCommand<modes.IOccurence[]>('_executeDocumentHighlights', args).then(value => {
			if (Array.isArray(value)) {
B
Benjamin Pasero 已提交
217
				return value.map(typeConverters.toDocumentHighlight);
218 219 220
			}
		});
	}
J
Johannes Rieken 已提交
221 222 223 224 225 226 227 228

	private _executeReferenceProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position)
		};
		return this._commands.executeCommand<modes.IReference[]>('_executeDocumentHighlights', args).then(value => {
			if (Array.isArray(value)) {
229
				return value.map(typeConverters.location.to);
J
Johannes Rieken 已提交
230 231 232
			}
		});
	}
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

	private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Thenable<types.WorkspaceEdit> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position),
			newName
		};
		return this._commands.executeCommand<modes.IRenameResult>('_executeDocumentRenameProvider', args).then(value => {
			if (!value) {
				return;
			}
			if (value.rejectReason) {
				return TPromise.wrapError(value.rejectReason);
			}
			let workspaceEdit = new types.WorkspaceEdit();
			for (let edit of value.edits) {
				workspaceEdit.replace(edit.resource, typeConverters.toRange(edit.range), edit.newText);
			}
			return workspaceEdit;
		});
	}

	private _executeSignatureHelpProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable<types.SignatureHelp> {
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position),
			triggerCharacter
		};
		return this._commands.executeCommand<modes.IParameterHints>('_executeSignatureHelpProvider', args).then(value => {
			if (value) {
				return typeConverters.SignatureHelp.to(value);
			}
		});
	}
267

268
	private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable<types.CompletionItem[]|types.CompletionList> {
269 270 271 272 273
		const args = {
			resource,
			position: position && typeConverters.fromPosition(position),
			triggerCharacter
		};
274
		return this._commands.executeCommand<modes.ISuggestResult[][]>('_executeCompletionItemProvider', args).then(value => {
275 276
			if (value) {
				let items: types.CompletionItem[] = [];
277
				let incomplete: boolean;
278 279
				for (let group of value) {
					for (let suggestions of group) {
280
						incomplete = suggestions.incomplete || incomplete;
281
						for (let suggestion of suggestions.suggestions) {
282
							const item = typeConverters.Suggest.to(suggestions, position, suggestion);
283 284 285 286
							items.push(item);
						}
					}
				}
287
				return new types.CompletionList(<any>items, incomplete);
288 289 290 291
			}
		});
	}

292 293 294 295 296 297 298 299 300 301
	private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> {
		const args = {
			resource
		};
		return this._commands.executeCommand<IOutline>('_executeDocumentSymbolProvider', args).then(value => {
			if (value && Array.isArray(value.entries)) {
				return value.entries.map(typeConverters.SymbolInformation.fromOutlineEntry);
			}
		});
	}
302 303 304 305 306 307 308

	private _executeCodeActionProvider(resource: URI, range: types.Range): Thenable<vscode.Command[]> {
		const args = {
			resource,
			range: typeConverters.fromRange(range)
		};
		return this._commands.executeCommand<IQuickFix2[]>('_executeCodeActionProvider', args).then(value => {
309 310
			if (!Array.isArray(value)) {
				return;
311
			}
312
			return value.map(quickFix => typeConverters.Command.to(quickFix.command));
313 314
		});
	}
J
Johannes Rieken 已提交
315

J
Johannes Rieken 已提交
316
	private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]> {
317
		const args = { resource };
J
Johannes Rieken 已提交
318
		return this._commands.executeCommand<ICodeLensData[]>('_executeCodeLensProvider', args).then(value => {
J
Johannes Rieken 已提交
319
			if (Array.isArray(value)) {
J
Johannes Rieken 已提交
320
				return value.map(item => {
321 322
					return new types.CodeLens(
						typeConverters.toRange(item.symbol.range),
J
Johannes Rieken 已提交
323 324
						typeConverters.Command.to(item.symbol.command));
				});
J
Johannes Rieken 已提交
325 326 327
			}
		});
	}
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352

	private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
		const args = {
			resource,
			options
		};
		return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args).then(value => {
			if (Array.isArray(value)) {
				return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
			}
		});
	}

	private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
		const args = {
			resource,
			range: typeConverters.fromRange(range),
			options
		};
		return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args).then(value => {
			if (Array.isArray(value)) {
				return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
			}
		});
	}
353

J
Johannes Rieken 已提交
354
	private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
355 356 357 358 359 360 361 362 363 364 365 366
		const args = {
			resource,
			position: typeConverters.fromPosition(position),
			ch,
			options
		};
		return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args).then(value => {
			if (Array.isArray(value)) {
				return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
			}
		});
	}
367
}