提交 6079bc6d 编写于 作者: B Benjamin Pasero

notifications - better error handling

上级 3891d2bb
......@@ -242,6 +242,10 @@ export interface IErrorWithActions {
actions?: IAction[];
}
export function isErrorWithActions(obj: any): obj is IErrorWithActions {
return obj instanceof Error && Array.isArray((obj as IErrorWithActions).actions);
}
export function create(message: string, options: IErrorOptions = Object.create(null)): Error & IErrorWithActions {
const result = new Error(message);
......
......@@ -48,7 +48,7 @@ import { ThrottledEmitter } from 'vs/base/common/async';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { INotificationService, Severity, INotificationActions } from 'vs/platform/notification/common/notification';
import { IErrorWithActions } from 'vs/base/common/errors';
import { isErrorWithActions } from 'vs/base/common/errors';
class ProgressMonitor {
......@@ -541,22 +541,22 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
});
}
private doHandleSetInputError(e: Error, group: EditorGroup, editor: BaseEditor, input: EditorInput, options: EditorOptions, monitor: ProgressMonitor): void {
private doHandleSetInputError(error: Error, group: EditorGroup, editor: BaseEditor, input: EditorInput, options: EditorOptions, monitor: ProgressMonitor): void {
const position = this.stacks.positionOfGroup(group);
// Stop loading promise if any
monitor.cancel();
// Report error only if this was not us restoring previous error state
if (this.partService.isCreated() && !errors.isPromiseCanceledError(e)) {
if (this.partService.isCreated() && !errors.isPromiseCanceledError(error)) {
const actions: INotificationActions = { primary: [] };
if (e && Array.isArray((<IErrorWithActions>e).actions)) {
actions.primary = (<IErrorWithActions>e).actions;
if (isErrorWithActions(error)) {
actions.primary = error.actions;
}
this.notificationService.notify({
severity: Severity.Error,
message: nls.localize('editorOpenError', "Unable to open '{0}': {1}.", input.getName(), toErrorMessage(e)),
message: nls.localize('editorOpenError', "Unable to open '{0}': {1}.", input.getName(), toErrorMessage(error)),
actions
});
}
......
......@@ -10,7 +10,7 @@ import { INotification, INotificationHandle, INotificationActions, INotification
import { toErrorMessage } from 'vs/base/common/errorMessage';
import Event, { Emitter, once } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { isPromiseCanceledError, isErrorWithActions } from 'vs/base/common/errors';
export interface INotificationsModel {
......@@ -355,7 +355,14 @@ export class NotificationViewItem implements INotificationViewItem {
message.value = `${message.value.substr(0, NotificationViewItem.MAX_MESSAGE_LENGTH)}...`;
}
return new NotificationViewItem(severity, message, notification.source, notification.actions);
let actions: INotificationActions;
if (notification.actions) {
actions = notification.actions;
} else if (isErrorWithActions(notification.message)) {
actions = { primary: notification.message.actions };
}
return new NotificationViewItem(severity, message, notification.source, actions);
}
private static toMarkdownString(input: string | IMarkdownString | Error): IMarkdownString {
......
......@@ -154,16 +154,12 @@ export class TextFileEditor extends BaseTextEditor {
return TPromise.wrapError<void>(errors.create(toErrorMessage(error), {
actions: [
new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), null, true, () => {
return this.fileService.updateContent(input.getResource(), '').then(() => {
// Open
return this.editorService.openEditor({
resource: input.getResource(),
options: {
pinned: true // new file gets pinned by default
}
});
});
return this.fileService.updateContent(input.getResource(), '').then(() => this.editorService.openEditor({
resource: input.getResource(),
options: {
pinned: true // new file gets pinned by default
}
}));
})
]
}));
......
......@@ -11,7 +11,6 @@ import arrays = require('vs/base/common/arrays');
import types = require('vs/base/common/types');
import { language, LANGUAGE_DEFAULT } from 'vs/base/common/platform';
import { Action } from 'vs/base/common/actions';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration } from 'vs/base/parts/quickopen/common/quickOpen';
import { QuickOpenEntryGroup, IHighlight, QuickOpenModel, QuickOpenEntry } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
......@@ -32,9 +31,9 @@ import { LRUCache } from 'vs/base/common/map';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { isPromiseCanceledError, IErrorWithActions } from 'vs/base/common/errors';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { INotificationService, INotificationActions, Severity } from 'vs/platform/notification/common/notification';
import { INotificationService } from 'vs/platform/notification/common/notification';
export const ALL_COMMANDS_PREFIX = '>';
......@@ -275,26 +274,6 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup {
return nls.localize('entryAriaLabel', "{0}, commands", this.getLabel());
}
private onError(error?: Error | IErrorWithActions): void {
if (isPromiseCanceledError(error)) {
return;
}
let message: string;
if (error) {
message = toErrorMessage(error);
} else {
message = nls.localize('canNotRun', "Command '{0}' can not be run from here.", this.label);
}
const actions: INotificationActions = { primary: [] };
if (error && Array.isArray((<IErrorWithActions>error).actions)) {
actions.primary = (<IErrorWithActions>error).actions;
}
this.notificationService.notify({ severity: Severity.Error, message, actions });
}
public run(mode: Mode, context: IEntryRunContext): boolean {
if (mode === Mode.OPEN) {
this.runAction(this.getAction());
......@@ -336,6 +315,14 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup {
}
}, err => this.onError(err));
}
private onError(error?: Error): void {
if (isPromiseCanceledError(error)) {
return;
}
this.notificationService.error(error || nls.localize('canNotRun', "Command '{0}' can not be run from here.", this.label));
}
}
class EditorActionCommandEntry extends BaseCommandEntry {
......
......@@ -9,6 +9,7 @@ import * as assert from 'assert';
import { NotificationsModel, NotificationViewItem, INotificationChangeEvent, NotificationChangeType, NotificationViewItemLabelKind } from 'vs/workbench/common/notifications';
import { Action } from 'vs/base/common/actions';
import { INotification, Severity } from 'vs/platform/notification/common/notification';
import { create } from 'vs/base/common/errors';
suite('Notifications', () => {
......@@ -102,6 +103,10 @@ suite('Notifications', () => {
item1.dispose();
assert.equal(called, 1);
// Error with Action
let item6 = NotificationViewItem.create({ severity: Severity.Error, message: create('Hello Error', { actions: [new Action('id', 'label')] }) });
assert.equal(item6.actions.primary.length, 1);
});
test('Model', () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册