mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
#20183 move current problem contribution to editor status
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/editorstatus';
|
||||
import * as nls from 'vs/nls';
|
||||
import { runAtThisOrScheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { format } from 'vs/base/common/strings';
|
||||
import { format, compare } from 'vs/base/common/strings';
|
||||
import { extname, basename, isEqual } from 'vs/base/common/resources';
|
||||
import { areFunctions, withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -50,6 +50,8 @@ import { Event } from 'vs/base/common/event';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { IMarker, IMarkerService, MarkerSeverity, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
|
||||
class SideBySideEditorEncodingSupport implements IEncodingSupport {
|
||||
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
|
||||
@@ -282,6 +284,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
private readonly eolElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
private readonly modeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
private readonly metadataElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
private readonly currentProblemStatus: ShowCurrentMarkerInStatusbarContribution = this._register(this.instantiationService.createInstance(ShowCurrentMarkerInStatusbarContribution));
|
||||
|
||||
private readonly state = new State();
|
||||
private readonly activeEditorListeners = this._register(new DisposableStore());
|
||||
@@ -299,7 +302,8 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -577,6 +581,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
this.onEncodingChange(activeControl, activeCodeEditor);
|
||||
this.onIndentationChange(activeCodeEditor);
|
||||
this.onMetadataChange(activeControl);
|
||||
this.currentProblemStatus.update(activeCodeEditor);
|
||||
|
||||
// Dispose old active editor listeners
|
||||
this.activeEditorListeners.clear();
|
||||
@@ -594,6 +599,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
// Hook Listener for Selection changes
|
||||
this.activeEditorListeners.add(activeCodeEditor.onDidChangeCursorPosition((event: ICursorPositionChangedEvent) => {
|
||||
this.onSelectionChange(activeCodeEditor);
|
||||
this.currentProblemStatus.update(activeCodeEditor);
|
||||
}));
|
||||
|
||||
// Hook Listener for mode changes
|
||||
@@ -604,6 +610,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
// Hook Listener for content changes
|
||||
this.activeEditorListeners.add(activeCodeEditor.onDidChangeModelContent((e) => {
|
||||
this.onEOLChange(activeCodeEditor);
|
||||
this.currentProblemStatus.update(activeCodeEditor);
|
||||
|
||||
const selections = activeCodeEditor.getSelections();
|
||||
if (selections) {
|
||||
@@ -824,6 +831,130 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
class ShowCurrentMarkerInStatusbarContribution extends Disposable {
|
||||
|
||||
private readonly statusBarEntryAccessor: MutableDisposable<IStatusbarEntryAccessor>;
|
||||
private editor: ICodeEditor | undefined = undefined;
|
||||
private markers: IMarker[] = [];
|
||||
private currentMarker: IMarker | null = null;
|
||||
|
||||
constructor(
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IMarkerService private readonly markerService: IMarkerService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this.statusBarEntryAccessor = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
this._register(markerService.onMarkerChanged(changedResources => this.onMarkerChanged(changedResources)));
|
||||
this._register(Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('problems.showCurrentInStatus'))(() => this.updateStatus()));
|
||||
}
|
||||
|
||||
update(editor: ICodeEditor | undefined): void {
|
||||
this.editor = editor;
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
private updateStatus(): void {
|
||||
const previousMarker = this.currentMarker;
|
||||
this.currentMarker = this.getMarker();
|
||||
if (this.hasToUpdateStatus(previousMarker, this.currentMarker)) {
|
||||
if (this.currentMarker) {
|
||||
const line = this.currentMarker.message.split(/\r\n|\r|\n/g)[0];
|
||||
const text = `${this.getType(this.currentMarker)} ${line}`;
|
||||
if (!this.statusBarEntryAccessor.value) {
|
||||
this.statusBarEntryAccessor.value = this.statusbarService.addEntry({ text: '' }, 'statusbar.currentProblem', nls.localize('currentProblem', "Current Problem"), StatusbarAlignment.LEFT);
|
||||
}
|
||||
this.statusBarEntryAccessor.value.update({ text });
|
||||
} else {
|
||||
this.statusBarEntryAccessor.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private hasToUpdateStatus(previousMarker: IMarker | null, currentMarker: IMarker | null): boolean {
|
||||
if (!currentMarker) {
|
||||
return true;
|
||||
}
|
||||
if (!previousMarker) {
|
||||
return true;
|
||||
}
|
||||
return IMarkerData.makeKey(previousMarker) !== IMarkerData.makeKey(currentMarker);
|
||||
}
|
||||
|
||||
private getType(marker: IMarker): string {
|
||||
switch (marker.severity) {
|
||||
case MarkerSeverity.Error: return '$(error)';
|
||||
case MarkerSeverity.Warning: return '$(warning)';
|
||||
case MarkerSeverity.Info: return '$(info)';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getMarker(): IMarker | null {
|
||||
if (!this.configurationService.getValue<boolean>('problems.showCurrentInStatus')) {
|
||||
return null;
|
||||
}
|
||||
if (!this.editor) {
|
||||
return null;
|
||||
}
|
||||
const model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return null;
|
||||
}
|
||||
const position = this.editor.getPosition();
|
||||
if (!position) {
|
||||
return null;
|
||||
}
|
||||
return find(this.markers, marker => Range.containsPosition(marker, position)) || null;
|
||||
}
|
||||
|
||||
private onMarkerChanged(changedResources: ReadonlyArray<URI>): void {
|
||||
if (!this.editor) {
|
||||
return;
|
||||
}
|
||||
const model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
if (model && !changedResources.some(r => isEqual(model.uri, r))) {
|
||||
return;
|
||||
}
|
||||
this.updateMarkers();
|
||||
}
|
||||
|
||||
private updateMarkers(): void {
|
||||
if (!this.editor) {
|
||||
return;
|
||||
}
|
||||
const model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
if (model) {
|
||||
this.markers = this.markerService.read({
|
||||
resource: model.uri,
|
||||
severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info
|
||||
});
|
||||
this.markers.sort(compareMarker);
|
||||
} else {
|
||||
this.markers = [];
|
||||
}
|
||||
this.updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
function compareMarker(a: IMarker, b: IMarker): number {
|
||||
let res = compare(a.resource.toString(), b.resource.toString());
|
||||
if (res === 0) {
|
||||
res = MarkerSeverity.compare(a.severity, b.severity);
|
||||
}
|
||||
if (res === 0) {
|
||||
res = Range.compareRangesUsingStarts(a, b);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
function isWritableCodeEditor(codeEditor: ICodeEditor | undefined): boolean {
|
||||
if (!codeEditor) {
|
||||
return false;
|
||||
|
||||
@@ -25,21 +25,10 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { ActivePanelContext } from 'vs/workbench/common/panel';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { IMarkerService, MarkerStatistics, IMarker, MarkerSeverity, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IMarkerService, MarkerStatistics } from 'vs/platform/markers/common/markers';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
|
||||
registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService, false);
|
||||
|
||||
@@ -359,136 +348,3 @@ class MarkersStatusBarContributions extends Disposable implements IWorkbenchCont
|
||||
}
|
||||
|
||||
workbenchRegistry.registerWorkbenchContribution(MarkersStatusBarContributions, LifecyclePhase.Restored);
|
||||
|
||||
class ShowCurrentMarkerInStatusbarContribution extends Disposable implements IEditorContribution {
|
||||
|
||||
public static readonly ID = 'editor.contrib.showCurrentMarkerInStatusbar';
|
||||
|
||||
private readonly rendererDisposable: MutableDisposable<ShowCurrentMarkerInStatusbarRenderer>;
|
||||
|
||||
constructor(
|
||||
private readonly editor: ICodeEditor,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this.rendererDisposable = new MutableDisposable<ShowCurrentMarkerInStatusbarRenderer>();
|
||||
this.onDidConfigurationChange();
|
||||
this._register(Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('problems.showCurrentInStatus'))(() => this.onDidConfigurationChange()));
|
||||
}
|
||||
|
||||
private onDidConfigurationChange(): void {
|
||||
this.rendererDisposable.clear();
|
||||
if (this.configurationService.getValue<boolean>('problems.showCurrentInStatus')) {
|
||||
this.rendererDisposable.value = this.instantiationService.createInstance(ShowCurrentMarkerInStatusbarRenderer, this.editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShowCurrentMarkerInStatusbarRenderer extends Disposable {
|
||||
|
||||
private readonly statusBarEntryAccessor: MutableDisposable<IStatusbarEntryAccessor>;
|
||||
private markers: IMarker[] = [];
|
||||
private currentMarker: IMarker | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly editor: ICodeEditor,
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IMarkerService private readonly markerService: IMarkerService
|
||||
) {
|
||||
super();
|
||||
this.statusBarEntryAccessor = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
this._register(markerService.onMarkerChanged(changedResources => this.onMarkerChanged(changedResources)));
|
||||
this._register(editor.onDidChangeModel(() => this.updateMarkers()));
|
||||
this._register(editor.onDidChangeCursorPosition(() => this.render()));
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
const previousMarker = this.currentMarker;
|
||||
this.currentMarker = this.getMarker();
|
||||
if (this.hasToUpdateStatus(previousMarker, this.currentMarker)) {
|
||||
this.updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private hasToUpdateStatus(previousMarker: IMarker | null, currentMarker: IMarker | null): boolean {
|
||||
if (!currentMarker) {
|
||||
return true;
|
||||
}
|
||||
if (!previousMarker) {
|
||||
return true;
|
||||
}
|
||||
return IMarkerData.makeKey(previousMarker) !== IMarkerData.makeKey(currentMarker);
|
||||
}
|
||||
|
||||
private updateStatus(): void {
|
||||
if (this.currentMarker) {
|
||||
const line = this.currentMarker.message.split(/\r\n|\r|\n/g)[0];
|
||||
const text = `${this.getType(this.currentMarker)} ${line}`;
|
||||
if (this.statusBarEntryAccessor.value) {
|
||||
this.statusBarEntryAccessor.value.update({ text });
|
||||
} else {
|
||||
this.statusBarEntryAccessor.value = this.statusbarService.addEntry({ text }, 'statusbar.currentProblem', localize('currentProblem', "Current Problem"), StatusbarAlignment.LEFT);
|
||||
}
|
||||
} else {
|
||||
this.statusBarEntryAccessor.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private getType(marker: IMarker): string {
|
||||
switch (marker.severity) {
|
||||
case MarkerSeverity.Error: return '$(error)';
|
||||
case MarkerSeverity.Warning: return '$(warning)';
|
||||
case MarkerSeverity.Info: return '$(info)';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getMarker(): IMarker | null {
|
||||
const model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return null;
|
||||
}
|
||||
const position = this.editor.getPosition();
|
||||
if (!position) {
|
||||
return null;
|
||||
}
|
||||
return find(this.markers, marker => Range.containsPosition(marker, position)) || null;
|
||||
}
|
||||
|
||||
private onMarkerChanged(changedResources: ReadonlyArray<URI>): void {
|
||||
const editorModel = this.editor.getModel();
|
||||
if (editorModel && !changedResources.some(r => isEqual(editorModel.uri, r))) {
|
||||
return;
|
||||
}
|
||||
this.updateMarkers();
|
||||
}
|
||||
|
||||
private updateMarkers(): void {
|
||||
const editorModel = this.editor.getModel();
|
||||
if (editorModel) {
|
||||
this.markers = this.markerService.read({
|
||||
resource: editorModel.uri,
|
||||
severities: MarkerSeverity.Error | MarkerSeverity.Warning | MarkerSeverity.Info
|
||||
});
|
||||
this.markers.sort(compareMarker);
|
||||
} else {
|
||||
this.markers = [];
|
||||
}
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
function compareMarker(a: IMarker, b: IMarker): number {
|
||||
let res = compare(a.resource.toString(), b.resource.toString());
|
||||
if (res === 0) {
|
||||
res = MarkerSeverity.compare(a.severity, b.severity);
|
||||
}
|
||||
if (res === 0) {
|
||||
res = Range.compareRangesUsingStarts(a, b);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
registerEditorContribution(ShowCurrentMarkerInStatusbarContribution.ID, ShowCurrentMarkerInStatusbarContribution);
|
||||
|
||||
Reference in New Issue
Block a user