提交 80545878 编写于 作者: J Johannes Rieken

more more code actions in F8, fixes #13287

上级 26433f86
......@@ -5,7 +5,7 @@
/* marker zone */
.monaco-editor .marker-widget {
padding-left: 20px;
padding-left: 2px;
background-color: white;
overflow: hidden;
text-overflow: ellipsis;
......@@ -38,29 +38,3 @@
.monaco-editor .marker-widget .descriptioncontainer {
white-space: pre-wrap;
}
.monaco-editor .marker-widget .fixes .quickfixhead {
background-image: url('lightbulp.svg');
background-repeat: no-repeat;
padding-left: 20px;
}
.monaco-editor.vs-dark .marker-widget .fixes .quickfixhead,
.monaco-editor.hc-black .marker-widget .fixes .quickfixhead {
background-image: url('lightbulp-dark.svg');
}
.monaco-editor .marker-widget .fixes .quickfixentry {
text-decoration: underline;
}
.monaco-editor .marker-widget .fixes .quickfixentry:hover {
cursor: pointer;
color: blue;
}
.monaco-editor.vs-dark .marker-widget .fixes .quickfixentry:hover,
.monaco-editor.hc-black .marker-widget .fixes .quickfixentry:hover {
color: lightblue;
}
......@@ -7,26 +7,23 @@
import 'vs/css!./gotoError';
import * as nls from 'vs/nls';
import {onUnexpectedError} from 'vs/base/common/errors';
import {Emitter} from 'vs/base/common/event';
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import * as dom from 'vs/base/browser/dom';
import {ICommandService} from 'vs/platform/commands/common/commands';
import {RawContextKey, IContextKey, IContextKeyService} from 'vs/platform/contextkey/common/contextkey';
import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {Position} from 'vs/editor/common/core/position';
import {Range} from 'vs/editor/common/core/range';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IMarker, IMarkerService } from 'vs/platform/markers/common/markers';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {editorAction, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions';
import {ICodeEditor} from 'vs/editor/browser/editorBrowser';
import {editorContribution} from 'vs/editor/browser/editorBrowserExtensions';
import {ZoneWidget} from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
import {getCodeActions, IQuickFix2} from 'vs/editor/contrib/quickFix/common/quickFix';
import { editorAction, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
import EditorContextKeys = editorCommon.EditorContextKeys;
......@@ -190,124 +187,10 @@ class MarkerModel {
}
}
class FixesWidget {
domNode: HTMLDivElement;
private _disposeOnUpdate: IDisposable[] = [];
private _listener: IDisposable;
constructor(
container: HTMLElement,
private _markerWidget: MarkerNavigationWidget,
@ICommandService private _commandService: ICommandService
) {
this.domNode = document.createElement('div');
container.appendChild(this.domNode);
this._listener = dom.addStandardDisposableListener(container, 'keydown', (e) => {
switch (e.asKeybinding()) {
case KeyCode.LeftArrow:
this._move(true);
e.preventDefault();
e.stopPropagation();
break;
case KeyCode.RightArrow:
this._move(false);
e.preventDefault();
e.stopPropagation();
break;
}
});
}
dispose(): void {
this._disposeOnUpdate = dispose(this._disposeOnUpdate);
this._listener = dispose(this._listener);
}
update(marker: IMarker): TPromise<any> {
this._disposeOnUpdate = dispose(this._disposeOnUpdate);
this.domNode.style.display = 'none';
if (marker) {
const fixes = getCodeActions(this._markerWidget.editor.getModel(), Range.lift(marker));
return fixes.then(fixes => this._doUpdate(fixes), onUnexpectedError);
}
}
private _doUpdate(fixes: IQuickFix2[]): void {
dom.clearNode(this.domNode);
if (!fixes || fixes.length === 0) {
return;
}
// light bulb and label
let quickfixhead = document.createElement('span');
quickfixhead.className = 'quickfixhead';
quickfixhead.appendChild(document.createTextNode(fixes.length > 1
? nls.localize('quickfix.multiple.label', 'Suggested fixes: ')
: nls.localize('quickfix.single.label', 'Suggested fix: ')));
this.domNode.appendChild(quickfixhead);
// each fix as entry
const container = document.createElement('span');
container.className = 'quickfixcontainer';
fixes.forEach((fix, idx, arr) => {
if (idx > 0) {
let separator = document.createElement('span');
separator.appendChild(document.createTextNode(', '));
container.appendChild(separator);
}
let entry = document.createElement('a');
entry.tabIndex = 0;
entry.className = `quickfixentry`;
entry.dataset['idx'] = String(idx);
entry.dataset['next'] = String(idx < arr.length - 1 ? idx + 1 : 0);
entry.dataset['prev'] = String(idx > 0 ? idx - 1 : arr.length - 1);
entry.appendChild(document.createTextNode(fix.command.title));
this._disposeOnUpdate.push(dom.addDisposableListener(entry, dom.EventType.CLICK, (e) => {
this._commandService.executeCommand(fix.command.id, ...fix.command.arguments);
this._markerWidget.focus();
e.preventDefault();
}));
this._disposeOnUpdate.push(dom.addStandardDisposableListener(entry, 'keydown', (e) => {
switch (e.asKeybinding()) {
case KeyCode.Enter:
case KeyCode.Space:
this._commandService.executeCommand(fix.command.id, ...fix.command.arguments);
this._markerWidget.focus();
e.preventDefault();
e.stopPropagation();
}
}));
container.appendChild(entry);
});
this.domNode.appendChild(container);
this.domNode.style.display = '';
}
private _move(left: boolean): void {
let target: HTMLElement;
if (document.activeElement.classList.contains('quickfixentry')) {
let current = <HTMLElement> document.activeElement;
let idx = left ? current.dataset['prev'] : current.dataset['next'];
target = <HTMLElement>this.domNode.querySelector(`a[data-idx='${idx}']`);
} else {
target = <HTMLElement> this.domNode.querySelector('.quickfixentry');
}
target.focus();
}
}
class MessageWidget {
domNode: HTMLDivElement;
lines: number = 0;
constructor(container: HTMLElement) {
this.domNode = document.createElement('div');
......@@ -318,9 +201,11 @@ class MessageWidget {
}
update({source, message}: IMarker): void {
this.lines = 1;
if (source) {
const indent = new Array(source.length + 3 + 1).join(' ');
message = `[${source}] ` + message.replace(/\r\n|\r|\n/g, function () {
message = `[${source}] ` + message.replace(/\r\n|\r|\n/g, () => {
this.lines += 1;
return '\n' + indent;
});
}
......@@ -334,7 +219,6 @@ class MarkerNavigationWidget extends ZoneWidget {
private _container: HTMLElement;
private _title: HTMLElement;
private _message: MessageWidget;
private _fixesWidget: FixesWidget;
private _callOnDispose: IDisposable[] = [];
constructor(editor: ICodeEditor, private _model: MarkerModel, private _commandService: ICommandService) {
......@@ -367,10 +251,6 @@ class MarkerNavigationWidget extends ZoneWidget {
this._message = new MessageWidget(this._container);
this.editor.applyFontInfo(this._message.domNode);
this._fixesWidget = new FixesWidget(this._container, this, this._commandService);
this._fixesWidget.domNode.classList.add('fixes');
this._callOnDispose.push(this._fixesWidget);
}
public show(where: editorCommon.IPosition, heightInLines: number): void {
......@@ -393,11 +273,9 @@ class MarkerNavigationWidget extends ZoneWidget {
// update:
// * title
// * message
// * quick fixes
this._container.classList.remove('stale');
this._title.innerHTML = nls.localize('title.wo_source', "({0}/{1})", this._model.indexOf(marker), this._model.total);
this._message.update(marker);
this._fixesWidget.update(marker).then(() => this._relayout());
this._model.withoutWatchingEditorPosition(() => {
......@@ -420,20 +298,14 @@ class MarkerNavigationWidget extends ZoneWidget {
}
private _onMarkersChanged(): void {
const marker = this._model.findMarkerAtPosition(this.position);
if (marker) {
this._container.classList.remove('stale');
this._message.update(marker);
this._relayout();
this._fixesWidget.update(marker).then(() => this._relayout());
} else {
this._container.classList.add('stale');
this._fixesWidget.update(marker);
this._relayout();
}
this._relayout();
}
protected _relayout(): void {
......@@ -441,9 +313,7 @@ class MarkerNavigationWidget extends ZoneWidget {
}
private computeRequiredHeight() {
// minimum one line content, add one line for zone widget decorations
const lineHeight = this.editor.getConfiguration().lineHeight || 12;
return Math.max(1, Math.ceil(this._container.clientHeight / lineHeight)) + 1;
return 1 + this._message.lines;
}
}
......@@ -451,12 +321,12 @@ class MarkerNavigationAction extends EditorAction {
private _isNext: boolean;
constructor(next: boolean, opts:IActionOptions) {
constructor(next: boolean, opts: IActionOptions) {
super(opts);
this._isNext = next;
}
public run(accessor:ServicesAccessor, editor:editorCommon.ICommonCodeEditor): void {
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
const telemetryService = accessor.get(ITelemetryService);
let controller = MarkerController.get(editor);
......
<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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册