protected override DbgDotNetValue ReadValue() { var value = byRefValue.LoadIndirect(); if (value != null) { return(runtime.RecordValue(value)); } return(null); }
public override ulong GetChildCount(DbgEvaluationInfo evalInfo) { if (!initialized) { initialized = true; // Fails if it's not supported by the runtime derefValue = value.LoadIndirect().Value; Debug2.Assert((derefValue is null) == ((evalInfo.Runtime.GetDotNetRuntime().Features & DbgDotNetRuntimeFeatures.NoDereferencePointers) != 0)); } return(derefValue is not null ? 1UL : 0); }
DbgDotNetValueNode CreateValue(DbgEvaluationInfo evalInfo, DbgDotNetText name, DbgDotNetValue value, ReadOnlyCollection <string>?formatSpecifiers, DbgValueNodeEvaluationOptions options, string expression, string imageName, bool isReadOnly, bool causesSideEffects, DmdType expectedType, bool isRootExpression, ColumnFormatter?columnFormatter) { // Could be a by-ref property, local, or parameter. if (expectedType.IsByRef) { if (value.Type.IsByRef) { var newValue = value.LoadIndirect(); value.Dispose(); if (newValue.HasError) { return(CreateError(evalInfo, name, newValue.ErrorMessage !, expression, causesSideEffects)); } value = newValue.Value !; } expectedType = expectedType.GetElementType() !; } options = PredefinedFormatSpecifiers.GetValueNodeEvaluationOptions(formatSpecifiers, options); var nodeInfo = new DbgDotNetValueNodeInfo(value, expression); bool addParens = isRootExpression && NeedsParentheses(expression); DbgDotNetValueNodeProviderResult info; bool useProvider = false; var specialViewOptions = (options & ~(DbgValueNodeEvaluationOptions.ResultsView | DbgValueNodeEvaluationOptions.DynamicView)); if ((options & DbgValueNodeEvaluationOptions.ResultsView) != 0) { info = valueNodeProviderFactory.CreateResultsView(evalInfo, addParens, expectedType, nodeInfo, specialViewOptions); useProvider = !(info.ErrorMessage is null); } else if ((options & DbgValueNodeEvaluationOptions.DynamicView) != 0) { info = valueNodeProviderFactory.CreateDynamicView(evalInfo, addParens, expectedType, nodeInfo, specialViewOptions); useProvider = true; } else { info = valueNodeProviderFactory.Create(evalInfo, addParens, expectedType, nodeInfo, options); } if (useProvider) { if (!(info.ErrorMessage is null)) { return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, PredefinedDbgValueNodeImageNames.Error, true, false, null, null, info.ErrorMessage, new DbgDotNetText(new DbgDotNetTextPart(DbgTextColor.Error, info.ErrorMessage)), formatSpecifiers, columnFormatter)); } Debug2.Assert(!(info.Provider is null)); return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, info.Provider?.ImageName ?? imageName, true, false, null, null, info.ErrorMessage, info.Provider?.ValueText ?? default, formatSpecifiers, columnFormatter)); } return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, imageName, isReadOnly, causesSideEffects, expectedType, value.Type, info.ErrorMessage, default, formatSpecifiers, columnFormatter));
public void Format(DmdType type, DbgDotNetValue value) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } List <(DmdType type, DbgDotNetValue value)> arrayTypesList = null; try { if (recursionCounter++ >= MAX_RECURSION) { return; } switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.SZArray: case DmdTypeSignatureKind.MDArray: // Array types are shown in reverse order arrayTypesList = new List <(DmdType type, DbgDotNetValue value)>(); do { arrayTypesList.Add((type, arrayTypesList.Count == 0 ? value : null)); type = type.GetElementType(); } while (type.IsArray); var t = arrayTypesList[arrayTypesList.Count - 1]; Format(t.type.GetElementType(), null); foreach (var tuple in arrayTypesList) { var aryType = tuple.type; var aryValue = tuple.value; uint elementCount; if (aryType.IsVariableBoundArray) { OutputWrite(ARRAY_OPEN_PAREN, BoxedTextColor.Punctuation); int rank = Math.Min(aryType.GetArrayRank(), MAX_ARRAY_RANK); if (rank <= 0) { OutputWrite("???", BoxedTextColor.Error); } else { if (rank == 1) { OutputWrite("*", BoxedTextColor.Operator); } if (aryValue == null || aryValue.IsNull || !aryValue.GetArrayInfo(out elementCount, out var dimensionInfos)) { dimensionInfos = null; } if (ShowArrayValueSizes && dimensionInfos != null && dimensionInfos.Length == rank) { for (int i = 0; i < rank; i++) { if (i > 0) { OutputWrite(",", BoxedTextColor.Punctuation); WriteSpace(); } if (dimensionInfos[i].BaseIndex == 0) { WriteUInt32(dimensionInfos[i].Length); } else { WriteInt32(dimensionInfos[i].BaseIndex); OutputWrite("..", BoxedTextColor.Operator); WriteInt32(dimensionInfos[i].BaseIndex + (int)dimensionInfos[i].Length - 1); } } } else { OutputWrite(TypeFormatterUtils.GetArrayCommas(rank), BoxedTextColor.Punctuation); } } OutputWrite(ARRAY_CLOSE_PAREN, BoxedTextColor.Punctuation); } else { Debug.Assert(aryType.IsSZArray); OutputWrite(ARRAY_OPEN_PAREN, BoxedTextColor.Punctuation); if (ShowArrayValueSizes && aryValue != null && !aryValue.IsNull) { if (aryValue.GetArrayCount(out elementCount)) { WriteUInt32(elementCount); } } OutputWrite(ARRAY_CLOSE_PAREN, BoxedTextColor.Punctuation); } } break; case DmdTypeSignatureKind.Pointer: Format(type.GetElementType(), null); OutputWrite("*", BoxedTextColor.Operator); break; case DmdTypeSignatureKind.ByRef: OutputWrite(BYREF_KEYWORD, BoxedTextColor.Keyword); WriteSpace(); Format(type.GetElementType(), value?.LoadIndirect()); break; case DmdTypeSignatureKind.TypeGenericParameter: WriteIdentifier(type.MetadataName, BoxedTextColor.TypeGenericParameter); break; case DmdTypeSignatureKind.MethodGenericParameter: WriteIdentifier(type.MetadataName, BoxedTextColor.MethodGenericParameter); break; case DmdTypeSignatureKind.Type: case DmdTypeSignatureKind.GenericInstance: if (type.IsNullable) { Format(type.GetNullableElementType(), null); OutputWrite("?", BoxedTextColor.Operator); } else if (TypeFormatterUtils.IsTupleType(type)) { OutputWrite(TUPLE_OPEN_PAREN, BoxedTextColor.Punctuation); var tupleType = type; int tupleIndex = 0; for (;;) { tupleType = WriteTupleFields(tupleType, ref tupleIndex); if ((object)tupleType != null) { WriteCommaSpace(); } else { break; } } OutputWrite(TUPLE_CLOSE_PAREN, BoxedTextColor.Punctuation); } else { var genericArgs = type.GetGenericArguments(); int genericArgsIndex = 0; KeywordType keywordType; if ((object)type.DeclaringType == null) { keywordType = GetKeywordType(type); if (keywordType == KeywordType.NoKeyword) { WriteNamespace(type); } WriteTypeName(type, keywordType); WriteGenericArguments(type, genericArgs, ref genericArgsIndex); } else { var typesList = new List <DmdType>(); typesList.Add(type); while (type.DeclaringType != null) { type = type.DeclaringType; typesList.Add(type); } keywordType = GetKeywordType(type); if (keywordType == KeywordType.NoKeyword) { WriteNamespace(type); } for (int i = typesList.Count - 1; i >= 0; i--) { WriteTypeName(typesList[i], i == 0 ? keywordType : KeywordType.NoKeyword); WriteGenericArguments(typesList[i], genericArgs, ref genericArgsIndex); if (i != 0) { OutputWrite(".", BoxedTextColor.Operator); } } } } break; case DmdTypeSignatureKind.FunctionPointer: //TODO: OutputWrite("fnptr", BoxedTextColor.Keyword); break; default: throw new InvalidOperationException(); } } finally { recursionCounter--; if (arrayTypesList != null) { foreach (var info in arrayTypesList) { if (info.value != value) { info.value?.Dispose(); } } } } }
protected override DbgDotNetValue ReadValue() => runtime.RecordValue(pointerValue.LoadIndirect());
protected override DbgDotNetValue?ReadValue() => runtime.RecordValue(byRefValue.LoadIndirect());