protected static void GetInheritedTypes(IReferenceType type, HashSet <IReferenceType> inheritedTypes) { Contract.Requires <ArgumentNullException>(type != null, "type"); Contract.Requires <ArgumentNullException>(inheritedTypes != null, "inheritedTypes"); List <IReferenceType> immediateBases = new List <IReferenceType>(); IClassType classtype = type as IClassType; if (classtype != null) { IClassType basetype = classtype.GetSuperclass(); if (basetype != null) { immediateBases.Add(basetype); } immediateBases.AddRange(classtype.GetInterfaces(false)); } IInterfaceType interfacetype = type as IInterfaceType; if (interfacetype != null) { immediateBases.AddRange(interfacetype.GetSuperInterfaces()); } foreach (var baseType in immediateBases) { if (inheritedTypes.Add(baseType)) { GetInheritedTypes(baseType, inheritedTypes); } } }
/// <summary> /// Gets the DEBUG_PROPERTY_INFO structure that describes a property. /// </summary> /// <param name="dwFields">[in] A combination of values from the DEBUGPROP_INFO_FLAGS enumeration that specifies which fields are to be filled out in the pPropertyInfo structure.</param> /// <param name="dwRadix">[in] Radix to be used in formatting any numerical information.</param> /// <param name="dwTimeout">[in] Specifies the maximum time, in milliseconds, to wait before returning from this method. Use INFINITE to wait indefinitely.</param> /// <param name="rgpArgs">[in, out] Reserved for future use; set to a null value.</param> /// <param name="dwArgCount">[in] Reserved for future use; set to zero.</param> /// <param name="pPropertyInfo">[out] A DEBUG_PROPERTY_INFO structure that is filled in with the description of the property.</param> /// <returns>If successful, returns S_OK; otherwise returns error code.</returns> public int GetPropertyInfo(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, uint dwTimeout, IDebugReference2[] rgpArgs, uint dwArgCount, DEBUG_PROPERTY_INFO[] pPropertyInfo) { if (pPropertyInfo == null) { throw new ArgumentNullException("pPropertyInfo"); } if (pPropertyInfo.Length == 0) { throw new ArgumentException(); } bool getFullName = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME) != 0; bool getName = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME) != 0; bool getType = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE) != 0; bool getValue = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE) != 0; bool getAttributes = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB) != 0; bool getProperty = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP) != 0; bool useAutoExpandValue = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_AUTOEXPAND) != 0; bool noFormatting = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_RAW) != 0; bool noToString = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_NO_TOSTRING) != 0; if (getFullName) { pPropertyInfo[0].bstrFullName = _evaluatedExpression.FullName; pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME; } if (getName) { pPropertyInfo[0].bstrName = _evaluatedExpression.Name; pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME; } if (getType) { pPropertyInfo[0].bstrType = _evaluatedExpression.ValueType.GetName(); if (_evaluatedExpression.Value != null && !_evaluatedExpression.Value.GetValueType().Equals(_evaluatedExpression.ValueType)) { pPropertyInfo[0].bstrType += " {" + _evaluatedExpression.Value.GetValueType().GetName() + "}"; } pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE; } if (getValue) { if (_evaluatedExpression.Value == null) { pPropertyInfo[0].bstrValue = "null"; } if (_evaluatedExpression.Value is IVoidValue) { pPropertyInfo[0].bstrValue = "The expression has been evaluated and has no value."; } else if (_evaluatedExpression.Value is IPrimitiveValue) { IBooleanValue booleanValue = _evaluatedExpression.Value as IBooleanValue; if (booleanValue != null) { pPropertyInfo[0].bstrValue = booleanValue.GetValue().ToString().ToLowerInvariant(); pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_BOOLEAN; if (booleanValue.GetValue()) { pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_BOOLEAN_TRUE; } } IByteValue byteValue = _evaluatedExpression.Value as IByteValue; if (byteValue != null) { pPropertyInfo[0].bstrValue = byteValue.GetValue().ToString(); } ICharValue charValue = _evaluatedExpression.Value as ICharValue; if (charValue != null) { pPropertyInfo[0].bstrValue = EscapeSpecialCharacters(charValue.GetValue().ToString(), 10, '\''); } IShortValue shortValue = _evaluatedExpression.Value as IShortValue; if (shortValue != null) { pPropertyInfo[0].bstrValue = shortValue.GetValue().ToString(); } IIntegerValue integerValue = _evaluatedExpression.Value as IIntegerValue; if (integerValue != null) { pPropertyInfo[0].bstrValue = integerValue.GetValue().ToString(); } ILongValue longValue = _evaluatedExpression.Value as ILongValue; if (longValue != null) { pPropertyInfo[0].bstrValue = longValue.GetValue().ToString(); } IFloatValue floatValue = _evaluatedExpression.Value as IFloatValue; if (floatValue != null) { pPropertyInfo[0].bstrValue = floatValue.GetValue().ToString(); } IDoubleValue doubleValue = _evaluatedExpression.Value as IDoubleValue; if (doubleValue != null) { pPropertyInfo[0].bstrValue = doubleValue.GetValue().ToString(); } } else if (_evaluatedExpression.Value is IArrayReference) { IArrayReference arrayReference = _evaluatedExpression.Value as IArrayReference; int length = arrayReference.GetLength(); IArrayType arrayType = (IArrayType)arrayReference.GetReferenceType(); pPropertyInfo[0].bstrValue = string.Format("{{{0}[{1}]}}", arrayType.GetComponentTypeName(), length); if (length > 0) { pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; } } else if (_evaluatedExpression.Value is IObjectReference) { IStringReference stringReference = _evaluatedExpression.Value as IStringReference; if (stringReference != null) { pPropertyInfo[0].bstrValue = EscapeSpecialCharacters(stringReference.GetValue(), 120, '"'); } else { IObjectReference objectReference = _evaluatedExpression.Value as IObjectReference; if (objectReference != null) { int collectionSize; if (TryGetCollectionSize(objectReference, out collectionSize)) { pPropertyInfo[0].bstrValue = string.Format("{{size() = {0}}}", collectionSize); pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; } else { string displayValue = null; IClassType classType = objectReference.GetReferenceType() as IClassType; if (noToString || classType == null) { displayValue = objectReference.GetReferenceType().GetName(); } else { IMethod method = classType.GetConcreteMethod("toString", "()Ljava/lang/String;"); using (IStrongValueHandle <IValue> result = objectReference.InvokeMethod(null, method, InvokeOptions.None)) { if (result != null) { stringReference = result.Value as IStringReference; if (stringReference != null) { displayValue = stringReference.GetValue(); } } } if (displayValue == null) { IClassType objectClass = classType; while (true) { IClassType parentClass = objectClass.GetSuperclass(); if (parentClass != null) { objectClass = parentClass; } else { break; } } IMethod objectToStringMethod = objectClass.GetConcreteMethod("toString", "()Ljava/lang/String;"); // fall back to a non-virtual call using (IStrongValueHandle <IValue> result = objectReference.InvokeMethod(null, objectToStringMethod, InvokeOptions.NonVirtual | InvokeOptions.SingleThreaded)) { if (result != null) { stringReference = result.Value as IStringReference; if (stringReference != null) { displayValue = stringReference.GetValue(); } } } } } pPropertyInfo[0].bstrValue = "{" + displayValue + "}"; pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; } } else { pPropertyInfo[0].bstrValue = "Unrecognized value"; pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_ERROR; } } } pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE; } if (getAttributes) { if (_evaluatedExpression.Field != null) { if (_evaluatedExpression.Field.GetIsPrivate()) { pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PRIVATE; } if (_evaluatedExpression.Field.GetIsProtected()) { pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PROTECTED; } if (_evaluatedExpression.Field.GetIsPublic()) { pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PUBLIC; } } pPropertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_READONLY; pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB; #if false bool expandable; bool hasId; bool canHaveId; bool readOnly; bool error; bool sideEffect; bool overloadedContainer; bool boolean; bool booleanTrue; bool invalid; bool notAThing; bool autoExpanded; bool timeout; bool rawString; bool customViewer; bool accessNone; bool accessPrivate; bool accessProtected; bool accessPublic; bool storageNone; bool storageGlobal; bool storageStatic; bool storageRegister; bool noModifiers; bool @virtual; bool constant; bool synchronized; bool @volatile; bool dataField; bool method; bool property; bool @class; bool baseClass; bool @interface; bool innerClass; bool mostDerived; bool multiCustomViewers; #endif } if (getProperty) { pPropertyInfo[0].pProperty = this; pPropertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP; } return(VSConstants.S_OK); }
public int EnumChildren(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, ref Guid guidFilter, enum_DBG_ATTRIB_FLAGS dwAttribFilter, string pszNameFilter, uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum) { Stopwatch stopwatch = Stopwatch.StartNew(); bool infinite = dwTimeout == unchecked ((uint)Timeout.Infinite); TimeSpan timeout = infinite ? TimeSpan.Zero : TimeSpan.FromMilliseconds(dwTimeout); IObjectReference objectReference = _evaluatedExpression.Value as IObjectReference; IReferenceType referenceType = _evaluatedExpression.ValueType as IReferenceType; if (objectReference == null || referenceType == null) { ppEnum = new EnumDebugPropertyInfo(Enumerable.Empty <DEBUG_PROPERTY_INFO>()); return(VSConstants.S_OK); } ppEnum = null; bool getFullName = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME) != 0; bool getName = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME) != 0; bool getType = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE) != 0; bool getValue = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE) != 0; bool getAttributes = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB) != 0; bool getProperty = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP) != 0; bool useAutoExpandValue = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_AUTOEXPAND) != 0; bool noFormatting = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_RAW) != 0; bool noToString = (dwFields & enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_NO_TOSTRING) != 0; List <DEBUG_PROPERTY_INFO> properties = new List <DEBUG_PROPERTY_INFO>(); DEBUG_PROPERTY_INFO[] propertyInfo = new DEBUG_PROPERTY_INFO[1]; bool isCollection = false; int collectionSize = 0; bool haveCollectionValues = false; ReadOnlyCollection <IValue> collectionValues = null; IType componentType = null; if (!_useRawValues) { isCollection = TryGetCollectionSize(objectReference, out collectionSize); if (isCollection && (getValue || getProperty)) { haveCollectionValues = TryGetCollectionValues(objectReference, out collectionValues, out componentType); } } if (isCollection) { for (int i = 0; i < collectionSize; i++) { propertyInfo[0] = default(DEBUG_PROPERTY_INFO); if (haveCollectionValues) { string name = "[" + i + "]"; IType propertyType = componentType; IValue value = collectionValues[i]; JavaDebugProperty property = new JavaDebugProperty(this, name, _evaluatedExpression.FullName + name, propertyType, value, _evaluatedExpression.HasSideEffects); bool timedout = !infinite && timeout < stopwatch.Elapsed; enum_DEBUGPROP_INFO_FLAGS fields = dwFields; if (timedout) { fields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_NO_TOSTRING; } int hr = property.GetPropertyInfo(fields, dwRadix, dwTimeout, null, 0, propertyInfo); if (ErrorHandler.Failed(hr)) { return(hr); } if (timedout) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_TIMEOUT; } properties.Add(propertyInfo[0]); continue; } else { if (getFullName) { propertyInfo[0].bstrFullName = _evaluatedExpression.FullName + "[" + i + "]"; propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME; } if (getName) { propertyInfo[0].bstrName = "[" + i + "]"; propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME; } if (getType) { propertyInfo[0].bstrType = componentType.GetName(); propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE; } if (getAttributes) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_AUTOEXPANDED; propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_READONLY; if (_evaluatedExpression.HasSideEffects) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_SIDE_EFFECT; } propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB; } } } bool useRawValues = referenceType is IClassType; if (useRawValues) { if (_rawValuesProperty == null) { _rawValuesProperty = new JavaDebugProperty(this, "Raw Values") { _useRawValues = true }; } propertyInfo[0] = default(DEBUG_PROPERTY_INFO); ErrorHandler.ThrowOnFailure(_rawValuesProperty.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); properties.Add(propertyInfo[0]); } } else { ReadOnlyCollection <IField> fields = referenceType.GetFields(false); List <IField> staticFields = new List <IField>(fields.Where(i => i.GetIsStatic())); bool useMostDerived = !_preventMostDerived && _evaluatedExpression.Value != null && !_evaluatedExpression.Value.GetValueType().Equals(referenceType); if (useMostDerived) { if (_mostDerivedProperty == null) { _mostDerivedProperty = new JavaDebugProperty(this, string.Format("[{0}]", _evaluatedExpression.Value.GetValueType().GetName()), _evaluatedExpression.Value.GetValueType()) { _preventMostDerived = true }; } propertyInfo[0] = default(DEBUG_PROPERTY_INFO); ErrorHandler.ThrowOnFailure(_mostDerivedProperty.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); properties.Add(propertyInfo[0]); } bool useSuper = false; if (!useMostDerived) { IClassType valueType = _evaluatedExpression.ValueType as IClassType; if (valueType != null) { IClassType superClass = valueType.GetSuperclass(); useSuper = superClass != null && superClass.GetName() != "java.lang.Object"; if (useSuper) { if (_superProperty == null) { _superProperty = new JavaDebugProperty(this, "[super]", superClass) { _preventMostDerived = true }; } propertyInfo[0] = default(DEBUG_PROPERTY_INFO); ErrorHandler.ThrowOnFailure(_superProperty.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); properties.Add(propertyInfo[0]); } } } foreach (var field in fields) { if (field.GetIsStatic()) { continue; } propertyInfo[0] = default(DEBUG_PROPERTY_INFO); if (getValue || getProperty) { IDebugProperty2 property; try { string name = field.GetName(); IType propertyType = field.GetFieldType(); IValue value = objectReference.GetValue(field); property = new JavaDebugProperty(this, name, _evaluatedExpression.FullName + "." + name, propertyType, value, _evaluatedExpression.HasSideEffects, field); ErrorHandler.ThrowOnFailure(property.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); } catch (Exception e) { if (ErrorHandler.IsCriticalException(e)) { throw; } string name = field.GetName(); IType propertyType = field.GetFieldType(); IValue value = field.GetVirtualMachine().GetMirrorOf(0); property = new JavaDebugProperty(this, name, _evaluatedExpression.FullName + "." + name, propertyType, value, _evaluatedExpression.HasSideEffects, field); ErrorHandler.ThrowOnFailure(property.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); } } else { if (getFullName) { propertyInfo[0].bstrFullName = _evaluatedExpression.FullName + "." + field.GetName(); propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME; } if (getName) { propertyInfo[0].bstrName = field.GetName(); propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME; } if (getType) { propertyInfo[0].bstrType = field.GetFieldTypeName(); propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE; } if (getAttributes) { if (field.GetIsStatic()) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_STORAGE_STATIC; } if (field.GetIsPrivate()) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PRIVATE; } if (field.GetIsProtected()) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PROTECTED; } if (field.GetIsPublic()) { propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PUBLIC; } propertyInfo[0].dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_READONLY; propertyInfo[0].dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB; #if false bool expandable; bool hasId; bool canHaveId; bool readOnly; bool error; bool sideEffect; bool overloadedContainer; bool boolean; bool booleanTrue; bool invalid; bool notAThing; bool autoExpanded; bool timeout; bool rawString; bool customViewer; bool accessNone; bool accessPrivate; bool accessProtected; bool accessPublic; bool storageNone; bool storageGlobal; bool storageStatic; bool storageRegister; bool noModifiers; bool @virtual; bool constant; bool synchronized; bool @volatile; bool dataField; bool method; bool property; bool @class; bool baseClass; bool @interface; bool innerClass; bool mostDerived; bool multiCustomViewers; #endif } } properties.Add(propertyInfo[0]); continue; } if (staticFields.Count > 0) { propertyInfo[0] = default(DEBUG_PROPERTY_INFO); JavaDebugStaticMembersPseudoProperty property = new JavaDebugStaticMembersPseudoProperty(this, referenceType, staticFields); ErrorHandler.ThrowOnFailure(property.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, propertyInfo)); properties.Add(propertyInfo[0]); } } ppEnum = new EnumDebugPropertyInfo(properties); return(VSConstants.S_OK); }