Browse Source

Lazy getting of array values

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@831 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
dbe4cb08bd
  1. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  2. 18
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/MetaData/MetaData.cs
  3. 8
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Exception.cs
  4. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  5. 85
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs
  6. 55
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs
  7. 21
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs
  8. 14
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs

@ -251,7 +251,7 @@ namespace ICSharpCode.SharpDevelop.Services
{ {
DynamicTreeDebuggerRow row = (DynamicTreeDebuggerRow) sender; DynamicTreeDebuggerRow row = (DynamicTreeDebuggerRow) sender;
row.ChildRows.Clear(); row.ChildRows.Clear();
foreach(Variable variable in row.Variable.Value.SubVariables) { foreach(Variable variable in row.Variable.SubVariables) {
DynamicTreeDebuggerRow newRow = new DynamicTreeDebuggerRow(variable); DynamicTreeDebuggerRow newRow = new DynamicTreeDebuggerRow(variable);
DebuggerGridControl.AddColumns(newRow.ChildColumns); DebuggerGridControl.AddColumns(newRow.ChildColumns);
newRow.Expanding += TooltipControlRowExpanding; newRow.Expanding += TooltipControlRowExpanding;

18
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/MetaData/MetaData.cs

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -86,10 +86,8 @@ namespace Debugger
return typeRefProps; return typeRefProps;
} }
public IList<FieldProps> EnumFields(uint typeToken) public IEnumerable<FieldProps> EnumFields(uint typeToken)
{ {
List<FieldProps> fields = new List<FieldProps>();
IntPtr enumerator = IntPtr.Zero; IntPtr enumerator = IntPtr.Zero;
while (true) { while (true) {
uint fieldToken; uint fieldToken;
@ -99,10 +97,8 @@ namespace Debugger
metaData.CloseEnum(enumerator); metaData.CloseEnum(enumerator);
break; break;
} }
fields.Add(GetFieldProps(fieldToken)); yield return GetFieldProps(fieldToken);
} }
return fields;
} }
public FieldProps GetFieldProps(uint fieldToken) public FieldProps GetFieldProps(uint fieldToken)
@ -148,10 +144,8 @@ namespace Debugger
return fieldProps; return fieldProps;
} }
public IList<MethodProps> EnumMethods(uint typeToken) public IEnumerable<MethodProps> EnumMethods(uint typeToken)
{ {
IList<MethodProps> methods = new List<MethodProps>();
IntPtr enumerator = IntPtr.Zero; IntPtr enumerator = IntPtr.Zero;
while(true) { while(true) {
uint methodToken; uint methodToken;
@ -161,10 +155,8 @@ namespace Debugger
metaData.CloseEnum(enumerator); metaData.CloseEnum(enumerator);
break; break;
} }
methods.Add(GetMethodProps(methodToken)); yield return GetMethodProps(methodToken);
} }
return methods;
} }
public unsafe MethodProps GetMethodProps(uint methodToken) public unsafe MethodProps GetMethodProps(uint methodToken)

8
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Exception.cs

