Closed
Description
When we receive a 'stopped' event with a reason of 'exception', we need additional information about the exception that has occurred.
Information we need in order to support VS scenarios:
- Exception ID (e.g. "CLR/System.ArgumentException")
- Exception Break Mode (the mode set for the exception that caused us to enter break mode, e.g. if an exception type's mode has been set to "always", the UI may differentiate between an exception that was caught vs uncaught by sending, respectively, "always" or "unhandled")
- Description (explanatory text provided by the debug adapter, e.g. "An unhandled exception of type 'System.ArgumentNullException' occurred in ConsoleApp1.exe\nValue cannot be null.")
- Error Code (Win32 exceptions, for instance, are identified by a code, e.g. 0xC0000005)
- Optional details, consisting of:
- Inner Exception (if this exception wraps another exception)
- Object Expression (expression that can be evaluated to obtain the actual exception object, e.g. "$exception")
- Formatted Description (Descriptive text shown in the UI that allows simple formatting, e.g.
"**System.ArgumentNullException:** 'Value cannot be null\.'"
- Type Name (Short name of the exception type, e.g. "ArgumentNullException")
- Full Type Name (Full name of the exception type, e.g. "System.ArgumentNullException")
- HResult (COM-style error code often associated with CLR exceptions)
- Source (The name of the application that threw the exception)
- Stack Trace (The stack trace at the point when the exception was thrown. May not be the current stack trace, e.g. if an exception type with an ExceptionBreakMode of 'uncaught' was caught and rethrown, and the rethrown exception was not caught)
This seems like functionality that would be broadly useful for anyone who wants to participate in the new exception experience enabled by #64.
Proposed protocol extension (implemented and verified in the VS debug adapter host):
export interface InitializeRequestArguments {
// ...
/** Client supports the exceptionInfo request. */
supportsExceptionInfoRequest?: boolean;
// ...
}
/** Retrieves the details of the exception that caused the StoppedEvent to be raised. */
export interface ExceptionInfoRequest extends Request {
// command: 'exceptionInfo';
arguments: ExceptionInfoArguments;
}
/** Arguments for 'exceptionInfo' request. */
export interface ExceptionInfoArguments {
/** Thread for which exception information should be retrieved. */
threadId: number;
}
/** Response to 'exceptionInfo' request. */
export interface ExceptionInfoResponse extends Response {
body?: {
/** ID of the exception that was thrown. */
exceptionId: string;
/** Mode that caused the exception notification to be raised. */
breakMode: ExceptionBreakMode;
/** Descriptive text for the exception provided by the debug adapter. */
description?: string;
/** Numeric code for the exception provided by the debug adapter, if any. */
code?: number;
/** Detailed information about the exception. */
details?: ExceptionDetails;
};
}
/** Detailed information about an exception that has occurred */
export interface ExceptionDetails {
/** Message contained in the exception. */
message?: string;
/** Property that can be evaluated in the current scope to obtain the exception object. */
objectExpression?: string;
/** Formatted description of the exception. */
formattedDescription?: string;
/** Type name of the exception object. */
typeName?: string;
/** Result code of the exception. */
hresult?: number;
/** Name of the object or application that raised the exception. */
source?: string;
/** Fully-qualified type name of the exception object. */
fullTypeName?: string;
/** Stack trace at the time the exception was thrown. */
stackTrace?: string;
/** Details of the exception contained by this exception, if any. */
innerException?: ExceptionDetails;
}
Namedrops: @jacdavis @gregg-miskelly @richardstanton @tzwlai @WardenGnaw