Repository: microsoft/ptvsd

Issue:
Exception information not available when breaking on 'Raised Exceptions'
The exception information (name, type) is not available when breaking on exceptions.
Exception message needs to be returned in the `text` property of the `stopped` event.

See here:
https://github.com/Microsoft/vscode-debugadapter-node/blob/master/protocol/src/debugProtocol.ts#L88


Discussion:
Is this a new issue or regression?
I came across this last week, but assumed it was caused by #117.
After further research I've learnt that not to be the case, as mentioned above, `text` needs to be returned. However getting this `exception information` is no trivial task.

From what I can see following methods aren't being invoked (for unhandled exceptions). I guess you already know this.

```python
    @pydevd_events.handler(pydevd_comm.CMD_SEND_CURR_EXCEPTION_TRACE)
    def on_pydevd_send_curr_exception_trace(self, seq, args):

    @pydevd_events.handler(pydevd_comm.CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED)
```

Expected behavior: (modified PTVSD, but does not work for unhandled exceptions).

![errorinfo](https://user-images.githubusercontent.com/1948812/36821634-be215486-1ca8-11e8-8815-60e7da82338e.gif)


Resolving patch:
diff --git a/ptvsd/wrapper.py b/ptvsd/wrapper.py
--- a/ptvsd/wrapper.py
+++ b/ptvsd/wrapper.py
@@ -850,21 +850,26 @@ def on_setExceptionBreakpoints(self, request, args):
     def on_exceptionInfo(self, request, args):
         # TODO: docstring
         tid = self.thread_map.to_pydevd(args['threadId'])
+        name, description = self.get_exceptionInfo(tid)
+        self.send_response(
+            request,
+            exceptionId=name,
+            description=description,
+            breakMode=self.exceptions_mgr.get_break_mode(name),
+            details={'typeName': name,
+                     'message': description},
+        )
+
+    def get_exceptionInfo(self, pyd_tid):
+        """Gets the exception name and description for the given PyDev Thread id"""
         with self.active_exceptions_lock:
             try:
-                exc = self.active_exceptions[tid]
+                exc = self.active_exceptions[pyd_tid]
             except KeyError:
                 exc = ExceptionInfo('BaseException',
                                     'exception: no description')
-        self.send_response(
-            request,
-            exceptionId=exc.name,
-            description=exc.description,
-            breakMode=self.exceptions_mgr.get_break_mode(exc.name),
-            details={'typeName': exc.name,
-                     'message': exc.description},
-        )
-
+        return (exc.name, exc.description)
+        
     @pydevd_events.handler(pydevd_comm.CMD_THREAD_CREATE)
     def on_pydevd_thread_create(self, seq, args):
         # TODO: docstring
@@ -910,11 +915,14 @@ def on_pydevd_thread_suspend(self, seq, args):
             vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
         except KeyError:
             return
-
+        
+        text = None
         if reason in STEP_REASONS:
             reason = 'step'
         elif reason in EXCEPTION_REASONS:
             reason = 'exception'
+            name, description = self.get_exceptionInfo(pyd_tid)
+            text = '{}, {}'.format(name, description)
         elif reason == pydevd_comm.CMD_SET_BREAK:
             reason = 'breakpoint'
         else:
@@ -923,7 +931,7 @@ def on_pydevd_thread_suspend(self, seq, args):
         with self.stack_traces_lock:
             self.stack_traces[pyd_tid] = xml.thread.frame
         
-        self.send_event('stopped', reason=reason, threadId=vsc_tid)
+        self.send_event('stopped', reason=reason, threadId=vsc_tid, text=text)
 
     @pydevd_events.handler(pydevd_comm.CMD_THREAD_RUN)
     def on_pydevd_thread_run(self, seq, args):


Test patch: