提交 27ca195e 编写于 作者: I Isidor Nikolic 提交者: GitHub

Merge pull request #22948 from michelkaporin/exception-widget

Surfacing new Exception DAP in UI
...@@ -9,13 +9,13 @@ import * as dom from 'vs/base/browser/dom'; ...@@ -9,13 +9,13 @@ import * as dom from 'vs/base/browser/dom';
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget'; import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IDebugService } from 'vs/workbench/parts/debug/common/debug'; import { IDebugService, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug';
import { RunOnceScheduler } from 'vs/base/common/async'; import { RunOnceScheduler } from 'vs/base/common/async';
const $ = dom.$; const $ = dom.$;
export class ExceptionWidget extends ZoneWidget { export class ExceptionWidget extends ZoneWidget {
constructor(editor: ICodeEditor, private lineNumber: number, constructor(editor: ICodeEditor, private exceptionInfo: IExceptionInfo, private lineNumber: number,
@IContextViewService private contextViewService: IContextViewService, @IContextViewService private contextViewService: IContextViewService,
@IDebugService private debugService: IDebugService @IDebugService private debugService: IDebugService
) { ) {
...@@ -35,15 +35,38 @@ export class ExceptionWidget extends ZoneWidget { ...@@ -35,15 +35,38 @@ export class ExceptionWidget extends ZoneWidget {
this.container.style.lineHeight = `${fontInfo.lineHeight}px`; this.container.style.lineHeight = `${fontInfo.lineHeight}px`;
let title = $('.title'); let title = $('.title');
title.textContent = nls.localize('exceptionThrown', 'Exception occurred'); let msg = $('.message');
dom.append(container, title); const defaultConditionMessage = nls.localize('exceptionThrown', 'Exception has occurred.');
if (this.exceptionInfo.breakMode) {
let conditionMessage;
switch (this.exceptionInfo.breakMode) {
case 'never':
conditionMessage = nls.localize('neverException', 'User-handled exception has occurred.');
break;
case 'always':
conditionMessage = nls.localize('alwaysException', 'Always-breaking exception has occurred.');
break;
case 'unhandled':
conditionMessage = nls.localize('unhandledException', 'Unhandled exception has occurred.');
break;
case 'userUnhandled':
conditionMessage = nls.localize('userUnhandledException', 'User-unhandled exception has occurred.');
break;
default:
conditionMessage = defaultConditionMessage;
break;
}
const thread = this.debugService.getViewModel().focusedThread; title.textContent = `${conditionMessage} ${this.exceptionInfo.description}`;
if (thread && thread.stoppedDetails) { msg.textContent = this.exceptionInfo.details.stackTrace;
let msg = $('.message'); } else {
msg.textContent = thread.stoppedDetails.text; title.textContent = defaultConditionMessage;
dom.append(container, msg); msg.textContent = this.exceptionInfo.description;
} }
dom.append(container, title);
dom.append(container, msg);
} }
protected _doLayout(heightInPixel: number, widthInPixel: number): void { protected _doLayout(heightInPixel: number, widthInPixel: number): void {
......
...@@ -77,6 +77,7 @@ export interface IExpression extends ITreeElement, IExpressionContainer { ...@@ -77,6 +77,7 @@ export interface IExpression extends ITreeElement, IExpressionContainer {
export interface ISession { export interface ISession {
stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>; stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse>;
scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>; scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>; variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>; evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
...@@ -133,6 +134,11 @@ export interface IThread extends ITreeElement { ...@@ -133,6 +134,11 @@ export interface IThread extends ITreeElement {
*/ */
stoppedDetails: IRawStoppedDetails; stoppedDetails: IRawStoppedDetails;
/**
* Information about the exception if an 'exception' stopped event raised and DA supports the 'exceptionInfo' request, otherwise null.
*/
exceptionInfo: TPromise<IExceptionInfo>;
/** /**
* Gets the callstack if it has already been received from the debug * Gets the callstack if it has already been received from the debug
* adapter, otherwise it returns null. * adapter, otherwise it returns null.
...@@ -214,6 +220,13 @@ export interface IExceptionBreakpoint extends IEnablement { ...@@ -214,6 +220,13 @@ export interface IExceptionBreakpoint extends IEnablement {
label: string; label: string;
} }
export interface IExceptionInfo {
id?: string;
description?: string;
breakMode: string;
details?: DebugProtocol.ExceptionDetails;
}
// model interfaces // model interfaces
export interface IViewModel extends ITreeElement { export interface IViewModel extends ITreeElement {
......
...@@ -19,7 +19,7 @@ import { ISuggestion } from 'vs/editor/common/modes'; ...@@ -19,7 +19,7 @@ import { ISuggestion } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position'; import { Position } from 'vs/editor/common/core/position';
import { import {
ITreeElement, IExpression, IExpressionContainer, IProcess, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel, ITreeElement, IExpression, IExpressionContainer, IProcess, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel,
IConfig, ISession, IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IRawBreakpoint IConfig, ISession, IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IRawBreakpoint, IExceptionInfo
} from 'vs/workbench/parts/debug/common/debug'; } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
...@@ -490,6 +490,30 @@ export class Thread implements IThread { ...@@ -490,6 +490,30 @@ export class Thread implements IThread {
}); });
} }
/**
* Returns exception info promise if the exception was thrown, otherwise null
*/
public get exceptionInfo(): TPromise<IExceptionInfo> {
const session = this.process.session;
if (this.stoppedDetails && this.stoppedDetails.reason === 'exception') {
if (!session.capabilities.supportsExceptionInfoRequest) {
return TPromise.as({
description: this.stoppedDetails.text,
breakMode: null
});
}
return session.exceptionInfo({ threadId: this.threadId }).then(exception => ({
id: exception.body.exceptionId,
description: exception.body.description,
breakMode: exception.body.breakMode,
details: exception.body.details
}));
}
return TPromise.as(null);
}
public next(): TPromise<any> { public next(): TPromise<any> {
return this.process.session.next({ threadId: this.threadId }); return this.process.session.next({ threadId: this.threadId });
} }
......
...@@ -30,7 +30,7 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c ...@@ -30,7 +30,7 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView'; import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
import { DebugHoverWidget } from 'vs/workbench/parts/debug/electron-browser/debugHover'; import { DebugHoverWidget } from 'vs/workbench/parts/debug/electron-browser/debugHover';
import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpointAction, DisableBreakpointAction, AddConditionalBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions'; import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpointAction, DisableBreakpointAction, AddConditionalBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression } from 'vs/workbench/parts/debug/common/debug'; import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug';
import { BreakpointWidget } from 'vs/workbench/parts/debug/browser/breakpointWidget'; import { BreakpointWidget } from 'vs/workbench/parts/debug/browser/breakpointWidget';
import { ExceptionWidget } from 'vs/workbench/parts/debug/browser/exceptionWidget'; import { ExceptionWidget } from 'vs/workbench/parts/debug/browser/exceptionWidget';
import { FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets'; import { FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
...@@ -360,17 +360,21 @@ export class DebugEditorContribution implements IDebugEditorContribution { ...@@ -360,17 +360,21 @@ export class DebugEditorContribution implements IDebugEditorContribution {
const sameUri = exceptionSf.source.uri.toString() === model.uri.toString(); const sameUri = exceptionSf.source.uri.toString() === model.uri.toString();
if (this.exceptionWidget && !sameUri) { if (this.exceptionWidget && !sameUri) {
this.closeExceptionWidget(); this.closeExceptionWidget();
} else if (sameUri && focusedSf.thread.stoppedDetails && focusedSf.thread.stoppedDetails.reason === 'exception') { } else if (sameUri) {
this.showExceptionWidget(exceptionSf.lineNumber, exceptionSf.column); focusedSf.thread.exceptionInfo.then(exceptionInfo => {
if (exceptionInfo) {
this.showExceptionWidget(exceptionInfo, exceptionSf.lineNumber, exceptionSf.column);
}
});
} }
} }
private showExceptionWidget(lineNumber: number, column: number): void { private showExceptionWidget(exceptionInfo: IExceptionInfo, lineNumber: number, column: number): void {
if (this.exceptionWidget) { if (this.exceptionWidget) {
this.exceptionWidget.dispose(); this.exceptionWidget.dispose();
} }
this.exceptionWidget = this.instantiationService.createInstance(ExceptionWidget, this.editor, lineNumber); this.exceptionWidget = this.instantiationService.createInstance(ExceptionWidget, this.editor, exceptionInfo, lineNumber);
this.exceptionWidget.show({ lineNumber, column }, 0); this.exceptionWidget.show({ lineNumber, column }, 0);
} }
......
...@@ -323,6 +323,10 @@ export class RawDebugSession extends v8.V8Protocol implements debug.ISession { ...@@ -323,6 +323,10 @@ export class RawDebugSession extends v8.V8Protocol implements debug.ISession {
return this.send('stackTrace', args); return this.send('stackTrace', args);
} }
public exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse> {
return this.send('exceptionInfo', args);
}
public scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse> { public scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse> {
return this.send('scopes', args); return this.send('scopes', args);
} }
......
...@@ -120,6 +120,15 @@ export class MockSession implements debug.ISession { ...@@ -120,6 +120,15 @@ export class MockSession implements debug.ISession {
}); });
} }
public exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse> {
return TPromise.as({
body: {
exceptionId: 'mockExceptionId',
breakMode: 'unhandled'
}
});
}
public attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse> { public attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse> {
return TPromise.as(null); return TPromise.as(null);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册