mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 11:08:51 +01:00
Prototyping new CodeAction API (#36316)
* Add CodeAction Type Adds skeleton on a new CodeActionType and allows codeActionProvider to return either `Command`s or `CodeAction`s Move proposed CodeAction API to proposed and try using it in TS Split CodeAction into quickfix and refactoring classes Update proposed interface Update for new API Adding basic docs * Support workspace edits and text edits in codeactions * Remove placeholders * Resolving conflicts and making PR suggested changes * Fix quick fix test * Revert change to only use `CodeAction` instead of `CodeAction | Command` in modes since this will break `vscode.executeCodeActionProvider`
This commit is contained in:
@@ -531,6 +531,7 @@ export function createApiFactory(
|
||||
debug,
|
||||
// types
|
||||
CancellationTokenSource: CancellationTokenSource,
|
||||
CodeAction: extHostTypes.CodeAction,
|
||||
CodeLens: extHostTypes.CodeLens,
|
||||
Color: extHostTypes.Color,
|
||||
ColorPresentation: extHostTypes.ColorPresentation,
|
||||
|
||||
@@ -581,7 +581,7 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover>;
|
||||
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]>;
|
||||
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]>;
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]>;
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<(modes.Command | modes.CodeAction)[]>;
|
||||
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
|
||||
@@ -111,7 +111,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
orderLoop: for (let i = 0; i < 4; i++) {
|
||||
for (let diagnostic of diagnostics) {
|
||||
if (diagnostic.severity === order[i]) {
|
||||
const len = marker.push(DiagnosticCollection._toMarkerData(diagnostic));
|
||||
const len = marker.push(DiagnosticCollection.toMarkerData(diagnostic));
|
||||
if (len === DiagnosticCollection._maxDiagnosticsPerFile) {
|
||||
break orderLoop;
|
||||
}
|
||||
@@ -129,7 +129,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
endColumn: marker[marker.length - 1].endColumn
|
||||
});
|
||||
} else {
|
||||
marker = diagnostics.map(DiagnosticCollection._toMarkerData);
|
||||
marker = diagnostics.map(DiagnosticCollection.toMarkerData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
}
|
||||
}
|
||||
|
||||
private static _toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData {
|
||||
public static toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData {
|
||||
|
||||
let range = diagnostic.range;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject } from './extHost.protocol';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
@@ -269,7 +269,7 @@ class QuickFixAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCodeActions(resource: URI, range: IRange): TPromise<modes.Command[]> {
|
||||
provideCodeActions(resource: URI, range: IRange): TPromise<(modes.CodeAction | modes.Command)[]> {
|
||||
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const ran = <vscode.Range>TypeConverters.toRange(range);
|
||||
@@ -285,11 +285,37 @@ class QuickFixAdapter {
|
||||
}
|
||||
});
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => {
|
||||
return asWinJsPromise(token =>
|
||||
this._provider.provideCodeActions2
|
||||
? this._provider.provideCodeActions2(doc, ran, { diagnostics: allDiagnostics }, token)
|
||||
: this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)
|
||||
).then(commands => {
|
||||
if (!Array.isArray(commands)) {
|
||||
return undefined;
|
||||
}
|
||||
return commands.map(command => this._commands.toInternal(command));
|
||||
return commands.map((action): modes.CodeAction => {
|
||||
if (!action) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof action.command === 'string') {
|
||||
return this._commands.toInternal(action as vscode.Command);
|
||||
}
|
||||
|
||||
const codeAction = action as vscode.CodeAction;
|
||||
return {
|
||||
title: codeAction.title,
|
||||
command: codeAction.command ? this._commands.toInternal(codeAction.command) : undefined,
|
||||
edits: codeAction.edits
|
||||
? Array.isArray(codeAction.edits)
|
||||
? TypeConverters.WorkspaceEdit.fromTextEdits(resource, codeAction.edits)
|
||||
: TypeConverters.WorkspaceEdit.from(codeAction.edits)
|
||||
: undefined,
|
||||
diagnostics: codeAction.diagnostics
|
||||
? codeAction.diagnostics.map(DiagnosticCollection.toMarkerData)
|
||||
: undefined
|
||||
} as modes.CodeAction;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -438,22 +464,7 @@ class RenameAdapter {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let result = <modes.WorkspaceEdit>{
|
||||
edits: []
|
||||
};
|
||||
|
||||
for (let entry of value.entries()) {
|
||||
let [uri, textEdits] = entry;
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: TypeConverters.fromRange(textEdit.range)
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return TypeConverters.WorkspaceEdit.from(value);
|
||||
}, err => {
|
||||
if (typeof err === 'string') {
|
||||
return <modes.WorkspaceEdit>{
|
||||
@@ -917,7 +928,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> {
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<(modes.Command | modes.CodeAction)[]> {
|
||||
return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range));
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +223,35 @@ export const TextEdit = {
|
||||
}
|
||||
};
|
||||
|
||||
export namespace WorkspaceEdit {
|
||||
export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit {
|
||||
const result: modes.WorkspaceEdit = { edits: [] };
|
||||
for (let entry of value.entries()) {
|
||||
let [uri, textEdits] = entry;
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: fromRange(textEdit.range)
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function fromTextEdits(uri: vscode.Uri, textEdits: vscode.TextEdit[]): modes.WorkspaceEdit {
|
||||
const result: modes.WorkspaceEdit = { edits: [] };
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: fromRange(textEdit.range)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export namespace SymbolKind {
|
||||
|
||||
|
||||
@@ -808,6 +808,21 @@ export class SymbolInformation {
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeAction {
|
||||
title: string;
|
||||
|
||||
command?: vscode.Command;
|
||||
|
||||
edits?: TextEdit[] | WorkspaceEdit;
|
||||
|
||||
dianostics?: Diagnostic[];
|
||||
|
||||
constructor(title: string, edits?: TextEdit[] | WorkspaceEdit) {
|
||||
this.title = title;
|
||||
this.edits = edits;
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeLens {
|
||||
|
||||
range: Range;
|
||||
@@ -889,6 +904,11 @@ export class SignatureHelp {
|
||||
}
|
||||
}
|
||||
|
||||
export enum CodeActionType {
|
||||
QuickFix = 1,
|
||||
Refactoring = 2
|
||||
}
|
||||
|
||||
export enum CompletionTriggerKind {
|
||||
Invoke = 0,
|
||||
TriggerCharacter = 1
|
||||
|
||||
Reference in New Issue
Block a user