Browse Source
Variable submenus implemented in Debugger.Core git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1582 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
16 changed files with 375 additions and 371 deletions
@ -0,0 +1,227 @@
@@ -0,0 +1,227 @@
|
||||
// <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; |
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
using Debugger.Wrappers.CorDebug; |
||||
using Debugger.Wrappers.MetaData; |
||||
|
||||
namespace Debugger |
||||
{ |
||||
public class ObjectValueClass: RemotingObjectBase |
||||
{ |
||||
NDebugger debugger; |
||||
|
||||
ObjectValue objectValue; |
||||
|
||||
Module module; |
||||
ICorDebugClass corClass; |
||||
TypeDefProps classProps; |
||||
|
||||
ICorDebugObjectValue CorObjectValue { |
||||
get { |
||||
return objectValue.CorValue.As<ICorDebugObjectValue>(); |
||||
} |
||||
} |
||||
|
||||
bool IsCorValueCompatible { |
||||
get { |
||||
return objectValue.IsCorValueCompatible; |
||||
} |
||||
} |
||||
|
||||
public Module Module { |
||||
get { |
||||
return module; |
||||
} |
||||
} |
||||
|
||||
public string Type { |
||||
get{ |
||||
return classProps.Name; |
||||
} |
||||
} |
||||
|
||||
internal ICorDebugClass CorClass { |
||||
get { |
||||
return corClass; |
||||
} |
||||
} |
||||
|
||||
public uint ClassToken { |
||||
get { |
||||
return classProps.Token; |
||||
} |
||||
} |
||||
|
||||
public ObjectValueClass(ObjectValue objectValue, ICorDebugClass corClass) |
||||
{ |
||||
this.debugger = objectValue.Debugger; |
||||
this.objectValue = objectValue; |
||||
this.module = debugger.GetModule(corClass.Module); |
||||
this.corClass = corClass; |
||||
this.classProps = Module.MetaData.GetTypeDefProps(corClass.Token); |
||||
} |
||||
|
||||
public VariableCollection SubVariables { |
||||
get { |
||||
return new VariableCollection("Base class", |
||||
"{" + Type + "}", |
||||
SubCollections, |
||||
GetSubVariables(Variable.Flags.Public, Variable.Flags.PublicStatic)); |
||||
} |
||||
} |
||||
|
||||
IEnumerable<VariableCollection> SubCollections { |
||||
get { |
||||
ObjectValueClass baseClass = BaseClass; |
||||
VariableCollection privateStatic = new VariableCollection("Private static members", |
||||
String.Empty, |
||||
new VariableCollection[0], |
||||
GetSubVariables(Variable.Flags.Static, Variable.Flags.PublicStatic)); |
||||
VariableCollection privateInstance = new VariableCollection("Private members", |
||||
String.Empty, |
||||
privateStatic.IsEmpty? new VariableCollection[0] : new VariableCollection[] {privateStatic}, |
||||
GetSubVariables(Variable.Flags.None, Variable.Flags.PublicStatic)); |
||||
VariableCollection publicStatic = new VariableCollection("Static members", |
||||
String.Empty, |
||||
new VariableCollection[0], |
||||
GetSubVariables(Variable.Flags.PublicStatic, Variable.Flags.PublicStatic)); |
||||
if (baseClass != null) { |
||||
yield return baseClass.SubVariables; |
||||
} |
||||
if (!privateInstance.IsEmpty) { |
||||
yield return privateInstance; |
||||
} |
||||
if (!publicStatic.IsEmpty) { |
||||
yield return publicStatic; |
||||
} |
||||
} |
||||
} |
||||
|
||||
IEnumerable<Variable> GetSubVariables(Variable.Flags requiredFlags, Variable.Flags mask) { |
||||
foreach(Variable var in GetFieldVariables()) { |
||||
if ((var.VariableFlags & mask) == requiredFlags) { |
||||
yield return var; |
||||
} |
||||
} |
||||
|
||||
foreach(Variable var in GetPropertyVariables()) { |
||||
if ((var.VariableFlags & mask) == requiredFlags) { |
||||
yield return var; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public ObjectValueClass BaseClass { |
||||
get { |
||||
ICorDebugClass superClass = GetSuperClass(debugger, corClass); |
||||
if (superClass != null) { |
||||
return new ObjectValueClass(objectValue, superClass); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<Variable> GetFieldVariables() |
||||
{ |
||||
foreach(FieldProps f in Module.MetaData.EnumFields(ClassToken)) { |
||||
FieldProps field = f; // One per scope/delegate
|
||||
if (field.IsStatic && field.IsLiteral) continue; // Skip field
|
||||
yield return new Variable(debugger, |
||||
field.Name, |
||||
(field.IsStatic ? Variable.Flags.Static : Variable.Flags.None) | |
||||
(field.IsPublic ? Variable.Flags.Public : Variable.Flags.None), |
||||
new IExpirable[] {this.objectValue.Variable}, |
||||
delegate { return GetCorValueOfField(field); }); |
||||
} |
||||
} |
||||
|
||||
ICorDebugValue GetCorValueOfField(FieldProps field) |
||||
{ |
||||
if (!IsCorValueCompatible) throw new CannotGetValueException("Object type changed"); |
||||
|
||||
// Current frame is used to resolve context specific static values (eg. ThreadStatic)
|
||||
ICorDebugFrame curFrame = null; |
||||
if (debugger.IsPaused && debugger.SelectedThread != null && debugger.SelectedThread.LastFunction != null && debugger.SelectedThread.LastFunction.CorILFrame != null) { |
||||
curFrame = debugger.SelectedThread.LastFunction.CorILFrame.CastTo<ICorDebugFrame>(); |
||||
} |
||||
|
||||
try { |
||||
if (field.IsStatic) { |
||||
return corClass.GetStaticFieldValue(field.Token, curFrame); |
||||
} else { |
||||
return CorObjectValue.GetFieldValue(corClass, field.Token); |
||||
} |
||||
} catch { |
||||
throw new CannotGetValueException("Can not get value of field"); |
||||
} |
||||
} |
||||
|
||||
IEnumerable<MethodProps> Methods { |
||||
get { |
||||
return this.Module.MetaData.EnumMethods(this.ClassToken); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<Variable> GetPropertyVariables() |
||||
{ |
||||
foreach(MethodProps m in Methods) { |
||||
MethodProps method = m; // One per scope/delegate
|
||||
if (method.HasSpecialName && method.Name.StartsWith("get_") && method.Name != "get_Item") { |
||||
Eval eval = Eval.CallFunction(debugger, |
||||
Module.CorModule.GetFunctionFromToken(method.Token), |
||||
true, // reevaluateAfterDebuggeeStateChange
|
||||
method.IsStatic? null : this.objectValue.Variable, |
||||
new Variable[] {}); |
||||
Variable var = eval.Result; |
||||
var.Name = method.Name.Remove(0, 4); |
||||
var.VariableFlags = (method.IsStatic ? Variable.Flags.Static : Variable.Flags.None) | |
||||
(method.IsPublic ? Variable.Flags.Public : Variable.Flags.None); |
||||
yield return var; |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected static ICorDebugClass GetSuperClass(NDebugger debugger, ICorDebugClass currClass) |
||||
{ |
||||
Module currModule = debugger.GetModule(currClass.Module); |
||||
uint superToken = currModule.MetaData.GetTypeDefProps(currClass.Token).SuperClassToken; |
||||
|
||||
// It has no base class
|
||||
if ((superToken & 0x00FFFFFF) == 0x00000000) return null; |
||||
|
||||
// TypeDef - Localy defined
|
||||
if ((superToken & 0xFF000000) == 0x02000000) { |
||||
return currModule.CorModule.GetClassFromToken(superToken); |
||||
} |
||||
|
||||
// TypeRef - Referencing to external assembly
|
||||
if ((superToken & 0xFF000000) == 0x01000000) { |
||||
string fullTypeName = currModule.MetaData.GetTypeRefProps(superToken).Name; |
||||
|
||||
foreach (Module superModule in debugger.Modules) { |
||||
// TODO: Does not work for nested
|
||||
// TODO: preservesig
|
||||
try { |
||||
uint token = superModule.MetaData.FindTypeDefByName(fullTypeName, 0).Token; |
||||
return superModule.CorModule.GetClassFromToken(token); |
||||
} catch { |
||||
continue; |
||||
} |
||||
} |
||||
} |
||||
|
||||
throw new DebuggerException("Superclass not found"); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue