Browse Source

Support for variables captured by delegate

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4836 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
704a87db67
  1. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs
  2. 79
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs
  3. 109
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/CompilerGeneratedClasses.cs

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

@ -733,7 +733,7 @@ namespace Debugger.MetaData
public bool IsDisplayClass { public bool IsDisplayClass {
get { get {
return this.IsCompilerGenerated && this.Name.Contains("DisplayClass"); return this.Name.StartsWith("<>") && this.Name.Contains("__DisplayClass");
} }
} }

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

@ -427,7 +427,7 @@ namespace Debugger.MetaData
public List<LocalVariableInfo> LocalVariables { public List<LocalVariableInfo> LocalVariables {
get { get {
if (this.SymMethod != null) { // TODO: Is this needed? if (this.SymMethod != null) { // TODO: Is this needed?
return GetLocalVariablesInScope(this.SymMethod.RootScope); return GetLocalVariables();
} else { } else {
return new List<LocalVariableInfo>(); return new List<LocalVariableInfo>();
} }
@ -446,25 +446,84 @@ namespace Debugger.MetaData
} }
} }
List<LocalVariableInfo> localVariables; // Cache
List<LocalVariableInfo> GetLocalVariables()
{
if (localVariables != null) return localVariables;
localVariables = GetLocalVariablesInScope(this.SymMethod.RootScope);
if (!this.IsStatic && this.DeclaringType.IsDisplayClass) {
// Get display class from self
localVariables.AddRange(GetLocalVariablesFromDisplayClass(
delegate(StackFrame context) {
return context.GetThisValue();
},
this.DeclaringType
));
// Get dispaly classes from fields
foreach(FieldInfo fieldInfo in this.DeclaringType.GetFields()) {
FieldInfo fieldInfoCopy = fieldInfo;
if (fieldInfo.Name.StartsWith("CS$")) {
localVariables.AddRange(GetLocalVariablesFromDisplayClass(
delegate(StackFrame context) {
return context.GetThisValue().GetFieldValue(fieldInfoCopy);
},
fieldInfo.Type
));
}
}
}
return localVariables;
}
List<LocalVariableInfo> GetLocalVariablesFromDisplayClass(ValueGetter getDisplayClass, DebugType displayClassType)
{
List<LocalVariableInfo> vars = new List<LocalVariableInfo>();
if (displayClassType.IsDisplayClass) {
foreach(FieldInfo fieldInfo in displayClassType.GetFields()) {
FieldInfo fieldInfoCopy = fieldInfo;
if (!fieldInfo.Name.StartsWith("CS$")) {
vars.Add(
new LocalVariableInfo(
fieldInfo.Name,
fieldInfo.Type,
delegate(StackFrame context) {
return getDisplayClass(context).GetFieldValue(fieldInfoCopy);
}
)
);
}
}
}
return vars;
}
List<LocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope) List<LocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope)
{ {
List<LocalVariableInfo> vars = new List<LocalVariableInfo>(); List<LocalVariableInfo> vars = new List<LocalVariableInfo>();
foreach (ISymUnmanagedVariable symVar in symScope.Locals) { foreach (ISymUnmanagedVariable symVar in symScope.Locals) {
ISymUnmanagedVariable symVarCopy = symVar;
int start; int start;
SignatureReader sigReader = new SignatureReader(symVar.Signature); SignatureReader sigReader = new SignatureReader(symVar.Signature);
LocalVarSig.LocalVariable locVarSig = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start); LocalVarSig.LocalVariable locVarSig = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start);
DebugType type = DebugType.CreateFromSignature(this.Module, locVarSig.Type, this.DeclaringType); DebugType locVarType = DebugType.CreateFromSignature(this.Module, locVarSig.Type, this.DeclaringType);
// Compiler generated? // Compiler generated?
// NB: Display class does not have the compiler-generated flag // NB: Display class does not have the compiler-generated flag
if ((symVar.Attributes & 1) == 1 || symVar.Name.StartsWith("CS$")) { if ((symVar.Attributes & 1) == 1 || symVar.Name.StartsWith("CS$")) {
if (type.IsDisplayClass) { // Get display class from local variable
if (locVarType.IsDisplayClass) {
vars.AddRange(GetLocalVariablesFromDisplayClass(
delegate(StackFrame context) {
return GetLocalVariableValue(context, symVarCopy);
},
locVarType
));
} }
} else { } else {
ISymUnmanagedVariable symVarCopy = symVar;
LocalVariableInfo locVar = new LocalVariableInfo( LocalVariableInfo locVar = new LocalVariableInfo(
symVar.Name, symVar.Name,
type, locVarType,
delegate(StackFrame context) { delegate(StackFrame context) {
return GetLocalVariableValue(context, symVarCopy); return GetLocalVariableValue(context, symVarCopy);
} }
@ -491,13 +550,13 @@ namespace Debugger.MetaData
} }
} }
public delegate Value ValueGetter(StackFrame context);
public class LocalVariableInfo public class LocalVariableInfo
{ {
public delegate Value LocalVariableValueGetter(StackFrame context);
string name; string name;
DebugType type; DebugType type;
LocalVariableValueGetter getter; ValueGetter getter;
public string Name { public string Name {
get { return name; } get { return name; }
@ -507,7 +566,7 @@ namespace Debugger.MetaData
get { return type; } get { return type; }
} }
public LocalVariableInfo(string name, DebugType type, LocalVariableValueGetter getter) public LocalVariableInfo(string name, DebugType type, ValueGetter getter)
{ {
this.name = name; this.name = name;
this.type = type; this.type = type;

109
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/CompilerGeneratedClasses.cs

@ -16,10 +16,10 @@ namespace Debugger.Tests.TestPrograms
public static void Main() public static void Main()
{ {
new List<object>(MyEnum()); new List<object>(new CompilerGeneratedClasses().MyEnum());
} }
static IEnumerable<object> MyEnum() IEnumerable<object> MyEnum()
{ {
int stateFullVar = 101; int stateFullVar = 101;
int stateFullVar_DelegRef = 102; int stateFullVar_DelegRef = 102;
@ -46,9 +46,13 @@ namespace Debugger.Tests.TestPrograms
Console.WriteLine(delegVar_NestedDelegRef); Console.WriteLine(delegVar_NestedDelegRef);
Console.WriteLine(stateFullVar_NestedDelegRef); Console.WriteLine(stateFullVar_NestedDelegRef);
Console.WriteLine(stateLessVar_NestedDelegRef); Console.WriteLine(stateLessVar_NestedDelegRef);
Console.WriteLine(this);
System.Diagnostics.Debugger.Break();
}; };
System.Diagnostics.Debugger.Break(); System.Diagnostics.Debugger.Break();
nestedDeleg(402);
}; };
deleg(401); deleg(401);
} }
@ -71,7 +75,12 @@ namespace Debugger.Tests {
Select(v => new { v.Name, Value = v.GetValue(process.SelectedStackFrame) }) Select(v => new { v.Name, Value = v.GetValue(process.SelectedStackFrame) })
); );
process.Continue(); process.Continue();
ObjectDump("DelegateLocalVariables", ObjectDump("OutterDelegateLocalVariables",
process.SelectedStackFrame.MethodInfo.LocalVariables.
Select(v => new { v.Name, Value = v.GetValue(process.SelectedStackFrame) })
);
process.Continue();
ObjectDump("InnterDelegateLocalVariables",
process.SelectedStackFrame.MethodInfo.LocalVariables. process.SelectedStackFrame.MethodInfo.LocalVariables.
Select(v => new { v.Name, Value = v.GetValue(process.SelectedStackFrame) }) Select(v => new { v.Name, Value = v.GetValue(process.SelectedStackFrame) })
); );
@ -101,9 +110,19 @@ namespace Debugger.Tests {
Name="deleg" Name="deleg"
Value="deleg = null" /> Value="deleg = null" />
</Item> </Item>
<Item>
<AnonymousType
Name="stateLessVar_DelegRef"
Value="(()(CS$&lt;&gt;8__locals5)).stateLessVar_DelegRef = 202" />
</Item>
<Item>
<AnonymousType
Name="stateLessVar_NestedDelegRef"
Value="(()(CS$&lt;&gt;8__locals5)).stateLessVar_NestedDelegRef = 203" />
</Item>
</YieldLocalVariables> </YieldLocalVariables>
<DebuggingPaused>Break CompilerGeneratedClasses.cs:51,6-51,42</DebuggingPaused> <DebuggingPaused>Break CompilerGeneratedClasses.cs:54,6-54,42</DebuggingPaused>
<DelegateLocalVariables> <OutterDelegateLocalVariables>
<Item> <Item>
<AnonymousType <AnonymousType
Name="delegVar" Name="delegVar"
@ -114,7 +133,85 @@ namespace Debugger.Tests {
Name="nestedDeleg" Name="nestedDeleg"
Value="nestedDeleg = {IntDelegate}" /> Value="nestedDeleg = {IntDelegate}" />
</Item> </Item>
</DelegateLocalVariables> <Item>
<AnonymousType
Name="delegVar_NestedDelegRef"
Value="(()(CS$&lt;&gt;8__locals7)).delegVar_NestedDelegRef = 302" />
</Item>
<Item>
<AnonymousType
Name="delegArg_NestedDelegRef"
Value="(()(CS$&lt;&gt;8__locals7)).delegArg_NestedDelegRef = 401" />
</Item>
<Item>
<AnonymousType
Name="stateLessVar_DelegRef"
Value="(()(this)).stateLessVar_DelegRef = 202" />
</Item>
<Item>
<AnonymousType
Name="stateLessVar_NestedDelegRef"
Value="(()(this)).stateLessVar_NestedDelegRef = 203" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_DelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).stateFullVar_DelegRef = 102" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_NestedDelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).stateFullVar_NestedDelegRef = 103" />
</Item>
<Item>
<AnonymousType
Name="&lt;&gt;4__this"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).&lt;&gt;4__this = {Debugger.Tests.TestPrograms.CompilerGeneratedClasses}" />
</Item>
</OutterDelegateLocalVariables>
<DebuggingPaused>Break CompilerGeneratedClasses.cs:51,7-51,43</DebuggingPaused>
<InnterDelegateLocalVariables>
<Item>
<AnonymousType
Name="nestedDelegVar"
Value="nestedDelegVar = 303" />
</Item>
<Item>
<AnonymousType
Name="delegVar_NestedDelegRef"
Value="(()(this)).delegVar_NestedDelegRef = 302" />
</Item>
<Item>
<AnonymousType
Name="delegArg_NestedDelegRef"
Value="(()(this)).delegArg_NestedDelegRef = 401" />
</Item>
<Item>
<AnonymousType
Name="stateLessVar_DelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals5)).stateLessVar_DelegRef = 202" />
</Item>
<Item>
<AnonymousType
Name="stateLessVar_NestedDelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals5)).stateLessVar_NestedDelegRef = 203" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_DelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).stateFullVar_DelegRef = 102" />
</Item>
<Item>
<AnonymousType
Name="stateFullVar_NestedDelegRef"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).stateFullVar_NestedDelegRef = 103" />
</Item>
<Item>
<AnonymousType
Name="&lt;&gt;4__this"
Value="(()((()(this)).CS$&lt;&gt;8__locals3)).&lt;&gt;4__this = {Debugger.Tests.TestPrograms.CompilerGeneratedClasses}" />
</Item>
</InnterDelegateLocalVariables>
<ProcessExited /> <ProcessExited />
</Test> </Test>
</DebuggerTests> </DebuggerTests>

Loading…
Cancel
Save