Skip to content

Commit fdb97f4

Browse files
committed
more command metadata, check args on exthost side
1 parent 9408e3b commit fdb97f4

4 files changed

Lines changed: 167 additions & 71 deletions

File tree

src/vs/base/common/types.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -123,25 +123,27 @@ export type TypeConstraint = string | Function;
123123
export function validateConstraints(args: any[], constraints: TypeConstraint[]): void {
124124
const len = Math.min(args.length, constraints.length);
125125
for (let i = 0; i < len; i++) {
126-
const arg = args[i];
127-
const constraint = constraints[i];
128-
129-
if (typeof constraint === 'string') {
130-
if (typeof arg !== constraint) {
131-
throw new Error(`argument #${i} does not match constraint: typeof ${constraint}`);
132-
}
133-
} else if (typeof constraint === 'function') {
134-
if (arg instanceof constraint) {
135-
continue;
136-
}
137-
if (arg && arg.constructor === constraint) {
138-
continue;
139-
}
140-
if (constraint.length === 1 && constraint.call(undefined, arg) === true) {
141-
continue;
142-
}
143-
throw new Error(`argument #${i} does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true`);
126+
validateConstraint(args[i], constraints[i])
127+
}
128+
}
129+
130+
export function validateConstraint(arg: any, constraint: TypeConstraint): void {
131+
132+
if (typeof constraint === 'string') {
133+
if (typeof arg !== constraint) {
134+
throw new Error(`argument does not match constraint: typeof ${constraint}`);
135+
}
136+
} else if (typeof constraint === 'function') {
137+
if (arg instanceof constraint) {
138+
return;
139+
}
140+
if (arg && arg.constructor === constraint) {
141+
return;
142+
}
143+
if (constraint.length === 1 && constraint.call(undefined, arg) === true) {
144+
return;
144145
}
146+
throw new Error(`argument does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true`);
145147
}
146148
}
147149

src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export class ExtHostLanguageFeatureCommands {
5252
returns: 'A promise that resolves to an array of SymbolInformation-instances.'
5353
}
5454
});
55-
5655
this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider, {
5756
description: 'Execute all definition provider.',
5857
signature: {
@@ -63,7 +62,6 @@ export class ExtHostLanguageFeatureCommands {
6362
returns: 'A promise that resolves to an array of Location-instances.'
6463
}
6564
});
66-
6765
this._register('vscode.executeHoverProvider', this._executeHoverProvider, {
6866
description: 'Execute all definition provider.',
6967
signature: {
@@ -74,7 +72,6 @@ export class ExtHostLanguageFeatureCommands {
7472
returns: 'A promise that resolves to an array of Hover-instances.'
7573
}
7674
});
77-
7875
this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights, {
7976
description: 'Execute document highlight provider.',
8077
signature: {
@@ -85,17 +82,108 @@ export class ExtHostLanguageFeatureCommands {
8582
returns: 'A promise that resolves to an array of DocumentHighlight-instances.'
8683
}
8784
});
88-
89-
this._register('vscode.executeReferenceProvider', this._executeReferenceProvider);
90-
this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider);
91-
this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider);
92-
this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider);
93-
this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider);
94-
this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider);
95-
this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider);
96-
this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider);
97-
this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider);
98-
this._register('vscode.executeFormatOnTypeProvider', this._executeFormatOnTypeProvider);
85+
this._register('vscode.executeReferenceProvider', this._executeReferenceProvider, {
86+
description: 'Execute reference provider.',
87+
signature: {
88+
args: [
89+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
90+
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
91+
],
92+
returns: 'A promise that resolves to an array of Location-instances.'
93+
}
94+
});
95+
this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider, {
96+
description: 'Execute rename provider.',
97+
signature: {
98+
args: [
99+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
100+
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
101+
{ name: 'newName', description: 'The new symbol name', constraint: String }
102+
],
103+
returns: 'A promise that resolves to a WorkspaceEdit.'
104+
}
105+
});
106+
this._register('vscode.executeSignatureHelpProvider', this._executeSignatureHelpProvider, {
107+
description: 'Execute signature help provider.',
108+
signature: {
109+
args: [
110+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
111+
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
112+
],
113+
returns: 'A promise that resolves to SignatureHelp.'
114+
}
115+
});
116+
this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider, {
117+
description: 'Execute document symbol provider.',
118+
signature: {
119+
args: [
120+
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
121+
],
122+
returns: 'A promise that resolves to an array of SymbolInformation-instances.'
123+
}
124+
});
125+
this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider, {
126+
description: 'Execute completion item provider.',
127+
signature: {
128+
args: [
129+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
130+
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
131+
],
132+
returns: 'A promise that resolves to an array of CompletionItem-instances.'
133+
}
134+
});
135+
this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider, {
136+
description: 'Execute code action provider.',
137+
signature: {
138+
args: [
139+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
140+
{ name: 'range', description: 'Range in a text document', constraint: types.Range }
141+
],
142+
returns: 'A promise that resolves to an array of CompletionItem-instances.'
143+
}
144+
});
145+
this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider, {
146+
description: 'Execute completion item provider.',
147+
signature: {
148+
args: [
149+
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
150+
],
151+
returns: 'A promise that resolves to an array of Commands.'
152+
}
153+
});
154+
this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider, {
155+
description: 'Execute document format provider.',
156+
signature: {
157+
args: [
158+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
159+
{ name: 'options', description: 'Formatting options' }
160+
],
161+
returns: 'A promise that resolves to an array of TextEdits.'
162+
}
163+
});
164+
this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider, {
165+
description: 'Execute range format provider.',
166+
signature: {
167+
args: [
168+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
169+
{ name: 'range', description: 'Range in a text document', constraint: types.Range },
170+
{ name: 'options', description: 'Formatting options' }
171+
],
172+
returns: 'A promise that resolves to an array of TextEdits.'
173+
}
174+
});
175+
this._register('vscode.executeFormatOnTypeProvider', this._executeFormatOnTypeProvider, {
176+
description: 'Execute document format provider.',
177+
signature: {
178+
args: [
179+
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
180+
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
181+
{ name: 'ch', description: 'Character that got typed', constraint: String },
182+
{ name: 'options', description: 'Formatting options' }
183+
],
184+
returns: 'A promise that resolves to an array of TextEdits.'
185+
}
186+
});
99187
}
100188

