Merge from vscode 1fbacccbc900bb59ba8a8f26a4128d48a1c97842

This commit is contained in:
ADS Merger
2020-02-13 02:56:02 +00:00
parent 9af1f3b0eb
commit 73ea8b79b2
229 changed files with 3192 additions and 2103 deletions

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { equals, flatten, isNonEmptyArray, mergeSort } from 'vs/base/common/arrays';
import { equals, flatten, isNonEmptyArray, mergeSort, coalesce } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { illegalArgument, isPromiseCanceledError, onUnexpectedExternalError } from 'vs/base/common/errors';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
@@ -27,6 +27,8 @@ export interface CodeActionSet extends IDisposable {
readonly validActions: readonly modes.CodeAction[];
readonly allActions: readonly modes.CodeAction[];
readonly hasAutoFix: boolean;
readonly documentation: readonly modes.Command[];
}
class ManagedCodeActionSet extends Disposable implements CodeActionSet {
@@ -48,7 +50,11 @@ class ManagedCodeActionSet extends Disposable implements CodeActionSet {
public readonly validActions: readonly modes.CodeAction[];
public readonly allActions: readonly modes.CodeAction[];
public constructor(actions: readonly modes.CodeAction[], disposables: DisposableStore) {
public constructor(
actions: readonly modes.CodeAction[],
public readonly documentation: readonly modes.Command[],
disposables: DisposableStore,
) {
super();
this._register(disposables);
this.allActions = mergeSort([...actions], ManagedCodeActionSet.codeActionsComparator);
@@ -80,17 +86,23 @@ export function getCodeActions(
const promises = providers.map(async provider => {
try {
const providedCodeActions = await provider.provideCodeActions(model, rangeOrSelection, codeActionContext, cts.token);
if (cts.token.isCancellationRequested || !providedCodeActions) {
return [];
if (providedCodeActions) {
disposables.add(providedCodeActions);
}
disposables.add(providedCodeActions);
return providedCodeActions.actions.filter(action => action && filtersAction(filter, action));
if (cts.token.isCancellationRequested) {
return { actions: [] as modes.CodeAction[], documentation: undefined };
}
const filteredActions = (providedCodeActions?.actions || []).filter(action => action && filtersAction(filter, action));
const documentation = getDocumentation(provider, filteredActions, filter.include);
return { actions: filteredActions, documentation };
} catch (err) {
if (isPromiseCanceledError(err)) {
throw err;
}
onUnexpectedExternalError(err);
return [];
return { actions: [] as modes.CodeAction[], documentation: undefined };
}
});
@@ -101,9 +113,11 @@ export function getCodeActions(
}
});
return Promise.all(promises)
.then(flatten)
.then(actions => new ManagedCodeActionSet(actions, disposables))
return Promise.all(promises).then(actions => {
const allActions = flatten(actions.map(x => x.actions));
const allDocumentation = coalesce(actions.map(x => x.documentation));
return new ManagedCodeActionSet(allActions, allDocumentation, disposables);
})
.finally(() => {
listener.dispose();
cts.dispose();
@@ -125,6 +139,52 @@ function getCodeActionProviders(
});
}
function getDocumentation(
provider: modes.CodeActionProvider,
providedCodeActions: readonly modes.CodeAction[],
only?: CodeActionKind
): modes.Command | undefined {
if (!provider.documentation) {
return undefined;
}
const documentation = provider.documentation.map(entry => ({ kind: new CodeActionKind(entry.kind), command: entry.command }));
if (only) {
let currentBest: { readonly kind: CodeActionKind, readonly command: modes.Command } | undefined;
for (const entry of documentation) {
if (entry.kind.contains(only)) {
if (!currentBest) {
currentBest = entry;
} else {
// Take best match
if (currentBest.kind.contains(entry.kind)) {
currentBest = entry;
}
}
}
}
if (currentBest) {
return currentBest?.command;
}
}
// Otherwise, check to see if any of the provided actions match.
for (const action of providedCodeActions) {
if (!action.kind) {
continue;
}
for (const entry of documentation) {
if (entry.kind.contains(new CodeActionKind(action.kind))) {
return entry.command;
}
}
}
return undefined;
}
registerLanguageCommand('_executeCodeActionProvider', async function (accessor, args): Promise<ReadonlyArray<modes.CodeAction>> {
const { resource, rangeOrSelection, kind } = args;
if (!(resource instanceof URI)) {