Browse Source

Show only variables in scope

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5248 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
David Srbecký 16 years ago
parent
commit
8a0dc0ba3e
  1. 2
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
  2. 2
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  3. 8
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs
  4. 40
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
  5. 9
      src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs
  6. 4
      src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs
  7. 23
      src/AddIns/Debugger/Debugger.Core/StackFrame.cs
  8. 4
      src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj
  9. 11
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  10. 6
      src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs
  11. 10
      src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs
  12. 8
      src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs
  13. 115
      src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs
  14. 2
      src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs

2
src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs

@ -31,7 +31,7 @@ namespace Debugger.AddIn.TreeModel @@ -31,7 +31,7 @@ namespace Debugger.AddIn.TreeModel
foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) {
yield return new ExpressionNode(ExpressionNode.GetImageForParameter(), par.Name, par.GetExpression());
}
foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables()) {
foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) {
yield return new ExpressionNode(ExpressionNode.GetImageForLocalVariable(), locVar.Name, locVar.GetExpression());
}
if (stackFrame.Thread.CurrentException != null) {

2
src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs

@ -140,7 +140,7 @@ namespace Debugger @@ -140,7 +140,7 @@ namespace Debugger
process.TraceMessage(" - ignored");
} else if (thread.CurrentStepIn != null &&
thread.CurrentStepIn.StackFrame.Equals(currentStackFrame) &&
thread.CurrentStepIn.IsInStepRanges((int)currentStackFrame.CorInstructionPtr)) {
thread.CurrentStepIn.IsInStepRanges((int)currentStackFrame.IP)) {
Stepper.StepIn(currentStackFrame, thread.CurrentStepIn.StepRanges, "finishing step in");
process.TraceMessage(" - finishing step in");
} else if (currentStackFrame.MethodInfo.StepOver) {

8
src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs

@ -31,13 +31,19 @@ namespace Debugger.MetaData @@ -31,13 +31,19 @@ namespace Debugger.MetaData
}
public string Name { get; internal set; }
/// <summary> IL offset of the start of the variable scope (inclusive) </summary>
public int StartOffset { get; private set; }
/// <summary> IL offset of the end of the variable scope (exclusive) </summary>
public int EndOffset { get; private set; }
public bool IsThis { get; internal set; }
public bool IsCaptured { get; internal set; }
public DebugLocalVariableInfo(string name, int localIndex, DebugType localType, ValueGetter getter)
public DebugLocalVariableInfo(string name, int localIndex, int startOffset, int endOffset, DebugType localType, ValueGetter getter)
{
this.Name = name;
this.localIndex = localIndex;
this.StartOffset = startOffset;
this.EndOffset = endOffset;
this.localType = localType;
this.getter = getter;
}

40
src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs

