提交 84318e58 编写于 作者: M Martin Aeschlimann

There should be an API command to execute the color provider like we have for...

There should be an API command to execute the color provider like we have for code complete and others. Fixes #45867
上级 9d95fbae
......@@ -3,10 +3,17 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { ColorProviderRegistry, DocumentColorProvider, IColorInformation, IColorPresentation } from 'vs/editor/common/modes';
import { asWinJsPromise } from 'vs/base/common/async';
import { ITextModel } from 'vs/editor/common/model';
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { Range, IRange } from 'vs/editor/common/core/range';
import { illegalArgument } from 'vs/base/common/errors';
import { IModelService } from 'vs/editor/common/services/modelService';
export interface IColorData {
colorInfo: IColorInformation;
......@@ -30,3 +37,57 @@ export function getColors(model: ITextModel): TPromise<IColorData[]> {
export function getColorPresentations(model: ITextModel, colorInfo: IColorInformation, provider: DocumentColorProvider): TPromise<IColorPresentation[]> {
return asWinJsPromise(token => provider.provideColorPresentations(model, colorInfo, token));
}
registerLanguageCommand('_executeDocumentColorProvider', function (accessor, args) {
const { resource } = args;
if (!(resource instanceof URI)) {
throw illegalArgument();
}
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument();
}
const rawCIs: { range: IRange, color: [number, number, number, number] }[] = [];
const providers = ColorProviderRegistry.ordered(model).reverse();
const promises = providers.map(provider => asWinJsPromise(token => provider.provideDocumentColors(model, token)).then(result => {
if (Array.isArray(result)) {
for (let ci of result) {
rawCIs.push({ range: ci.range, color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] });
}
}
}));
return TPromise.join(promises).then(() => rawCIs);
});
registerLanguageCommand('_executeColorPresentationProvider', function (accessor, args) {
const { resource, color, range } = args;
if (!(resource instanceof URI) || !Array.isArray(color) || color.length !== 4 || !Range.isIRange(range)) {
throw illegalArgument();
}
const [red, green, blue, alpha] = color;
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument();
}
const colorInfo = {
range,
color: { red, green, blue, alpha }
};
const presentations: IColorPresentation[] = [];
const providers = ColorProviderRegistry.ordered(model).reverse();
const promises = providers.map(provider => asWinJsPromise(token => provider.provideColorPresentations(model, colorInfo, token)).then(result => {
if (Array.isArray(result)) {
presentations.push(...result);
}
}));
return TPromise.join(promises).then(() => presentations);
});
......@@ -10,6 +10,8 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import * as types from 'vs/workbench/api/node/extHostTypes';
import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
......@@ -177,7 +179,21 @@ export class ExtHostApiCommands {
args: [],
returns: 'An array of task handles'
});
this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, {
description: 'Execute document color provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
],
returns: 'A promise that resolves to an array of ColorInformation objects.'
});
this._register('vscode.executeColorPresentationProvider', this._executeColorPresentationProvider, {
description: 'Execute color presentation provider.',
args: [
{ name: 'color', description: 'The color to show and insert', constraint: types.Color },
{ name: 'context', description: 'Context object with uri and range' }
],
returns: 'A promise that resolves to an array of ColorPresentation objects.'
});
this._register('vscode.previewHtml', (uri: URI, position?: vscode.ViewColumn, label?: string, options?: any) => {
return this._commands.executeCommand('_workbench.previewHtml',
uri,
......@@ -391,6 +407,32 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentColorProvider(resource: URI): Thenable<types.ColorInformation[]> {
const args = {
resource
};
return this._commands.executeCommand<IRawColorInfo[]>('_executeDocumentColorProvider', args).then(result => {
if (result) {
return result.map(ci => ({ range: typeConverters.toRange(ci.range), color: typeConverters.Color.to(ci.color) }));
}
return [];
});
}
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable<types.ColorPresentation[]> {
const args = {
resource: context.uri,
color: typeConverters.Color.from(color),
range: typeConverters.fromRange(context.range),
};
return this._commands.executeCommand<modes.IColorPresentation[]>('_executeColorPresentationProvider', args).then(result => {
if (result) {
return result.map(typeConverters.ColorPresentation.to);
}
return [];
});
}
private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> {
const args = {
resource
......
......@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects';
import * as vscode from 'vscode';
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
......@@ -780,7 +780,7 @@ class ColorProviderAdapter {
const colorInfos: IRawColorInfo[] = colors.map(ci => {
return {
color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
color: TypeConverters.Color.from(ci.color),
range: TypeConverters.fromRange(ci.range)
};
});
......@@ -792,7 +792,7 @@ class ColorProviderAdapter {
provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
const document = this._documents.getDocumentData(resource).document;
const range = TypeConverters.toRange(raw.range);
const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]);
const color = TypeConverters.Color.to(raw.color);
return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
return value.map(TypeConverters.ColorPresentation.from);
});
......
......@@ -83,7 +83,6 @@ export function fromPosition(position: types.Position): IPosition {
return { lineNumber: position.line + 1, column: position.character + 1 };
}
export function fromDiagnostic(value: vscode.Diagnostic): IMarkerData {
return {
...fromRange(value.range),
......@@ -245,7 +244,7 @@ export const TextEdit = {
range: fromRange(edit.range)
};
},
to(edit: modes.TextEdit): vscode.TextEdit {
to(edit: modes.TextEdit): types.TextEdit {
let result = new types.TextEdit(toRange(edit.range), edit.text);
result.newEol = EndOfLine.to(edit.eol);
return result;
......@@ -547,12 +546,15 @@ export namespace DocumentLink {
}
export namespace ColorPresentation {
export function to(colorPresentation: modes.IColorPresentation): vscode.ColorPresentation {
return {
label: colorPresentation.label,
textEdit: colorPresentation.textEdit ? TextEdit.to(colorPresentation.textEdit) : undefined,
additionalTextEdits: colorPresentation.additionalTextEdits ? colorPresentation.additionalTextEdits.map(value => TextEdit.to(value)) : undefined
};
export function to(colorPresentation: modes.IColorPresentation): types.ColorPresentation {
let cp = new types.ColorPresentation(colorPresentation.label);
if (colorPresentation.textEdit) {
cp.textEdit = TextEdit.to(colorPresentation.textEdit);
}
if (colorPresentation.additionalTextEdits) {
cp.additionalTextEdits = colorPresentation.additionalTextEdits.map(value => TextEdit.to(value));
}
return cp;
}
export function from(colorPresentation: vscode.ColorPresentation): modes.IColorPresentation {
......@@ -564,6 +566,15 @@ export namespace ColorPresentation {
}
}
export namespace Color {
export function to(c: [number, number, number, number]): types.Color {
return new types.Color(c[0], c[1], c[2], c[3]);
}
export function from(color: types.Color): [number, number, number, number] {
return [color.red, color.green, color.blue, color.alpha];
}
}
export namespace TextDocumentSaveReason {
export function to(reason: SaveReason): vscode.TextDocumentSaveReason {
......
......@@ -522,4 +522,55 @@ suite('ExtHostLanguageFeatureCommands', function () {
});
});
});
test('Color provider', function () {
disposables.push(extHost.registerColorProvider(defaultSelector, <vscode.DocumentColorProvider>{
provideDocumentColors(): vscode.ColorInformation[] {
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
},
provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
const cp = new types.ColorPresentation('#ABC');
cp.textEdit = types.TextEdit.replace(new types.Range(1, 0, 1, 20), '#ABC');
cp.additionalTextEdits = [types.TextEdit.insert(new types.Position(2, 20), '*')];
return [cp];
}
}));
return rpcProtocol.sync().then(() => {
return commands.executeCommand<vscode.ColorInformation[]>('vscode.executeDocumentColorProvider', model.uri).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.color.red, 0.1);
assert.equal(first.color.green, 0.2);
assert.equal(first.color.blue, 0.3);
assert.equal(first.color.alpha, 0.4);
assert.equal(first.range.start.line, 0);
assert.equal(first.range.start.character, 0);
assert.equal(first.range.end.line, 0);
assert.equal(first.range.end.character, 20);
});
}).then(() => {
const color = new types.Color(0.5, 0.6, 0.7, 0.8);
const range = new types.Range(0, 0, 0, 20);
return commands.executeCommand<vscode.ColorPresentation[]>('vscode.executeColorPresentationProvider', color, { uri: model.uri, range }).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.label, '#ABC');
assert.equal(first.textEdit.newText, '#ABC');
assert.equal(first.textEdit.range.start.line, 1);
assert.equal(first.textEdit.range.start.character, 0);
assert.equal(first.textEdit.range.end.line, 1);
assert.equal(first.textEdit.range.end.character, 20);
assert.equal(first.additionalTextEdits.length, 1);
assert.equal(first.additionalTextEdits[0].range.start.line, 2);
assert.equal(first.additionalTextEdits[0].range.start.character, 20);
assert.equal(first.additionalTextEdits[0].range.end.line, 2);
assert.equal(first.additionalTextEdits[0].range.end.character, 20);
});
});
});
});
......@@ -45,6 +45,7 @@ import * as vscode from 'vscode';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NullLogService } from 'vs/platform/log/common/log';
import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model';
import { getColors } from 'vs/editor/contrib/colorPicker/color';
const defaultSelector = { scheme: 'far' };
const model: ITextModel = EditorModel.createFromString(
......@@ -1166,4 +1167,26 @@ suite('ExtHostLanguageFeatures', function () {
});
});
});
test('Document colors, data conversion', function () {
disposables.push(extHost.registerColorProvider(defaultSelector, <vscode.DocumentColorProvider>{
provideDocumentColors(): vscode.ColorInformation[] {
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
},
provideColorPresentations(color: vscode.Color, context: { range: vscode.Range, document: vscode.TextDocument }): vscode.ColorPresentation[] {
return [];
}
}));
return rpcProtocol.sync().then(() => {
return getColors(model).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.deepEqual(first.colorInfo.color, { red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4 });
assert.deepEqual(first.colorInfo.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 21 });
});
});
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册