Skip to content

Commit

Permalink
create dummy commands (and manage them) when code action or code lens…
Browse files Browse the repository at this point in the history
… commands have argument #1698
  • Loading branch information
jrieken committed Jan 4, 2016
1 parent 8b5d2dd commit ff077c1
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 31 deletions.
39 changes: 24 additions & 15 deletions src/vs/workbench/api/common/extHostLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import URI from 'vs/base/common/uri';
import {DefaultFilter} from 'vs/editor/common/modes/modesFilters';
import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle';
import {IDisposable, disposeAll} from 'vs/base/common/lifecycle';
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
import {Range as EditorRange} from 'vs/editor/common/core/range';
import * as vscode from 'vscode';
Expand All @@ -33,7 +33,7 @@ import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/pa
import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest';

function isThenable<T>(obj: any): obj is Thenable<T> {
return obj && typeof obj['then'] === 'function';
return obj && typeof (<Thenable<any>>obj).then === 'function';
}

function asWinJsPromise<T>(callback: (token: vscode.CancellationToken) => T | Thenable<T>): TPromise<T> {
Expand Down Expand Up @@ -75,41 +75,45 @@ class OutlineAdapter implements IOutlineSupport {
class CodeLensAdapter implements modes.ICodeLensSupport {

private _documents: ExtHostModelService;
private _commands: ExtHostCommands;
private _provider: vscode.CodeLensProvider;

private _cache: { [uri: string]: vscode.CodeLens[] } = Object.create(null);
private _cachedLenses: { [uri: string]: vscode.CodeLens[] } = Object.create(null);
private _cachedCommands: IDisposable[] = [];

constructor(documents: ExtHostModelService, provider: vscode.CodeLensProvider) {
constructor(documents: ExtHostModelService, commands: ExtHostCommands, provider: vscode.CodeLensProvider) {
this._documents = documents;
this._commands = commands;
this._provider = provider;
}

findCodeLensSymbols(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
let doc = this._documents.getDocument(resource);
let key = resource.toString();

delete this._cache[key];
this._cachedCommands = disposeAll(this._cachedCommands);
delete this._cachedLenses[key];

return asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(value => {
if (!Array.isArray(value)) {
return;
}

this._cache[key] = value;
this._cachedLenses[key] = value;

return value.map((lens, i) => {
return <modes.ICodeLensSymbol>{
id: String(i),
range: TypeConverters.fromRange(lens.range),
command: TypeConverters.Command.from(lens.command)
command: TypeConverters.Command.from(lens.command, { commands: this._commands, disposables: this._cachedCommands })
};
});
});
}

resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {

let lenses = this._cache[resource.toString()];
let lenses = this._cachedLenses[resource.toString()];
if (!lenses) {
return;
}
Expand All @@ -136,7 +140,7 @@ class CodeLensAdapter implements modes.ICodeLensSupport {
};
}

symbol.command = TypeConverters.Command.from(command);
symbol.command = TypeConverters.Command.from(command, { commands: this._commands, disposables: this._cachedCommands });
return symbol;
});
}
Expand Down Expand Up @@ -279,39 +283,44 @@ class QuickFixAdapter implements modes.IQuickFixSupport {
private _commands: ExtHostCommands;
private _provider: vscode.CodeActionProvider;

private _cachedCommands: IDisposable[] = [];

constructor(documents: ExtHostModelService, commands: ExtHostCommands, provider: vscode.CodeActionProvider) {
this._documents = documents;
this._commands = commands;
this._provider = provider;
}

getQuickFixes(resource: URI, range: IRange, marker?: IMarker[]): TPromise<modes.IQuickFix[]> {
getQuickFixes(resource: URI, range: IRange, markers?: IMarker[]): TPromise<modes.IQuickFix[]> {

const doc = this._documents.getDocument(resource);
const ran = TypeConverters.toRange(range);
const diagnostics = marker.map(marker => {
const diagnostics = markers.map(marker => {
const diag = new Diagnostic(TypeConverters.toRange(marker), marker.message);
diag.code = marker.code;
diag.severity = TypeConverters.toDiagnosticSeverty(marker.severity);
return diag;
});

this._cachedCommands = disposeAll(this._cachedCommands);
const ctx = { commands: this._commands, disposables: this._cachedCommands };

return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: <any>diagnostics }, token)).then(commands => {
if (!Array.isArray(commands)) {
return;
}
return commands.map((command, i) => {
return <modes.IQuickFix> {
command: TypeConverters.Command.from(command),
command: TypeConverters.Command.from(command, ctx),
score: i
};
});
});
}

runQuickFixAction(resource: URI, range: IRange, quickFix: modes.IQuickFix): any {
let {command} = quickFix;
return this._commands.executeCommand(command.id, ...command.arguments);
let command = TypeConverters.Command.to(quickFix.command);
return this._commands.executeCommand(command.command, ...command.arguments);
}
}

Expand Down Expand Up @@ -644,7 +653,7 @@ export class ExtHostLanguageFeatures {

registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter[handle] = new CodeLensAdapter(this._documents, provider);
this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands, provider);
this._proxy.$registerCodeLensSupport(handle, selector);
return this._createDisposable(handle);
}
Expand Down
58 changes: 42 additions & 16 deletions src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import {ExtHostCommands} from 'vs/workbench/api/common/extHostCommands';
import Severity from 'vs/base/common/severity';
import {isFalsyOrEmpty} from 'vs/base/common/arrays';
import {IDisposable} from 'vs/base/common/lifecycle';
import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import {Position as EditorPosition} from 'vs/platform/editor/common/editor';
Expand Down Expand Up @@ -419,24 +422,47 @@ export namespace SignatureHelp {
}
}

export const Command = {
from(command: vscode.Command): modes.ICommand {
if (command) {
return <modes.ICommand>{
id: command.command,
title: command.title,
arguments: command.arguments
};

export namespace Command {

const _cache: { [id: string]: vscode.Command } = Object.create(null);
let _idPool = 1;

export function from(command: vscode.Command, context: { commands: ExtHostCommands; disposables: IDisposable[]; }): modes.ICommand {

if (!command) {
return;
}
},

to(command: modes.ICommand): vscode.Command {
if (command) {
return <vscode.Command>{
const result = <modes.ICommand>{
id: command.command,
title: command.title
};

if (!isFalsyOrEmpty(command.arguments)) {

// keep command around
const id = `temp-command-${_idPool++}`;
result.id = id;
_cache[id] = command;

const disposable1 = context.commands.registerCommand(id, () => context.commands.executeCommand(command.command, ..._cache[id].arguments));
const disposable2 = { dispose() { delete _cache[id] } };
context.disposables.push(disposable1, disposable2);
}

return result;
}

export function to(command: modes.ICommand): vscode.Command {

let result = _cache[command.id];
if (!result) {
result = {
command: command.id,
title: command.title,
arguments: command.arguments
};
title: command.title
}
}
return result;
}
};
}

0 comments on commit ff077c1

Please sign in to comment.