@ -79,13 +79,7 @@ namespace Debugger
type = runtimeValue.Type; type = runtimeValue.Type;
} }
public override string ToString() { public string Type {
return "Exception data:\n" + runtimeValue.ToString() + "\n" +
"---------------\n" +
runtimeValueException.SubVariables.ToString();
}
public string Type {
get { get {
return type; return type;
} }

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -416,7 +416,7 @@ namespace Debugger
public IEnumerable<Variable> ContaingClassVariables { public IEnumerable<Variable> ContaingClassVariables {
get { get {
if (!IsStatic) { if (!IsStatic) {
foreach(Variable var in ThisValue.SubVariables) { foreach(Variable var in ThisValue.GetSubVariables(delegate{return ThisValue;})) {
yield return var; yield return var;
} }
} }

85
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs

@ -89,48 +89,71 @@ namespace Debugger
} }
} }
public unsafe Variable this[uint[] indices] { public Variable this[uint[] indices] {
get { get {
if (indices.Length != rank) throw new DebuggerException("Given indicies does not match array size."); return GetItem(indices, delegate {return this;});
string elementName = "[";
for (int i = 0; i < indices.Length; i++)
elementName += indices[i].ToString() + ",";
elementName = elementName.TrimEnd(new char[] {','}) + "]";
ICorDebugValue element;
fixed (void* pIndices = indices)
corArrayValue.GetElement(rank, new IntPtr(pIndices), out element);
return new Variable(debugger, element, elementName);
} }
} }
Variable GetItem(uint[] indices, ValueGetter getter)
{
if (indices.Length != rank) throw new DebuggerException("Given indicies does not match array size.");
string elementName = "[";
for (int i = 0; i < indices.Length; i++)
elementName += indices[i].ToString() + ",";
elementName = elementName.TrimEnd(new char[] {','}) + "]";
return new Variable(debugger,
elementName,
delegate {
ArrayValue updatedVal = getter() as ArrayValue;
if (this.IsEquivalentValue(updatedVal)) {
ICorDebugValue element;
unsafe {
fixed (void* pIndices = indices) {
updatedVal.corArrayValue.GetElement(rank, new IntPtr(pIndices), out element);
}
}
return Value.CreateValue(debugger, element);
} else {
return new UnavailableValue(debugger, "Value is not array");
}
});
}
public override bool MayHaveSubVariables { public override bool MayHaveSubVariables {
get { get {
return true; return true;
} }
} }
public override IEnumerable<Variable> SubVariables { public override IEnumerable<Variable> GetSubVariables(ValueGetter getter)
get { {
uint[] indices = new uint[rank]; uint[] indices = new uint[rank];
for(;;) // Go thought all combinations while(true) { // Go thought all combinations
{ for (uint i = rank - 1; i >= 1; i--)
for (uint i = rank - 1; i >= 1; i--) if (indices[i] >= dimensions[i])
if (indices[i] >= dimensions[i]) {
{ indices[i] = 0;
indices[i] = 0; indices[i-1]++;
indices[i-1]++; }
} if (indices[0] >= dimensions[0]) break; // We are done
if (indices[0] >= dimensions[0]) break; // We are done
yield return GetItem(indices, getter);
yield return this[indices];
indices[rank - 1]++;
indices[rank - 1]++;
}
} }
} }
public override bool IsEquivalentValue(Value val)
{
ArrayValue arrayVal = val as ArrayValue;
return arrayVal != null &&
arrayVal.ElementsType == this.ElementsType &&
arrayVal.Lenght == this.Lenght &&
arrayVal.Rank == this.Rank;
}
} }
} }

55
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs

@ -120,40 +120,39 @@ namespace Debugger
} }
} }
public override IEnumerable<Variable> SubVariables { public override IEnumerable<Variable> GetSubVariables(ValueGetter getter)
get { {
if (HasBaseClass) { if (HasBaseClass) {
yield return BaseClassVariable; yield return BaseClassVariable;
} }
// Current frame is necessary to resolve context specific static values (eg. ThreadStatic)
ICorDebugFrame curFrame;
if (debugger.CurrentThread == null || debugger.CurrentThread.LastFunction == null || debugger.CurrentThread.LastFunction.CorILFrame == null) {
curFrame = null;
} else {
curFrame = debugger.CurrentThread.LastFunction.CorILFrame;
}
foreach(FieldProps field in metaData.EnumFields(classProps.Token)) { // Current frame is necessary to resolve context specific static values (eg. ThreadStatic)
Variable var; ICorDebugFrame curFrame;
try { if (debugger.CurrentThread == null || debugger.CurrentThread.LastFunction == null || debugger.CurrentThread.LastFunction.CorILFrame == null) {
ICorDebugValue fieldValue; curFrame = null;
if (field.IsStatic) { } else {
if (field.IsLiteral) continue; // Try next field curFrame = debugger.CurrentThread.LastFunction.CorILFrame;
}
corClass.GetStaticFieldValue(field.Token, curFrame, out fieldValue); foreach(FieldProps field in metaData.EnumFields(classProps.Token)) {
} else { Variable var;
if (corValue == null) continue; // Try next field try {
ICorDebugValue fieldValue;
if (field.IsStatic) {
if (field.IsLiteral) continue; // Try next field
((ICorDebugObjectValue)corValue).GetFieldValue(corClass, field.Token, out fieldValue); corClass.GetStaticFieldValue(field.Token, curFrame, out fieldValue);
} } else {
if (corValue == null) continue; // Try next field
var = new Variable(debugger, fieldValue, field.Name); ((ICorDebugObjectValue)corValue).GetFieldValue(corClass, field.Token, out fieldValue);
} catch {
var = new Variable(new UnavailableValue(debugger), field.Name);
} }
yield return var;
var = new Variable(debugger, fieldValue, field.Name);
} catch {
var = new Variable(new UnavailableValue(debugger), field.Name);
} }
yield return var;
} }
} }