@ -443,30 +443,51 @@ namespace Debugger.MetaData @@ -443,30 +443,51 @@ namespace Debugger.MetaData
}
}
public DebugLocalVariableInfo GetLocalVariable(string name)
public DebugLocalVariableInfo GetLocalVariable(int offset, string name)
{
foreach(DebugLocalVariableInfo loc in GetLocalVariables()) {
foreach(DebugLocalVariableInfo loc in GetLocalVariables(offset)) {
if (loc.Name == name)
return loc;
}
return null;
}
[Debugger.Tests.Ignore]
public DebugLocalVariableInfo GetLocalVariableThis()
{
foreach(DebugLocalVariableInfo loc in GetLocalVariables()) {
if (loc.IsThis)
return loc;
}
return null;
}
/// <summary> Get local variables valid at the given IL offset </summary>
public IEnumerable<DebugLocalVariableInfo> GetLocalVariables(int offset)
{
foreach (DebugLocalVariableInfo varInfo in GetLocalVariables()) {
if (varInfo.StartOffset <= offset && offset < varInfo.EndOffset) {
yield return varInfo;
}
}
}
List<DebugLocalVariableInfo> localVariables;
public List<DebugLocalVariableInfo> GetLocalVariables()
{
if (localVariables != null) return localVariables;
// Generated constructor may not have any symbols
if (this.SymMethod == null)
return new List<DebugLocalVariableInfo>();
if (localVariables != null) return localVariables;
localVariables = GetLocalVariablesInScope(this.SymMethod.GetRootScope());
if (declaringType.IsDisplayClass || declaringType.IsYieldEnumerator) {
// Get display class from self
AddCapturedLocalVariables(
localVariables,
0, int.MaxValue,
delegate(StackFrame context) {
return context.GetThisValue();
},
@ -478,6 +499,7 @@ namespace Debugger.MetaData @@ -478,6 +499,7 @@ namespace Debugger.MetaData
if (fieldInfo.Name.StartsWith("CS$")) {
AddCapturedLocalVariables(
localVariables,
0, int.MaxValue,
delegate(StackFrame context) {
return context.GetThisValue().GetFieldValue(fieldInfoCopy);
},
@ -491,6 +513,7 @@ namespace Debugger.MetaData @@ -491,6 +513,7 @@ namespace Debugger.MetaData
DebugLocalVariableInfo thisVar = new DebugLocalVariableInfo(
"this",
-1,
0, int.MaxValue,
declaringType,
delegate(StackFrame context) {
return context.GetThisValue();
@ -503,7 +526,7 @@ namespace Debugger.MetaData @@ -503,7 +526,7 @@ namespace Debugger.MetaData
return localVariables;
}
static void AddCapturedLocalVariables(List<DebugLocalVariableInfo> vars, ValueGetter getCaptureClass, DebugType captureClassType)
static void AddCapturedLocalVariables(List<DebugLocalVariableInfo> vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType)
{
if (captureClassType.IsDisplayClass || captureClassType.IsYieldEnumerator) {
foreach(DebugFieldInfo fieldInfo in captureClassType.GetFields()) {
@ -512,6 +535,8 @@ namespace Debugger.MetaData @@ -512,6 +535,8 @@ namespace Debugger.MetaData
DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
fieldInfo.Name,
-1,
scopeStartOffset,
scopeEndOffset,
(DebugType)fieldInfo.FieldType,
delegate(StackFrame context) {
return getCaptureClass(context).GetFieldValue(fieldInfoCopy);
@ -559,6 +584,8 @@ namespace Debugger.MetaData @@ -559,6 +584,8 @@ namespace Debugger.MetaData
if (locVarType.IsDisplayClass) {
AddCapturedLocalVariables(
vars,
(int)symScope.GetStartOffset(),
(int)symScope.GetEndOffset(),
delegate(StackFrame context) {
return GetLocalVariableValue(context, symVarCopy);
},
@ -569,6 +596,9 @@ namespace Debugger.MetaData @@ -569,6 +596,9 @@ namespace Debugger.MetaData
DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
symVar.GetName(),
(int)symVar.GetAddressField1(),
// symVar also has Get*Offset methods, but the are not implemented
(int)symScope.GetStartOffset(),
(int)symScope.GetEndOffset(),
locVarType,
delegate(StackFrame context) {
return GetLocalVariableValue(context, symVarCopy);

9
src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs

@ -392,7 +392,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -392,7 +392,7 @@ namespace ICSharpCode.NRefactory.Visitors
if (par != null)
return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType);
DebugLocalVariableInfo loc = context.MethodInfo.GetLocalVariable(identifier);
DebugLocalVariableInfo loc = context.MethodInfo.GetLocalVariable(context.IP, identifier);
if (loc != null)
return new TypedValue(loc.GetValue(context), (DebugType)loc.LocalType);
@ -562,10 +562,9 @@ namespace ICSharpCode.NRefactory.Visitors @@ -562,10 +562,9 @@ namespace ICSharpCode.NRefactory.Visitors
TypedValue GetThisValue()
{
// This is needed so that captured 'this' is supported
foreach(DebugLocalVariableInfo locVar in context.MethodInfo.GetLocalVariables()) {
if (locVar.IsThis)
return new TypedValue(locVar.GetValue(context), (DebugType)locVar.LocalType);
}
DebugLocalVariableInfo thisVar = context.MethodInfo.GetLocalVariableThis();
if (thisVar != null)
return new TypedValue(thisVar.GetValue(context), (DebugType)thisVar.LocalType);
return null;
}

4
src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs

@ -232,7 +232,7 @@ namespace Debugger @@ -232,7 +232,7 @@ namespace Debugger
/// 'ILStart &lt;= ILOffset &lt;= ILEnd' and this range includes at least
/// the returned area of source code. (May incude some extra compiler generated IL too)
/// </summary>
internal static SourcecodeSegment Resolve(Module module, ICorDebugFunction corFunction, uint offset)
internal static SourcecodeSegment Resolve(Module module, ICorDebugFunction corFunction, int offset)
{
ISymUnmanagedReader symReader = module.SymReader;
if (symReader == null) return null; // No symbols
@ -253,7 +253,7 @@ namespace Debugger @@ -253,7 +253,7 @@ namespace Debugger
// Get i for which: offsets[i] <= offset < offsets[i + 1]
// or fallback to first element if offset < offsets[0]
for (int i = (int)sequencePointCount - 1; i >= 0; i--) { // backwards
if (sequencePoints[i].Offset <= offset || i == 0) {
if ((int)sequencePoints[i].Offset <= offset || i == 0) {
// Set inforamtion about current IL range
int codeSize = (int)corFunction.GetILCode().GetSize();

23
src/AddIns/Debugger/Debugger.Core/StackFrame.cs

@ -133,16 +133,17 @@ namespace Debugger @@ -133,16 +133,17 @@ namespace Debugger
}
}
internal uint CorInstructionPtr {
[Debugger.Tests.Ignore]
public int IP {
get {
uint corInstructionPtr;
CorDebugMappingResult mappingResult;
CorILFrame.GetIP(out corInstructionPtr, out mappingResult);
return corInstructionPtr;
return (int)corInstructionPtr;
}
}
SourcecodeSegment GetSegmentForOffet(uint offset)
SourcecodeSegment GetSegmentForOffet(int offset)
{
return SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, corFunction, offset);
}
@ -232,7 +233,7 @@ namespace Debugger @@ -232,7 +233,7 @@ namespace Debugger
/// </summary>
public SourcecodeSegment NextStatement {
get {
return GetSegmentForOffet(CorInstructionPtr);
return GetSegmentForOffet(IP);
}
}
@ -282,6 +283,8 @@ namespace Debugger @@ -282,6 +283,8 @@ namespace Debugger
/// <summary>
/// Gets the instance of the class asociated with the current frame.
/// That is, 'this' in C#.
/// Note that for delegates and enumerators this returns the instance of the display class.
/// The get the captured this, use GetLocalVariableThis.
/// </summary>
[Debugger.Tests.Ignore]
public Value GetThisValue()
@ -367,12 +370,22 @@ namespace Debugger @@ -367,12 +370,22 @@ namespace Debugger
/// <returns> Null if not found </returns>
public Value GetLocalVariableValue(string name)
{
DebugLocalVariableInfo loc = this.MethodInfo.GetLocalVariable(name);
DebugLocalVariableInfo loc = this.MethodInfo.GetLocalVariable(this.IP, name);
if (loc == null)
return null;
return loc.GetValue(this);
}
/// <summary> Get instance of 'this'. It works well with delegates and enumerators. </summary>
[Debugger.Tests.Ignore]
public Value GetLocalVariableThis()
{
DebugLocalVariableInfo thisVar = this.MethodInfo.GetLocalVariableThis();
if (thisVar != null)
return thisVar.GetValue(this);
return null;
}
public override bool Equals(object obj)
{
StackFrame other = obj as StackFrame;

4
src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>Debugger.Tests</RootNamespace>
@ -55,6 +56,7 @@ @@ -55,6 +56,7 @@
<Compile Include="Tests\DebugType_Tests.cs" />
<Compile Include="Tests\Exception_Custom.cs" />
<Compile Include="Tests\StackFrame_Lifetime.cs" />
<Compile Include="Tests\StackFrame_Tests.cs" />
<Compile Include="Tests\StackFrame_VariablesLifetime.cs" />
<Compile Include="Tests\_HelloWorldTest.cs" />
<Compile Include="Tests\ControlFlow_MainThreadExit.cs" />

11
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -35,6 +35,17 @@ namespace Debugger.Tests @@ -35,6 +35,17 @@ namespace Debugger.Tests
protected XmlElement snapshotNode;
protected int shapshotID;
public StackFrame SelectedStackFrame {
get {
return process.SelectedStackFrame;
}
}
public void Continue()
{
process.Continue();
}
[TestFixtureSetUp]
public virtual void TestFixtureSetUp()
{

6
src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs

@ -73,11 +73,11 @@ namespace Debugger.Tests { @@ -73,11 +73,11 @@ namespace Debugger.Tests {
public void DebugType_CompilerGeneratedClasses()
{
StartTest();
PrintLocalVariables("YieldLocalVariables");
DumpLocalVariables("YieldLocalVariables");
process.Continue();
PrintLocalVariables("OutterDelegateLocalVariables");
DumpLocalVariables("OutterDelegateLocalVariables");
process.Continue();
PrintLocalVariables("InnterDelegateLocalVariables");
DumpLocalVariables("InnterDelegateLocalVariables");
Eval("nestedDelegArg");
Eval("instanceField");
Eval("staticField");

10
src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs

@ -188,16 +188,16 @@ namespace Debugger.Tests { @@ -188,16 +188,16 @@ namespace Debugger.Tests {
public Value Value { get; set; }
}
void PrintLocalVariables()
void DumpLocalVariables()
{
PrintLocalVariables("LocalVariables");
DumpLocalVariables("LocalVariables");
}
void PrintLocalVariables(string msg)
void DumpLocalVariables(string msg)
{
ObjectDump(
msg,
process.SelectedStackFrame.MethodInfo.GetLocalVariables().Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(process.SelectedStackFrame) })
SelectedStackFrame.MethodInfo.GetLocalVariables(SelectedStackFrame.IP).Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(process.SelectedStackFrame)})
);
}
@ -219,7 +219,7 @@ namespace Debugger.Tests { @@ -219,7 +219,7 @@ namespace Debugger.Tests {
ObjectDump("Members", process.SelectedStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared));
ObjectDump("Access-Members", process.SelectedStackFrame.GetLocalVariableValue("access").Type.GetMembers());
ObjectDump("MyInterfaceImpl-Members", process.SelectedStackFrame.GetLocalVariableValue("myInterfaceImpl").Type.GetMembers());
PrintLocalVariables();
DumpLocalVariables();
EndTest();
}

8
src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs

@ -208,8 +208,8 @@ namespace Debugger.Tests { @@ -208,8 +208,8 @@ namespace Debugger.Tests {
// Test member hiding / overloading
Value myClass = process.SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference();
Expression myClassExpr = process.SelectedStackFrame.MethodInfo.GetLocalVariable("myClass").GetExpression();
Value myClass = SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference();
Expression myClassExpr = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "myClass").GetExpression();
List<Expression> expressions = new List<Expression>();
foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) {
@ -254,9 +254,9 @@ namespace Debugger.Tests { @@ -254,9 +254,9 @@ namespace Debugger.Tests {
// Type equality
DebugLocalVariableInfo loc = process.SelectedStackFrame.MethodInfo.GetLocalVariable("list");
DebugLocalVariableInfo loc = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "list");
Type locType = loc.LocalType;
Type valType = loc.GetValue(process.SelectedStackFrame).Type;
Type valType = loc.GetValue(SelectedStackFrame).Type;
ObjectDump("TypesIdentitcal", object.ReferenceEquals(locType, valType));
ObjectDump("TypesEqual", locType == valType);

115
src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger.Tests
{
public class StackFrame_Tests
{
public static void Main()
{
for (int i = 10; i < 11; i++) {
System.Diagnostics.Debugger.Break();
}
for (short i = 20; i < 21; i++) {
System.Diagnostics.Debugger.Break();
}
System.Diagnostics.Debugger.Break();
int j = 30;
System.Diagnostics.Debugger.Break();
}
}
}
#if TEST_CODE
namespace Debugger.Tests {
public partial class DebuggerTests
{
[NUnit.Framework.Test]
public void StackFrame_Tests()
{
StartTest();
// Test scoping
DumpLocalVariables("Loop1");
Continue();
DumpLocalVariables("Loop2");
Continue();
DumpLocalVariables("None");
Continue();
DumpLocalVariables("NewVarDefined");
EndTest();
}
}
}
#endif
#if EXPECTED_OUTPUT
<?xml version="1.0" encoding="utf-8"?>
<DebuggerTests>
<Test
name="StackFrame_Tests.cs">
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>StackFrame_Tests.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break StackFrame_Tests.cs:17,5-17,41</DebuggingPaused>
<Loop1>
<Item>
<LocalVariable
Name="j"
Type="System.Int32"
Value="0" />
</Item>
<Item>
<LocalVariable
Name="i"
Type="System.Int32"
Value="10" />
</Item>
</Loop1>
<DebuggingPaused>Break StackFrame_Tests.cs:20,5-20,41</DebuggingPaused>
<Loop2>
<Item>
<LocalVariable
Name="j"
Type="System.Int32"
Value="0" />
</Item>
<Item>
<LocalVariable
Name="i"
Type="System.Int16"
Value="20" />
</Item>
</Loop2>
<DebuggingPaused>Break StackFrame_Tests.cs:23,4-23,40</DebuggingPaused>
<None>
<Item>
<LocalVariable
Name="j"
Type="System.Int32"
Value="0" />
</Item>
</None>
<DebuggingPaused>Break StackFrame_Tests.cs:27,4-27,40</DebuggingPaused>
<NewVarDefined>
<Item>
<LocalVariable
Name="j"
Type="System.Int32"
Value="30" />
</Item>
</NewVarDefined>
<ProcessExited />
</Test>
</DebuggerTests>
#endif // EXPECTED_OUTPUT

2
src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs

@ -42,7 +42,7 @@ namespace Debugger.Tests { @@ -42,7 +42,7 @@ namespace Debugger.Tests {
{
StartTest();
PrintLocalVariables();
DumpLocalVariables();
Value array = process.SelectedStackFrame.GetLocalVariableValue("array").GetPermanentReference();
ObjectDump("array.Length", array.GetMemberValue("Length"));

Loading…
Cancel
Save