Skip to content

Commit c0270c8

Browse files
authored
Merge pull request #405 from daviwil/debugger-column-number
Report column number in stack frame when debugger stops
2 parents 0439152 + b5076b0 commit c0270c8

File tree

6 files changed

+61
-15
lines changed

6 files changed

+61
-15
lines changed

src/PowerShellEditorServices.Protocol/DebugAdapter/StackFrame.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ public class StackFrame
1515

1616
public int Line { get; set; }
1717

18+
public int? EndLine { get; set; }
19+
1820
public int Column { get; set; }
1921

22+
public int? EndColumn { get; set; }
23+
2024
// /** An identifier for the stack frame. */
2125
//id: number;
2226
///** The name of the stack frame, typically a method name */
@@ -38,8 +42,10 @@ public static StackFrame Create(
3842
{
3943
Id = id,
4044
Name = stackFrame.FunctionName,
41-
Line = stackFrame.LineNumber,
42-
Column = stackFrame.ColumnNumber,
45+
Line = stackFrame.StartLineNumber,
46+
EndLine = stackFrame.EndLineNumber > 0 ? (int?)stackFrame.EndLineNumber : null,
47+
Column = stackFrame.StartColumnNumber,
48+
EndColumn = stackFrame.EndColumnNumber > 0 ? (int?)stackFrame.EndColumnNumber : null,
4349
Source = new Source
4450
{
4551
Path = stackFrame.ScriptPath

src/PowerShellEditorServices.Protocol/DebugAdapter/StoppedEvent.cs

-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ public class StoppedEventBody
2828

2929
public Source Source { get; set; }
3030

31-
public int Line { get; set; }
32-
33-
public int Column { get; set; }
34-
3531
/// <summary>
3632
/// Gets or sets additional information such as an error message.
3733
/// </summary>

src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs

-2
Original file line numberDiff line numberDiff line change
@@ -857,8 +857,6 @@ await this.SendEvent(
857857
{
858858
Path = e.ScriptPath,
859859
},
860-
Line = e.LineNumber,
861-
Column = e.ColumnNumber,
862860
ThreadId = 1,
863861
Reason = debuggerStoppedReason
864862
});

src/PowerShellEditorServices/Debugging/DebugService.cs

+24
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Management.Automation;
1010
using System.Management.Automation.Language;
11+
using System.Reflection;
1112
using System.Text;
1213
using System.Threading.Tasks;
1314
using Microsoft.PowerShell.EditorServices.Debugging;
@@ -41,6 +42,7 @@ public class DebugService
4142
private VariableContainerDetails globalScopeVariables;
4243
private VariableContainerDetails scriptScopeVariables;
4344
private StackFrameDetails[] stackFrameDetails;
45+
private PropertyInfo invocationTypeScriptPositionProperty;
4446

4547
private static int breakpointHitCounter = 0;
4648

@@ -81,6 +83,12 @@ public DebugService(
8183
this.powerShellContext.BreakpointUpdated += this.OnBreakpointUpdated;
8284

8385
this.remoteFileManager = remoteFileManager;
86+
87+
this.invocationTypeScriptPositionProperty =
88+
typeof(InvocationInfo)
89+
.GetProperty(
90+
"ScriptPosition",
91+
BindingFlags.NonPublic | BindingFlags.Instance);
8492
}
8593

8694
#endregion
@@ -1100,6 +1108,22 @@ await this.remoteFileManager.FetchRemoteFile(
11001108
this.powerShellContext.CurrentRunspace);
11011109
}
11021110

1111+
if (this.stackFrameDetails.Length > 0)
1112+
{
1113+
// Augment the top stack frame with details from the stop event
1114+
IScriptExtent scriptExtent =
1115+
this.invocationTypeScriptPositionProperty
1116+
.GetValue(e.InvocationInfo) as IScriptExtent;
1117+
1118+
if (scriptExtent != null)
1119+
{
1120+
this.stackFrameDetails[0].StartLineNumber = scriptExtent.StartLineNumber;
1121+
this.stackFrameDetails[0].EndLineNumber = scriptExtent.EndLineNumber;
1122+
this.stackFrameDetails[0].StartColumnNumber = scriptExtent.StartColumnNumber;
1123+
this.stackFrameDetails[0].EndColumnNumber = scriptExtent.EndColumnNumber;
1124+
}
1125+
}
1126+
11031127
// Notify the host that the debugger is stopped
11041128
this.DebuggerStopped?.Invoke(
11051129
sender,

src/PowerShellEditorServices/Debugging/StackFrameDetails.cs

+15-5
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,25 @@ public class StackFrameDetails
3535
/// </summary>
3636
public string FunctionName { get; private set; }
3737

38+
/// <summary>
39+
/// Gets the start line number of the script where the stack frame occurred.
40+
/// </summary>
41+
public int StartLineNumber { get; internal set; }
42+
3843
/// <summary>
3944
/// Gets the line number of the script where the stack frame occurred.
4045
/// </summary>
41-
public int LineNumber { get; private set; }
46+
public int EndLineNumber { get; internal set; }
47+
48+
/// <summary>
49+
/// Gets the start column number of the line where the stack frame occurred.
50+
/// </summary>
51+
public int StartColumnNumber { get; internal set; }
4252

4353
/// <summary>
44-
/// Gets the column number of the line where the stack frame occurred.
54+
/// Gets the end column number of the line where the stack frame occurred.
4555
/// </summary>
46-
public int ColumnNumber { get; private set; }
56+
public int EndColumnNumber { get; internal set; }
4757

4858
/// <summary>
4959
/// Gets or sets the VariableContainerDetails that contains the auto variables.
@@ -82,8 +92,8 @@ static internal StackFrameDetails Create(
8292
{
8393
ScriptPath = (callStackFrameObject.Properties["ScriptName"].Value as string) ?? NoFileScriptPath,
8494
FunctionName = callStackFrameObject.Properties["FunctionName"].Value as string,
85-
LineNumber = (int)(callStackFrameObject.Properties["ScriptLineNumber"].Value ?? 0),
86-
ColumnNumber = 0, // Column number isn't given in PowerShell stack frames
95+
StartLineNumber = (int)(callStackFrameObject.Properties["ScriptLineNumber"].Value ?? 0),
96+
StartColumnNumber = 0, // Column number isn't given in PowerShell stack frames
8797
AutoVariables = autoVariables,
8898
LocalVariables = localVariables
8999
};

test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs

+14-2
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,25 @@ await this.SendRequest(
8585
// Wait for a couple breakpoints
8686
StoppedEventBody stoppedDetails = await breakEventTask;
8787
Assert.Equal(DebugScriptPath, stoppedDetails.Source.Path);
88-
Assert.Equal(5, stoppedDetails.Line);
88+
89+
var stackTraceResponse =
90+
await this.SendRequest(
91+
StackTraceRequest.Type,
92+
new StackTraceRequestArguments());
93+
94+
Assert.Equal(5, stackTraceResponse.StackFrames[0].Line);
8995

9096
breakEventTask = this.WaitForEvent(StoppedEvent.Type);
9197
await this.SendRequest(ContinueRequest.Type, new object());
9298
stoppedDetails = await breakEventTask;
9399
Assert.Equal(DebugScriptPath, stoppedDetails.Source.Path);
94-
Assert.Equal(7, stoppedDetails.Line);
100+
101+
stackTraceResponse =
102+
await this.SendRequest(
103+
StackTraceRequest.Type,
104+
new StackTraceRequestArguments());
105+
106+
Assert.Equal(7, stackTraceResponse.StackFrames[0].Line);
95107

96108
// Abort script execution
97109
await this.SendRequest(DisconnectRequest.Type, new object());

0 commit comments

Comments
 (0)