21
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs

@ -74,15 +74,26 @@ namespace Debugger
get; get;
} }
public virtual IEnumerable<Variable> SubVariables { /// <summary>
get { /// Gets the subvariables of this value
yield break; /// </summary>
} /// <param name="getter">Delegate that will be called to get the up-to-date value</param>
public virtual IEnumerable<Variable> GetSubVariables(ValueGetter getter)
{
yield break;
}
/// <summary>
/// Gets whether the given value is equivalent to this one. (ie it is may be just its other instance)
/// </summary>
public virtual bool IsEquivalentValue(Value val)
{
return val.GetType() == this.GetType();
} }
public Variable this[string variableName] { public Variable this[string variableName] {
get { get {
foreach(Variable v in SubVariables) { foreach(Variable v in GetSubVariables(delegate{return this;})) {
if (v.Name == variableName) return v; if (v.Name == variableName) return v;
} }
throw new DebuggerException("Subvariable " + variableName + " does not exist"); throw new DebuggerException("Subvariable " + variableName + " does not exist");

14
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs

@ -11,7 +11,7 @@ using Debugger.Interop.CorDebug;
namespace Debugger namespace Debugger
{ {
public delegate Value ValueUpdatingEventHandler(); public delegate Value ValueGetter();
public class Variable: RemotingObjectBase public class Variable: RemotingObjectBase
{ {
@ -21,7 +21,7 @@ namespace Debugger
Value val; Value val;
VariableCollection subVariables; VariableCollection subVariables;
event ValueUpdatingEventHandler updating; event ValueGetter updating;
public event EventHandler<VariableEventArgs> ValueChanged; public event EventHandler<VariableEventArgs> ValueChanged;
public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection; public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection;
@ -94,11 +94,7 @@ namespace Debugger
void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e) void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e)
{ {
VariableCollection newVariables = new VariableCollection(debugger); subVariables.UpdateTo(Value.GetSubVariables(delegate{return this.Value;}));
foreach(Variable v in Value.SubVariables) {
newVariables.Add(v);
}
subVariables.UpdateTo(newVariables);
} }
protected internal virtual void OnValueRemovedFromCollection(VariableCollectionEventArgs e) { protected internal virtual void OnValueRemovedFromCollection(VariableCollectionEventArgs e) {
@ -112,7 +108,7 @@ namespace Debugger
} }
public Variable(NDebugger debugger, string name, ValueUpdatingEventHandler updating):this(debugger, null, name, updating) public Variable(NDebugger debugger, string name, ValueGetter updating):this(debugger, null, name, updating)
{ {
} }
@ -122,7 +118,7 @@ namespace Debugger
} }
Variable(NDebugger debugger, Value val, string name, ValueUpdatingEventHandler updating) Variable(NDebugger debugger, Value val, string name, ValueGetter updating)
{ {
this.debugger = debugger; this.debugger = debugger;
if (val != null) { if (val != null) {

Loading…
Cancel
Save