22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33
44using System ;
5+ using System . Collections . Concurrent ;
56using System . Collections . Generic ;
67using System . Diagnostics ;
78using System . Globalization ;
2728
2829namespace OpenDebugAD7
2930{
30- internal class AD7DebugSession : DebugAdapterBase , IDebugPortNotify2 , IDebugEventCallback2
31+ internal sealed class AD7DebugSession : DebugAdapterBase , IDebugPortNotify2 , IDebugEventCallback2
3132 {
3233 // This is a general purpose lock. Don't hold it across long operations.
3334 private readonly object m_lock = new object ( ) ;
@@ -44,6 +45,10 @@ internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEven
4445
4546 private readonly DebugEventLogger m_logger ;
4647 private readonly Dictionary < string , Dictionary < int , IDebugPendingBreakpoint2 > > m_breakpoints ;
48+
49+ private readonly ConcurrentDictionary < int , IDebugCodeContext2 > m_gotoCodeContexts = new ConcurrentDictionary < int , IDebugCodeContext2 > ( ) ;
50+ private int m_nextContextId = 1 ;
51+
4752 private Dictionary < string , IDebugPendingBreakpoint2 > m_functionBreakpoints ;
4853 private readonly HandleCollection < IDebugStackFrame2 > m_frameHandles ;
4954
@@ -350,6 +355,7 @@ public void BeforeContinue()
350355 m_isStopped = false ;
351356 m_variableManager . Reset ( ) ;
352357 m_frameHandles . Reset ( ) ;
358+ m_gotoCodeContexts . Clear ( ) ;
353359 }
354360
355361 public void Stopped ( IDebugThread2 thread )
@@ -793,6 +799,7 @@ protected override void HandleInitializeRequestAsync(IRequestResponder<Initializ
793799 SupportsReadMemoryRequest = m_engine is IDebugMemoryBytesDAP , // TODO: Read from configuration or query engine for capabilities.
794800 SupportsModulesRequest = true ,
795801 AdditionalModuleColumns = additionalModuleColumns ,
802+ SupportsGotoTargetsRequest = true ,
796803 SupportsDisassembleRequest = true ,
797804 SupportsValueFormattingOptions = true ,
798805 } ;
@@ -1317,6 +1324,86 @@ protected override void HandlePauseRequestAsync(IRequestResponder<PauseArguments
13171324 responder . SetResponse ( new PauseResponse ( ) ) ;
13181325 }
13191326
1327+ protected override void HandleGotoRequestAsync ( IRequestResponder < GotoArguments > responder )
1328+ {
1329+ responder . SetError ( new ProtocolException ( AD7Resources . Error_NotImplementedSetNextStatement ) ) ;
1330+ }
1331+
1332+ protected override void HandleGotoTargetsRequestAsync ( IRequestResponder < GotoTargetsArguments , GotoTargetsResponse > responder )
1333+ {
1334+ var response = new GotoTargetsResponse ( ) ;
1335+
1336+ var source = responder . Arguments . Source ;
1337+
1338+ // Virtual documents don't have paths
1339+ if ( source . Path == null )
1340+ {
1341+ responder . SetResponse ( response ) ;
1342+ return ;
1343+ }
1344+
1345+ try
1346+ {
1347+ string convertedPath = m_pathConverter . ConvertClientPathToDebugger ( source . Path ) ;
1348+ int line = m_pathConverter . ConvertClientLineToDebugger ( responder . Arguments . Line ) ;
1349+ var docPos = new AD7DocumentPosition ( m_sessionConfig , convertedPath , line ) ;
1350+
1351+ var targets = new List < GotoTarget > ( ) ;
1352+
1353+ IEnumDebugCodeContexts2 codeContextsEnum ;
1354+ if ( m_program . EnumCodeContexts ( docPos , out codeContextsEnum ) == HRConstants . S_OK )
1355+ {
1356+ var codeContexts = new IDebugCodeContext2 [ 1 ] ;
1357+ uint nProps = 0 ;
1358+ while ( codeContextsEnum . Next ( 1 , codeContexts , ref nProps ) == HRConstants . S_OK )
1359+ {
1360+ var codeContext = codeContexts [ 0 ] ;
1361+
1362+ string contextName ;
1363+ codeContext . GetName ( out contextName ) ;
1364+
1365+ line = responder . Arguments . Line ;
1366+ IDebugDocumentContext2 documentContext ;
1367+ if ( codeContext . GetDocumentContext ( out documentContext ) == HRConstants . S_OK )
1368+ {
1369+ var startPos = new TEXT_POSITION [ 1 ] ;
1370+ var endPos = new TEXT_POSITION [ 1 ] ;
1371+ if ( documentContext . GetStatementRange ( startPos , endPos ) == HRConstants . S_OK )
1372+ line = m_pathConverter . ConvertDebuggerLineToClient ( ( int ) startPos [ 0 ] . dwLine ) ;
1373+ }
1374+
1375+ string instructionPointerReference = null ;
1376+ CONTEXT_INFO [ ] contextInfo = new CONTEXT_INFO [ 1 ] ;
1377+ if ( codeContext . GetInfo ( enum_CONTEXT_INFO_FIELDS . CIF_ADDRESS , contextInfo ) == HRConstants . S_OK &&
1378+ contextInfo [ 0 ] . dwFields . HasFlag ( enum_CONTEXT_INFO_FIELDS . CIF_ADDRESS ) )
1379+ {
1380+ instructionPointerReference = contextInfo [ 0 ] . bstrAddress ;
1381+ }
1382+
1383+ int codeContextId = m_nextContextId ++ ;
1384+ m_gotoCodeContexts . TryAdd ( codeContextId , codeContext ) ;
1385+
1386+ targets . Add ( new GotoTarget ( )
1387+ {
1388+ Id = codeContextId ,
1389+ Label = contextName ,
1390+ Line = line ,
1391+ InstructionPointerReference = instructionPointerReference
1392+ } ) ;
1393+ }
1394+ }
1395+
1396+ response . Targets = targets ;
1397+ }
1398+ catch ( AD7Exception e )
1399+ {
1400+ responder . SetError ( new ProtocolException ( e . Message ) ) ;
1401+ return ;
1402+ }
1403+
1404+ responder . SetResponse ( response ) ;
1405+ }
1406+
13201407 protected override void HandleStackTraceRequestAsync ( IRequestResponder < StackTraceArguments , StackTraceResponse > responder )
13211408 {
13221409 int threadReference = responder . Arguments . ThreadId ;
0 commit comments