101189
// --- command impl

src/vs/workbench/api/common/pluginHostCommands.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'use strict';
66

77
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
8+
import {TypeConstraint, validateConstraint} from 'vs/base/common/types';
89
import {IEventService} from 'vs/platform/event/common/event';
910
import {PluginsRegistry} from 'vs/platform/plugins/common/pluginsRegistry';
1011
import {SyncActionDescriptor} from 'vs/platform/actions/common/actions';
@@ -104,16 +105,21 @@ export class PluginHostCommands {
104105
return Promise.reject<T>(id);
105106
}
106107
try {
107-
let {callback, thisArg} = command;
108+
let {callback, thisArg, description} = command;
109+
if (description) {
110+
for (let i = 0; i < description.signature.args.length; i++) {
111+
validateConstraint(args[i], description.signature.args[i].constraint);
112+
}
113+
}
108114
let result = callback.apply(thisArg, args);
109115
return Promise.resolve(result);
110116
} catch (err) {
111-
try {
112-
console.log(toErrorMessage(err));
113-
console.log(err);
114-
} catch (err) {
115-
//
116-
}
117+
// try {
118+
// console.log(toErrorMessage(err));
119+
// console.log(err);
120+
// } catch (err) {
121+
// //
122+
// }
117123
return Promise.reject<T>(`Running the contributed command:'${id}' failed.`);
118124
}
119125
}

src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,22 @@ suite('ExtHostLanguageFeatureCommands', function() {
119119

120120
// --- workspace symbols
121121

122-
// test('WorkspaceSymbols, invalid arguments', function(done) {
123-
// let promises = [
124-
// commands.executeCommand('vscode.executeWorkspaceSymbolProvider'),
125-
// commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null),
126-
// commands.executeCommand('vscode.executeWorkspaceSymbolProvider', undefined),
127-
// commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true)
128-
// ];
129-
130-
// threadService.sync().then(() => {
131-
// TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
132-
// assert.equal(err.length, 4);
133-
// done();
134-
// return [];
135-
// });
136-
// });
137-
// });
122+
test('WorkspaceSymbols, invalid arguments', function(done) {
123+
let promises = [
124+
commands.executeCommand('vscode.executeWorkspaceSymbolProvider'),
125+
commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null),
126+
commands.executeCommand('vscode.executeWorkspaceSymbolProvider', undefined),
127+
commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true)
128+
];
129+
130+
// threadService.sync().then(() => {
131+
TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
132+
assert.equal(err.length, 4);
133+
done();
134+
return [];
135+
});
136+
// });
137+
});
138138

139139
test('WorkspaceSymbols, ⇔ back and forth', function(done) {
140140

@@ -172,22 +172,22 @@ suite('ExtHostLanguageFeatureCommands', function() {
172172

173173
// --- definition
174174

175-
// test('Definition, invalid arguments', function(done) {
176-
// let promises = [
177-
// commands.executeCommand('vscode.executeDefinitionProvider'),
178-
// commands.executeCommand('vscode.executeDefinitionProvider', null),
179-
// commands.executeCommand('vscode.executeDefinitionProvider', undefined),
180-
// commands.executeCommand('vscode.executeDefinitionProvider', true, false)
181-
// ];
182-
183-
// threadService.sync().then(() => {
184-
// TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
185-
// assert.equal(err.length, 4);
186-
// done();
187-
// return [];
188-
// });
189-
// });
190-
// });
175+
test('Definition, invalid arguments', function(done) {
176+
let promises = [
177+
commands.executeCommand('vscode.executeDefinitionProvider'),
178+
commands.executeCommand('vscode.executeDefinitionProvider', null),
179+
commands.executeCommand('vscode.executeDefinitionProvider', undefined),
180+
commands.executeCommand('vscode.executeDefinitionProvider', true, false)
181+
];
182+
183+
// threadService.sync().then(() => {
184+
TPromise.join(<any[]>promises).then(undefined, (err: any[]) => {
185+
assert.equal(err.length, 4);
186+
done();
187+
return [];
188+
});
189+
// });
190+
});
191191

192192
test('Definition, ⇔ back and forth', function(done) {
193193

0 commit comments

Comments
 (0)