提交 3dd856a8 编写于 作者: S Sandeep Somavarapu

Fix #52627

上级 22e16c76
......@@ -9,6 +9,7 @@ export class CodeActionKind {
private static readonly sep = '.';
public static readonly Empty = new CodeActionKind('');
public static readonly QuickFix = new CodeActionKind('quickfix');
public static readonly Refactor = new CodeActionKind('refactor');
public static readonly Source = new CodeActionKind('source');
public static readonly SourceOrganizeImports = new CodeActionKind('source.organizeImports');
......
......@@ -7,7 +7,7 @@
import * as paths from 'vs/base/common/paths';
import URI from 'vs/base/common/uri';
import { Range, IRange } from 'vs/editor/common/core/range';
import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers';
import { IMarker, MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers';
import { IFilter, IMatch, or, matchesContiguousSubString, matchesPrefix, matchesFuzzy } from 'vs/base/common/filters';
import Messages from 'vs/workbench/parts/markers/electron-browser/messages';
import { Schemas } from 'vs/base/common/network';
......@@ -18,7 +18,7 @@ import * as strings from 'vs/base/common/strings';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { CodeAction } from 'vs/editor/common/modes';
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
import { CodeActionTrigger } from 'vs/editor/contrib/codeAction/codeActionTrigger';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
function compareUris(a: URI, b: URI) {
if (a.toString() < b.toString()) {
......@@ -38,6 +38,7 @@ export class ResourceMarkers extends NodeWithId {
private _name: string = null;
private _path: string = null;
private _allFixesPromise: Promise<CodeAction[]>;
markers: Marker[] = [];
isExcluded: boolean = false;
......@@ -46,7 +47,8 @@ export class ResourceMarkers extends NodeWithId {
uriMatches: IMatch[] = [];
constructor(
readonly uri: URI
readonly uri: URI,
private textModelService: ITextModelService
) {
super(uri.toString());
}
......@@ -65,6 +67,37 @@ export class ResourceMarkers extends NodeWithId {
return this._name;
}
public getFixes(marker: Marker): Promise<CodeAction[]> {
return this._getFixes(new Range(marker.range.startLineNumber, marker.range.startColumn, marker.range.endLineNumber, marker.range.endColumn));
}
public async hasFixes(marker: Marker): Promise<boolean> {
if (!this._allFixesPromise) {
this._allFixesPromise = this._getFixes();
}
const allFixes = await this._allFixesPromise;
if (allFixes.length) {
const markerKey = IMarkerData.makeKey(marker.raw);
for (const fix of allFixes) {
if (fix.diagnostics && fix.diagnostics.some(d => IMarkerData.makeKey(d) === markerKey)) {
return true;
}
}
}
return false;
}
private async _getFixes(range?: Range): Promise<CodeAction[]> {
const modelReference = await this.textModelService.createModelReference(this.uri);
if (modelReference) {
const model = modelReference.object.textEditorModel;
const codeActions = await getCodeActions(model, range ? range : model.getFullModelRange(), { type: 'manual', filter: { kind: CodeActionKind.QuickFix } });
modelReference.dispose();
return codeActions;
}
return [];
}
static compare(a: ResourceMarkers, b: ResourceMarkers): number {
let [firstMarkerOfA] = a.markers;
let [firstMarkerOfB] = b.markers;
......@@ -88,8 +121,7 @@ export class Marker extends NodeWithId {
constructor(
id: string,
readonly raw: IMarker,
private textModelService: ITextModelService
readonly raw: IMarker
) {
super(id);
}
......@@ -102,17 +134,6 @@ export class Marker extends NodeWithId {
return this.raw;
}
public async getCodeActions(trigger: CodeActionTrigger): Promise<CodeAction[]> {
const modelReference = await this.textModelService.createModelReference(this.resource);
if (modelReference) {
const model = modelReference.object.textEditorModel;
const codeActions = await getCodeActions(model, new Range(this.range.startLineNumber, this.range.startColumn, this.range.endLineNumber, this.range.endColumn), trigger);
modelReference.dispose();
return codeActions;
}
return [];
}
public toString(): string {
return JSON.stringify({
...this.raw,
......@@ -289,11 +310,11 @@ export class MarkersModel {
private createResource(uri: URI, rawMarkers: IMarker[]): ResourceMarkers {
const markers: Marker[] = [];
const resource = new ResourceMarkers(uri);
const resource = new ResourceMarkers(uri, this.textModelService);
this.updateResource(resource);
rawMarkers.forEach((rawMarker, index) => {
const marker = new Marker(uri.toString() + index, rawMarker, this.textModelService);
const marker = new Marker(uri.toString() + index, rawMarker);
if (rawMarker.relatedInformation) {
const groupedByResource = groupBy(rawMarker.relatedInformation, MarkersModel._compareMarkersByUri);
groupedByResource.sort((a, b) => compareUris(a[0].resource, b[0].resource));
......
......@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import * as mouse from 'vs/base/browser/mouseEvent';
import * as tree from 'vs/base/parts/tree/browser/tree';
import { MarkersModel, Marker } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { MarkersModel, Marker, ResourceMarkers } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IAction, Action } from 'vs/base/common/actions';
......@@ -19,6 +19,7 @@ import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { localize } from 'vs/nls';
export class Controller extends WorkbenchTreeController {
......@@ -79,10 +80,14 @@ export class Controller extends WorkbenchTreeController {
private async _getMenuActions(tree: WorkbenchTree, element: any): Promise<IAction[]> {
const result: IAction[] = [];
const quickFixActions = await this._getQuickFixActions(element);
if (quickFixActions.length) {
result.push(...quickFixActions);
if (element instanceof Marker) {
const quickFixActions = await this._getQuickFixActions(tree, element);
if (quickFixActions.length) {
result.push(...quickFixActions);
} else {
result.push(new Action('problems.no.fixes', localize('no fixes available', "No fixes available"), void 0, false));
}
result.push(new Separator());
}
......@@ -100,9 +105,10 @@ export class Controller extends WorkbenchTreeController {
return result;
}
private async _getQuickFixActions(element: any): Promise<IAction[]> {
if (element instanceof Marker) {
const codeActions = await element.getCodeActions({ type: 'manual' });
private async _getQuickFixActions(tree: WorkbenchTree, element: Marker): Promise<IAction[]> {
const parent = tree.getNavigator(element).parent();
if (parent instanceof ResourceMarkers) {
const codeActions = await parent.getFixes(element);
return codeActions.map(codeAction => new Action(
codeAction.command ? codeAction.command.id : codeAction.title,
codeAction.title,
......@@ -112,9 +118,8 @@ export class Controller extends WorkbenchTreeController {
return this.openFileAtMarker(element)
.then(() => applyCodeAction(codeAction, this.bulkEditService, this.commandService));
}));
}
return Promise.resolve([]);
return [];
}
public openFileAtMarker(element: Marker): TPromise<void> {
......
......@@ -31,6 +31,7 @@ interface IResourceMarkersTemplateData {
interface IMarkerTemplateData {
icon: HTMLElement;
lightbulb: HTMLElement;
source: HighlightedLabel;
description: HighlightedLabel;
lnCol: HTMLElement;
......@@ -179,6 +180,7 @@ export class Renderer implements IRenderer {
private renderMarkerTemplate(container: HTMLElement): IMarkerTemplateData {
const data: IMarkerTemplateData = Object.create(null);
data.icon = dom.append(container, dom.$('.marker-icon'));
data.lightbulb = dom.append(container, dom.$('.icon.lightbulb'));
data.source = new HighlightedLabel(dom.append(container, dom.$('')));
data.description = new HighlightedLabel(dom.append(container, dom.$('.marker-description')));
data.lnCol = dom.append(container, dom.$('span.marker-line'));
......@@ -208,7 +210,9 @@ export class Renderer implements IRenderer {
private renderMarkerElement(tree: ITree, element: Marker, templateData: IMarkerTemplateData) {
let marker = element.raw;
templateData.icon.className = 'icon ' + Renderer.iconClassNameFor(marker);
dom.removeClass(templateData.lightbulb, 'quick-fixes');
templateData.source.set(marker.source, element.sourceMatches);
dom.toggleClass(templateData.source.element, 'marker-source', !!marker.source);
......@@ -217,6 +221,11 @@ export class Renderer implements IRenderer {
templateData.description.element.title = marker.message;
templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn);
const parent = tree.getNavigator(element).parent();
if (parent instanceof ResourceMarkers) {
parent.hasFixes(element).then(hasFixes => dom.toggleClass(templateData.lightbulb, 'quick-fixes', hasFixes));
}
}
private renderRelatedInfoElement(tree: ITree, element: RelatedInformation, templateData: IRelatedInformationTemplateData) {
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M13.5 4.2C13.1 2.1 10.8 0 9.3 0H6.7c-.4 0-.6.2-.6.2C4 .8 2.5 2.7 2.5 4.9c0 .5-.1 2.3 1.7 3.8.5.5 1.2 2 1.3 2.4v3.3L7.1 16h2l1.5-1.6V11c.1-.4.8-1.9 1.3-2.3 1.1-.9 1.5-1.9 1.6-2.7V4.2z"/><g><g fill="#C5C5C5"><path d="M6.5 12h3v1h-3zM7.5 15h1.1l.9-1h-3z"/></g><path fill="#DDB204" d="M12.6 5c0-2.3-1.8-4.1-4.1-4.1-.1 0-1.4.1-1.4.1-2.1.3-3.7 2-3.7 4 0 .1-.2 1.6 1.4 3 .7.7 1.5 2.4 1.6 2.9l.1.1h3l.1-.2c.1-.5.9-2.2 1.6-2.9 1.6-1.3 1.4-2.8 1.4-2.9zm-3 1l-.5 3h-.6V6c1.1 0 .9-1 .9-1H6.5v.1c0 .2.1.9 1 .9v3H7l-.2-.7L6.5 6c-.7 0-.9-.4-1-.7v-.4c0-.8.9-.9.9-.9h3.1s1 .1 1 1c0 0 .1 1-.9 1z"/></g><path fill="#252526" d="M10.5 5c0-.9-1-1-1-1H6.4s-.9.1-.9.9v.4c0 .3.3.7.9.7l.4 2.3.2.7h.5V6c-1 0-1-.7-1-.9V5h3s.1 1-.9 1v3h.6l.5-3c.9 0 .8-1 .8-1z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M13.5 4.2C13.1 2.1 10.8 0 9.3 0H6.7c-.4 0-.6.2-.6.2C4 .8 2.5 2.7 2.5 4.9c0 .5-.1 2.3 1.7 3.8.5.5 1.2 2 1.3 2.4v3.3L7.1 16h2l1.5-1.6V11c.1-.4.8-1.9 1.3-2.3 1.1-.9 1.5-1.9 1.6-2.7V4.2z"/><g><g fill="#848484"><path d="M6.5 12h3v1h-3zM7.5 15h1.1l.9-1h-3z"/></g><path fill="#fc0" d="M12.6 5c0-2.3-1.8-4.1-4.1-4.1-.1 0-1.4.1-1.4.1-2.1.3-3.7 2-3.7 4 0 .1-.2 1.6 1.4 3 .7.7 1.5 2.4 1.6 2.9l.1.1h3l.1-.2c.1-.5.9-2.2 1.6-2.9 1.6-1.3 1.4-2.8 1.4-2.9zm-3 1l-.5 3h-.6V6c1.1 0 .9-1 .9-1H6.5v.1c0 .2.1.9 1 .9v3H7l-.2-.7L6.5 6c-.7 0-.9-.4-1-.7v-.4c0-.8.9-.9.9-.9h3.1s1 .1 1 1c0 0 .1 1-.9 1z"/></g><path fill="#F0EFF1" d="M10.5 5c0-.9-1-1-1-1H6.4s-.9.1-.9.9v.4c0 .3.3.7.9.7l.4 2.3.2.7h.5V6c-1 0-1-.7-1-.9V5h3s.1 1-.9 1v3h.6l.5-3c.9 0 .8-1 .8-1z"/></svg>
\ No newline at end of file
......@@ -164,4 +164,19 @@
.vs-dark .markers-panel .icon.info {
background: url('status-info-inverse.svg') center center no-repeat;
}
.markers-panel .icon.lightbulb {
background: url('lightbulb.svg') center/40% no-repeat;
position: absolute;
width: 24px;
height: 30px;
}
.vs-dark .markers-panel .icon.lightbulb {
background: url('lightbulb-dark.svg') center/40% no-repeat;
}
.markers-panel .icon.lightbulb:not(.quick-fixes) {
display: none;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册