Browse Source

Support for local variables captured by yield

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5095 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
98377f4d0f
  1. 7
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
  2. 66
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs
  3. 5
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugType.cs
  4. 20
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugType_CompilerGeneratedClasses.cs
  5. 19
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Expressions.cs

7
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs

@ -399,7 +399,12 @@ namespace Debugger
public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
{ {
return context.GetThisValue(); // This is needed so that captured 'this' is supported
foreach(LocalVariableInfo locVar in context.MethodInfo.LocalVariables) {
if (locVar.IsThis)
return locVar.GetValue(context);
}
throw new GetValueException(context.MethodInfo.FullName + " does not have \"this\"");
} }
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)

66
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs

@ -453,57 +453,82 @@ namespace Debugger.MetaData
if (localVariables != null) return localVariables; if (localVariables != null) return localVariables;
localVariables = GetLocalVariablesInScope(this.SymMethod.RootScope); localVariables = GetLocalVariablesInScope(this.SymMethod.RootScope);
if (!this.IsStatic && this.DeclaringType.IsDisplayClass) { if (this.DeclaringType.IsDisplayClass || this.DeclaringType.IsYieldEnumerator) {
// Get display class from self // Get display class from self
localVariables.AddRange(GetLocalVariablesFromDisplayClass( AddCapturedLocalVariables(
localVariables,
delegate(StackFrame context) { delegate(StackFrame context) {
return context.GetThisValue(); return context.GetThisValue();
}, },
this.DeclaringType this.DeclaringType
)); );
// Get dispaly classes from fields // Get dispaly classes from fields
foreach(FieldInfo fieldInfo in this.DeclaringType.GetFields()) { foreach(FieldInfo fieldInfo in this.DeclaringType.GetFields()) {
FieldInfo fieldInfoCopy = fieldInfo; FieldInfo fieldInfoCopy = fieldInfo;
if (fieldInfo.Name.StartsWith("CS$")) { if (fieldInfo.Name.StartsWith("CS$")) {
localVariables.AddRange(GetLocalVariablesFromDisplayClass( AddCapturedLocalVariables(
localVariables,
delegate(StackFrame context) { delegate(StackFrame context) {
return context.GetThisValue().GetFieldValue(fieldInfoCopy); return context.GetThisValue().GetFieldValue(fieldInfoCopy);
}, },
fieldInfo.Type fieldInfo.Type
)); );
} }
} }
} else {
// Add this
if (!this.IsStatic) {
LocalVariableInfo thisVar = new LocalVariableInfo(
"this",
this.DeclaringType,
delegate(StackFrame context) {
return context.GetThisValue();
}
);
thisVar.IsThis = true;
localVariables.Add(thisVar);
} }
if (this.DeclaringType.IsYieldEnumerator) {
} }
return localVariables; return localVariables;
} }
List<LocalVariableInfo> GetLocalVariablesFromDisplayClass(ValueGetter getDisplayClass, DebugType displayClassType) static void AddCapturedLocalVariables(List<LocalVariableInfo> vars, ValueGetter getCaptureClass, DebugType captureClassType)
{ {
List<LocalVariableInfo> vars = new List<LocalVariableInfo>(); if (captureClassType.IsDisplayClass || captureClassType.IsYieldEnumerator) {
if (displayClassType.IsDisplayClass) { foreach(FieldInfo fieldInfo in captureClassType.GetFields()) {
foreach(FieldInfo fieldInfo in displayClassType.GetFields()) {
FieldInfo fieldInfoCopy = fieldInfo; FieldInfo fieldInfoCopy = fieldInfo;
if (!fieldInfo.Name.StartsWith("CS$")) { if (fieldInfo.Name.StartsWith("CS$")) continue; // Ignore
LocalVariableInfo locVar = new LocalVariableInfo( LocalVariableInfo locVar = new LocalVariableInfo(
fieldInfo.Name, fieldInfo.Name,
fieldInfo.Type, fieldInfo.Type,
delegate(StackFrame context) { delegate(StackFrame context) {
return getDisplayClass(context).GetFieldValue(fieldInfoCopy); return getCaptureClass(context).GetFieldValue(fieldInfoCopy);
} }
); );
locVar.IsCapturedByDelegate = true; locVar.IsCaptured = true;
if (fieldInfo.Name.StartsWith("<>") && fieldInfo.Name.EndsWith("__this")) { if (locVar.Name.StartsWith("<>")) {
bool hasThis = false;
foreach(LocalVariableInfo l in vars) {
if (l.IsThis) {
hasThis = true;
break;
}
}
if (!hasThis && locVar.Name.EndsWith("__this")) {
locVar.Name = "this"; locVar.Name = "this";
locVar.IsThis = true; locVar.IsThis = true;
} else {
continue; // Ignore
} }
vars.Add(locVar);
} }
if (locVar.Name.StartsWith("<")) {
int endIndex = locVar.Name.IndexOf('>');
if (endIndex == -1) continue; // Ignore
locVar.Name = fieldInfo.Name.Substring(1, endIndex - 1);
}
vars.Add(locVar);
} }
} }
return vars;
} }
List<LocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope) List<LocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope)
@ -520,12 +545,13 @@ namespace Debugger.MetaData
if ((symVar.Attributes & 1) == 1 || symVar.Name.StartsWith("CS$")) { if ((symVar.Attributes & 1) == 1 || symVar.Name.StartsWith("CS$")) {
// Get display class from local variable // Get display class from local variable
if (locVarType.IsDisplayClass) { if (locVarType.IsDisplayClass) {
vars.AddRange(GetLocalVariablesFromDisplayClass( AddCapturedLocalVariables(
vars,
delegate(StackFrame context) { delegate(StackFrame context) {
return GetLocalVariableValue(context, symVarCopy); return GetLocalVariableValue(context, symVarCopy);
}, },
locVarType locVarType
)); );
} }
} else { } else {
LocalVariableInfo locVar = new LocalVariableInfo( LocalVariableInfo locVar = new LocalVariableInfo(
@ -566,7 +592,7 @@ namespace Debugger.MetaData
public string Name { get; internal set; } public string Name { get; internal set; }
public DebugType Type { get; private set; } public DebugType Type { get; private set; }
public bool IsThis { get; internal set; } public bool IsThis { get; internal set; }
public bool IsCapturedByDelegate { get; internal set; } public bool IsCaptured { get; internal set; }
public LocalVariableInfo(string name, DebugType type, ValueGetter getter) public LocalVariableInfo(string name, DebugType type, ValueGetter getter)
{ {

5
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugType.cs

@ -298,6 +298,7 @@ namespace Debugger.Tests {
FullName="Access.get_publicProperty" FullName="Access.get_publicProperty"
IsPublic="True" IsPublic="True"
IsSpecialName="True" IsSpecialName="True"
LocalVariableNames="{this}"
Module="DebugType.exe" Module="DebugType.exe"
Name="get_publicProperty" Name="get_publicProperty"
ReturnType="System.Int32" /> ReturnType="System.Int32" />
@ -307,6 +308,7 @@ namespace Debugger.Tests {
DeclaringType="Access" DeclaringType="Access"
FullName="Access.publicMethod" FullName="Access.publicMethod"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="DebugType.exe" Module="DebugType.exe"
Name="publicMethod" /> Name="publicMethod" />
</Item> </Item>
@ -316,6 +318,7 @@ namespace Debugger.Tests {
FullName="Access..ctor" FullName="Access..ctor"
IsPublic="True" IsPublic="True"
IsSpecialName="True" IsSpecialName="True"
LocalVariableNames="{this}"
Module="DebugType.exe" Module="DebugType.exe"
Name=".ctor" /> Name=".ctor" />
</Item> </Item>
@ -348,6 +351,7 @@ namespace Debugger.Tests {
FullName="MyInterfaceImpl&lt;System.Int32&gt;.get_Prop" FullName="MyInterfaceImpl&lt;System.Int32&gt;.get_Prop"
IsPublic="True" IsPublic="True"
IsSpecialName="True" IsSpecialName="True"
LocalVariableNames="{this}"
Module="DebugType.exe" Module="DebugType.exe"
Name="get_Prop" Name="get_Prop"
ReturnType="System.Collections.Generic.List&lt;System.Int32&gt;" /> ReturnType="System.Collections.Generic.List&lt;System.Int32&gt;" />
@ -357,6 +361,7 @@ namespace Debugger.Tests {
DeclaringType="MyInterfaceImpl&lt;System.Int32&gt;" DeclaringType="MyInterfaceImpl&lt;System.Int32&gt;"
FullName="MyInterfaceImpl&lt;System.Int32&gt;.Fun2" FullName="MyInterfaceImpl&lt;System.Int32&gt;.Fun2"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="DebugType.exe" Module="DebugType.exe"
Name="Fun2" Name="Fun2"
ParameterCount="3" ParameterCount="3"

20
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugType_CompilerGeneratedClasses.cs

@ -120,6 +120,26 @@ namespace Debugger.Tests {
Name="stateLessVar_NestedDelegRef" Name="stateLessVar_NestedDelegRef"
Value="203" /> Value="203" />
</Item> </Item>
<Item>
<AnonymousType
Name="this"
Value="{Debugger.Tests.TestPrograms.DebugType_CompilerGeneratedClasses}" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar"
Value="101" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_DelegRef"
Value="102" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_NestedDelegRef"
Value="103" />
</Item>
</YieldLocalVariables> </YieldLocalVariables>
<DebuggingPaused>Break DebugType_CompilerGeneratedClasses.cs:54,6-54,42</DebuggingPaused> <DebuggingPaused>Break DebugType_CompilerGeneratedClasses.cs:54,6-54,42</DebuggingPaused>
<OutterDelegateLocalVariables> <OutterDelegateLocalVariables>

19
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Expressions.cs

@ -130,8 +130,8 @@ namespace Debugger.Tests {
</Item> </Item>
</Arguments> </Arguments>
<LocalVariables <LocalVariables
Capacity="4" Capacity="8"
Count="4"> Count="5">
<Item> <Item>
<Value <Value
AsString="0" AsString="0"
@ -165,6 +165,13 @@ namespace Debugger.Tests {
PrimitiveValue="baseClassString" PrimitiveValue="baseClassString"
Type="System.String" /> Type="System.String" />
</Item> </Item>
<Item>
<Value
AsString="{Debugger.Tests.TestPrograms.TestClass}"
IsReference="True"
PrimitiveValue="{Exception: Value is not a primitive type}"
Type="Debugger.Tests.TestPrograms.TestClass" />
</Item>
</LocalVariables> </LocalVariables>
<this> <this>
<Item> <Item>
@ -236,6 +243,7 @@ namespace Debugger.Tests {
FullName="Debugger.Tests.TestPrograms.TestClass.get_Name" FullName="Debugger.Tests.TestPrograms.TestClass.get_Name"
IsPublic="True" IsPublic="True"
IsSpecialName="True" IsSpecialName="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="get_Name" Name="get_Name"
ReturnType="System.String" ReturnType="System.String"
@ -255,7 +263,7 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.TestClass" DeclaringType="Debugger.Tests.TestPrograms.TestClass"
FullName="Debugger.Tests.TestPrograms.TestClass.Test" FullName="Debugger.Tests.TestPrograms.TestClass.Test"
IsPublic="True" IsPublic="True"
LocalVariableNames="{array, array2, BaseClass, i}" LocalVariableNames="{array, array2, BaseClass, i, this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="Test" Name="Test"
ParameterCount="1" ParameterCount="1"
@ -266,6 +274,7 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.TestClass" DeclaringType="Debugger.Tests.TestPrograms.TestClass"
FullName="Debugger.Tests.TestPrograms.TestClass.Test" FullName="Debugger.Tests.TestPrograms.TestClass.Test"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="Test" Name="Test"
ParameterCount="1" ParameterCount="1"
@ -276,6 +285,7 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.TestClass" DeclaringType="Debugger.Tests.TestPrograms.TestClass"
FullName="Debugger.Tests.TestPrograms.TestClass.Test" FullName="Debugger.Tests.TestPrograms.TestClass.Test"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="Test" Name="Test"
ParameterCount="1" ParameterCount="1"
@ -286,6 +296,7 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.TestClass" DeclaringType="Debugger.Tests.TestPrograms.TestClass"
FullName="Debugger.Tests.TestPrograms.TestClass.Foo" FullName="Debugger.Tests.TestPrograms.TestClass.Foo"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="Foo" Name="Foo"
ParameterCount="1" ParameterCount="1"
@ -297,6 +308,7 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.TestClass" DeclaringType="Debugger.Tests.TestPrograms.TestClass"
FullName="Debugger.Tests.TestPrograms.TestClass.Foo" FullName="Debugger.Tests.TestPrograms.TestClass.Foo"
IsPublic="True" IsPublic="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name="Foo" Name="Foo"
ParameterCount="1" ParameterCount="1"
@ -309,6 +321,7 @@ namespace Debugger.Tests {
FullName="Debugger.Tests.TestPrograms.TestClass..ctor" FullName="Debugger.Tests.TestPrograms.TestClass..ctor"
IsPublic="True" IsPublic="True"
IsSpecialName="True" IsSpecialName="True"
LocalVariableNames="{this}"
Module="Expressions.exe" Module="Expressions.exe"
Name=".ctor" /> Name=".ctor" />
</Item> </Item>

Loading…
Cancel
Save