提交 9e6ecbd6 编写于 作者: C Charles Stoner 提交者: GitHub

Merge pull request #13392 from cston/ee-tuples

Use Tuple syntax in EE for Type and Value
......@@ -1296,7 +1296,7 @@ internal virtual FieldSymbol FixedElementField
/// </summary>
/// <param name="tupleCardinality">If method returns true, contains cardinality of the compatible tuple type.</param>
/// <returns></returns>
public override bool IsTupleCompatible(out int tupleCardinality)
public sealed override bool IsTupleCompatible(out int tupleCardinality)
{
if (IsTupleType)
{
......
......@@ -1243,18 +1243,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' </summary>
''' <param name="tupleCardinality">If method returns true, contains cardinality of the compatible tuple type.</param>
''' <returns></returns>
Public Overrides Function IsTupleCompatible(<Out> ByRef tupleCardinality As Integer) As Boolean
Public NotOverridable Overrides Function IsTupleCompatible(<Out> ByRef tupleCardinality As Integer) As Boolean
If IsTupleType Then
tupleCardinality = 0
Return False
End If
' Should this be optimized for perf (caching for VT<0> to VT<7>, etc.)?
If (Not IsUnboundGenericType AndAlso
If Not IsUnboundGenericType AndAlso
ContainingSymbol?.Kind = SymbolKind.Namespace AndAlso
ContainingNamespace?.ContainingNamespace?.IsGlobalNamespace = True AndAlso
Name = TupleTypeSymbol.TupleTypeName AndAlso
ContainingNamespace.Name = MetadataHelpers.SystemString) Then
ContainingNamespace.Name = MetadataHelpers.SystemString Then
Dim arity = Me.Arity
......
......@@ -75,7 +75,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' PERF: if allocations here become nuisance, consider caching the results
' in the type symbols that can actually be tuple compatible
Dim cardinality As Integer
If (Not type.IsTupleCompatible(cardinality)) Then
If Not type.IsTupleCompatible(cardinality) Then
' source not a tuple or compatible
elementTypes = Nothing
Return False
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
......@@ -24,7 +25,7 @@ protected override void AppendIdentifierEscapingPotentialKeywords(StringBuilder
builder.Append(identifier);
}
protected override void AppendGenericTypeArgumentList(
protected override void AppendGenericTypeArguments(
StringBuilder builder,
Type[] typeArguments,
int typeArgumentOffset,
......
......@@ -136,6 +136,29 @@ internal override string GetCastExpression(string argument, string type, bool pa
return pooled.ToStringAndFree();
}
internal override string GetTupleExpression(string[] values)
{
Debug.Assert(values != null);
var pooled = PooledStringBuilder.GetInstance();
var builder = pooled.Builder;
builder.Append('(');
bool any = false;
foreach (var value in values)
{
if (any)
{
builder.Append(", ");
}
builder.Append(value);
any = true;
}
builder.Append(')');
return pooled.ToStringAndFree();
}
internal override string GetNamesForFlagsEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt)
{
var usedFields = ArrayBuilder<EnumField>.GetInstance();
......
......@@ -84,6 +84,7 @@
<Compile Include="NativeViewTests.cs" />
<Compile Include="ObjectIdTests.cs" />
<Compile Include="ResultsViewTests.cs" />
<Compile Include="TupleTests.cs" />
<Compile Include="TypeNameFormatterTests.cs" />
<Compile Include="TypeVariablesExpansionTests.cs" />
<Compile Include="ValueFormattingTests.cs" />
......@@ -97,4 +98,4 @@
<Import Project="..\..\Source\ResultProvider\CSharpResultProvider.projitems" Label="Shared" />
<Import Project="..\..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</Project>
</Project>
\ No newline at end of file
......@@ -3,7 +3,6 @@
using System;
using System.Collections.Immutable;
using System.Reflection;
using Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
......
......@@ -230,10 +230,7 @@ class C
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type,
evalFlags: DkmEvaluationResultFlags.None);
var value = type.Instantiate();
var evalResult = FormatResult("o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......
......@@ -605,7 +605,7 @@ class B
using (runtime.Load())
{
var type = runtime.GetType("B");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", value);
var children = GetChildren(evalResult);
Verify(children,
......
......@@ -18,7 +18,7 @@ public void Simple()
{
var value = CreateDkmClrValue(new object());
var rootExpr = "d";
var evalResult = FormatResult(rootExpr, rootExpr, value, declaredType: new DkmClrType((TypeImpl)typeof(object)), declaredTypeInfo: new[] { true });
var evalResult = FormatResult(rootExpr, rootExpr, value, declaredType: new DkmClrType((TypeImpl)typeof(object)), declaredTypeInfo: DynamicFlagsCustomTypeInfo.Create(true).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{object}", "dynamic {object}", rootExpr));
}
......@@ -62,7 +62,7 @@ class C<T, U>
var typeC_Constructed2 = typeC.MakeGenericType(typeof(object), typeC_Constructed1); // C<dynamic, C<object, dynamic>> (i.e. T = dynamic, U = C<object, dynamic>)
var value = CreateDkmClrValue(Activator.CreateInstance(typeC_Constructed2));
var rootExpr = "c";
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed2), new[] { false, true, false, false, true });
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed2), DynamicFlagsCustomTypeInfo.Create(false, true, false, false, true).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{C<object, C<object, object>>}", "C<dynamic, C<object, dynamic>> {C<object, C<object, object>>}", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
......@@ -91,7 +91,7 @@ class Inner<U>
var typeInner_Constructed = typeInner.MakeGenericType(typeof(object), typeof(object)); // Outer<dynamic>.Inner<object>
var value = CreateDkmClrValue(Activator.CreateInstance(typeInner_Constructed));
var rootExpr = "i";
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeInner_Constructed), new[] { false, true, false });
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeInner_Constructed), DynamicFlagsCustomTypeInfo.Create(false, true, false).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{Outer<object>.Inner<object>}", "Outer<dynamic>.Inner<object> {Outer<object>.Inner<object>}", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
......@@ -126,7 +126,7 @@ class D<T, U, V>
var typeC_Constructed = typeC.MakeGenericType(typeD_Constructed); // C<D<object, dynamic, int>>
var value = CreateDkmClrValue(Activator.CreateInstance(typeC_Constructed));
var rootExpr = "c";
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed), new[] { false, false, false, true, false });
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed), DynamicFlagsCustomTypeInfo.Create(false, false, false, true, false).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{C<D<object, object, int>>}", "C<D<object, dynamic, int>> {C<D<object, object, int>>}", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
......@@ -171,7 +171,7 @@ class C<T, U> : I<long, T>, I<bool, U>
var typeC_Constructed = typeC.MakeGenericType(typeof(object), typeof(object)); // C<dynamic, object>
var value = CreateDkmClrValue(Activator.CreateInstance(typeC_Constructed));
var rootExpr = "c";
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed), new[] { false, true, false });
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeC_Constructed), DynamicFlagsCustomTypeInfo.Create(false, true, false).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{C<object, object>}", "C<dynamic, object> {C<object, object>}", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
......@@ -206,7 +206,7 @@ class Derived<T, U> : Base<T, U, object, dynamic>
var typeDerived_Constructed = typeDerived.MakeGenericType(typeof(object), typeof(object)); // Derived<dynamic, object>
var value = CreateDkmClrValue(Activator.CreateInstance(typeDerived_Constructed));
var rootExpr = "d";
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeDerived_Constructed), new[] { false, true, false });
var evalResult = FormatResult(rootExpr, rootExpr, value, new DkmClrType((TypeImpl)typeDerived_Constructed), DynamicFlagsCustomTypeInfo.Create(false, true, false).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{Derived<object, object>}", "Derived<dynamic, object> {Derived<object, object>}", rootExpr, DkmEvaluationResultFlags.Expandable));
......@@ -228,7 +228,7 @@ public void ArrayElement()
{
var value = CreateDkmClrValue(new object[1]);
var rootExpr = "d";
var evalResult = FormatResult(rootExpr, rootExpr, value, declaredType: new DkmClrType((TypeImpl)typeof(object[])), declaredTypeInfo: new[] { false, true });
var evalResult = FormatResult(rootExpr, rootExpr, value, declaredType: new DkmClrType((TypeImpl)typeof(object[])), declaredTypeInfo: DynamicFlagsCustomTypeInfo.Create(false, true).GetCustomTypeInfo());
Verify(evalResult,
EvalResult(rootExpr, "{object[1]}", "dynamic[] {object[]}", rootExpr, DkmEvaluationResultFlags.Expandable));
var children = GetChildren(evalResult);
......@@ -250,7 +250,7 @@ public void TypeVariables()
var assembly = ReflectionUtilities.Load(assemblyBytes);
var reflectionType = assembly.GetType(ExpressionCompilerConstants.TypeVariablesClassName).MakeGenericType(new[] { typeof(object), typeof(object), typeof(object[]) });
var value = CreateDkmClrValue(value: null, type: reflectionType, valueFlags: DkmClrValueFlags.Synthetic);
var evalResult = FormatResult("typevars", "typevars", value, new DkmClrType((TypeImpl)reflectionType), new[] { false, true, false, false, true });
var evalResult = FormatResult("typevars", "typevars", value, new DkmClrType((TypeImpl)reflectionType), DynamicFlagsCustomTypeInfo.Create(false, true, false, false, true).GetCustomTypeInfo());
Verify(evalResult,
EvalResult("Type variables", "", "", null, DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data));
var children = GetChildren(evalResult);
......
......@@ -1561,7 +1561,7 @@ S This
using (runtime.Load())
{
var type = runtime.GetType("S");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var children = GetChildren(FormatResult("s", value));
Verify(children,
EvalResult(
......@@ -1609,7 +1609,7 @@ class E : System.Exception
using (runtime.Load())
{
var type = runtime.GetType("S");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var children = GetChildren(FormatResult("s", value));
Verify(children,
EvalResult("This", "'s.This' threw an exception of type 'E'", "S {E}", "s.This", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown),
......@@ -1651,9 +1651,9 @@ public void ExceptionThrownFlag_Nullable()
{
var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib());
var type = runtime.GetType(typeof(NullReferenceException));
var value = CreateDkmClrValue(
type.Instantiate(),
type: type,
var value = type.Instantiate(
new object[0],
alias: null,
evalFlags: DkmEvaluationResultFlags.ExceptionThrown);
var evalResult = FormatResult("c?.str.Length", value, runtime.GetType(typeof(int?)));
Verify(evalResult,
......@@ -1813,7 +1813,7 @@ class C
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -2204,7 +2204,7 @@ public void DoNotCopyParentState()
using (runtime.Load())
{
var type = runtime.GetType("B");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
// Format with "Just my code".
var inspectionContext = CreateDkmInspectionContext(DkmEvaluationFlags.HideNonPublicMembers, runtimeInstance: runtime);
var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
......@@ -2256,7 +2256,7 @@ public void NullableValue_Error()
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var memberValue = value.GetMemberValue("P", (int)System.Reflection.MemberTypes.Property, "C", DefaultInspectionContext);
var evalResult = FormatResult("o.P", memberValue);
Verify(evalResult,
......@@ -2278,7 +2278,7 @@ public void RootCastExpression()
var typeC = runtime.GetType("C");
// var o = (object)new C(); var e = (C)o;
var value = CreateDkmClrValue(typeC.Instantiate());
var value = typeC.Instantiate();
var evalResult = FormatResult("(C)o", value);
Verify(evalResult,
EvalResult("(C)o", "{C}", "C", "(C)o", DkmEvaluationResultFlags.Expandable));
......@@ -2287,7 +2287,7 @@ public void RootCastExpression()
EvalResult("F", "3", "object {int}", "((C)o).F"));
// var c = new C(); var e = (C)((object)c);
value = CreateDkmClrValue(typeC.Instantiate());
value = typeC.Instantiate();
evalResult = FormatResult("(C)((object)c)", value);
Verify(evalResult,
EvalResult("(C)((object)c)", "{C}", "C", "(C)((object)c)", DkmEvaluationResultFlags.Expandable));
......@@ -2296,7 +2296,7 @@ public void RootCastExpression()
EvalResult("F", "3", "object {int}", "((C)((object)c)).F"));
// var a = (object)new[] { new C() }; var e = ((C[])o)[0];
value = CreateDkmClrValue(typeC.Instantiate());
value = typeC.Instantiate();
evalResult = FormatResult("((C[])o)[0]", value);
Verify(evalResult,
EvalResult("((C[])o)[0]", "{C}", "C", "((C[])o)[0]", DkmEvaluationResultFlags.Expandable));
......@@ -2350,7 +2350,7 @@ class C
int n = 10;
var type = runtime.GetType("C");
// C[] with alternating null and non-null values.
var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => (i % 2) == 0 ? type.Instantiate() : null).ToArray());
var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => (i % 2) == 0 ? type.UnderlyingType.Instantiate() : null).ToArray());
var evalResult = FormatResult("a", value);
IDkmClrResultProvider resultProvider = new CSharpResultProvider();
......@@ -2397,7 +2397,7 @@ object P
int n = 10;
int nFailures = 2;
var type = runtime.GetType("C");
var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => type.Instantiate(i)).ToArray());
var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => type.UnderlyingType.Instantiate(i)).ToArray());
var evalResult = FormatResult("a", value);
IDkmClrResultProvider resultProvider = new CSharpResultProvider();
......
......@@ -156,9 +156,7 @@ class C
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoQuotes));
Verify(evalResult,
EvalResult("o", "f+103 g", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -229,9 +227,7 @@ static void Main()
var type = runtime.GetType("C");
// Non-null value.
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", "o, raw", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ShowValueRaw));
Verify(evalResult,
EvalResult("o", "{C}", "C", "o, raw", DkmEvaluationResultFlags.Expandable));
......@@ -319,9 +315,7 @@ public IEnumerator GetEnumerator()
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", "o, results, d", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
EvalResult("o", "{C}", "C", "o, results, d", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Method));
......@@ -359,9 +353,7 @@ IEnumerator IEnumerable.GetEnumerator()
using (runtime.Load())
{
var type = runtime.GetType("S`1").MakeGenericType(runtime.GetType(typeof(int)));
var value = CreateDkmClrValue(
value: type.Instantiate(2),
type: type);
var value = type.Instantiate(2);
var evalResult = FormatResult("o", "o, results", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
EvalResult("o", "{S<int>}", "S<int>", "o, results", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Method));
......@@ -399,7 +391,7 @@ int H
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", "o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -449,9 +441,7 @@ public object F
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", "o, results", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
EvalResult("o", "{C}", "C", "o, results", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Method));
......@@ -486,7 +476,7 @@ internal ArrayList Q
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var memberValue = value.GetMemberValue("P", (int)System.Reflection.MemberTypes.Property, "C", DefaultInspectionContext);
var evalResult = FormatResult("o.P", "o.P, results", memberValue, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
......@@ -536,7 +526,7 @@ internal int Q
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var memberValue = value.GetMemberValue("P", (int)System.Reflection.MemberTypes.Property, "C", DefaultInspectionContext);
var evalResult = FormatResult("o.P", "o.P, results", memberValue, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
......@@ -564,9 +554,7 @@ public IEnumerator GetEnumerator()
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(
value: type.Instantiate(),
type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", "o, results", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.ResultsOnly));
Verify(evalResult,
EvalFailedResult("o", "Results View requires System.Core.dll to be referenced"));
......
......@@ -58,7 +58,7 @@ internal C(long p)
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(ptr), type);
var value = type.Instantiate(ptr);
var evalResult = FormatResult("o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Other));
......
......@@ -1440,7 +1440,7 @@ internal IEnumerable Q
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -1489,7 +1489,7 @@ internal ArrayList P
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var memberValue = value.GetMemberValue("P", (int)System.Reflection.MemberTypes.Property, "C", DefaultInspectionContext);
var evalResult = FormatResult("o.P", memberValue);
Verify(evalResult,
......@@ -1525,7 +1525,7 @@ public IEnumerator GetEnumerator()
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = CreateDkmClrValue(type.Instantiate(), type: type);
var value = type.Instantiate();
var evalResult = FormatResult("o", value);
Verify(evalResult,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
......@@ -1569,7 +1569,7 @@ class C
using (runtime.Load())
{
var type = runtime.GetType("C");
var value = type.Instantiate();
var value = type.UnderlyingType.Instantiate();
// IEnumerable
var evalResult = FormatPropertyValue(runtime, value, "P");
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
// Implementation for "displaying type name as string" aspect of default (C#) Formatter component
// Implementation for "displaying type name as string" aspect of the Formatter component
internal abstract partial class Formatter
{
/// <returns>The qualified name (i.e. including containing types and namespaces) of a named,
......@@ -84,9 +84,7 @@ internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIde
Debug.Assert(pointerCount == 0 || nullableCount == 0, "Benign: pointer to nullable?");
int oldLength = builder.Length;
AppendQualifiedTypeNameInternal(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, out sawInvalidIdentifier);
string name = builder.ToString(oldLength, builder.Length - oldLength);
builder.Append('?', nullableCount);
builder.Append('*', pointerCount);
......@@ -134,9 +132,16 @@ internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIde
return;
}
int cardinality;
if (type.IsTupleCompatible(out cardinality))
{
AppendTupleFields(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, out sawInvalidIdentifier);
return;
}
// Note: in the Reflection/LMR object model, all type arguments are on the most nested type.
var hasTypeArguments = type.IsGenericType;
var typeArguments = type.IsGenericType
var typeArguments = hasTypeArguments
? type.GetGenericArguments()
: null;
Debug.Assert(hasTypeArguments == (typeArguments != null));
......@@ -145,6 +150,8 @@ internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIde
sawInvalidIdentifier = false;
bool sawSingleInvalidIdentifier;
var typeArgumentOffset = 0;
if (type.IsNested)
{
// Push from inside, out.
......@@ -163,8 +170,6 @@ internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIde
AppendNamespacePrefix(builder, stack[lastContainingTypeIndex], escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
var typeArgumentOffset = 0;
// Pop from outside, in.
for (int i = lastContainingTypeIndex; i >= 0; i--)
{
......@@ -181,17 +186,15 @@ internal string GetTypeName(TypeAndCustomInfo typeAndInfo, bool escapeKeywordIde
}
stack.Free();
AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, typeArgumentOffset, numTypeArguments - typeArgumentOffset, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
}
else
{
AppendNamespacePrefix(builder, type, escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, 0, numTypeArguments, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
}
AppendUnqualifiedTypeName(builder, type, dynamicFlags, ref index, escapeKeywordIdentifiers, typeArguments, typeArgumentOffset, numTypeArguments - typeArgumentOffset, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
}
/// <summary>
......@@ -284,10 +287,50 @@ private void AppendNamespacePrefix(StringBuilder builder, Type type, bool escape
AppendIdentifier(builder, escapeKeywordIdentifiers, unmangledName, out sawInvalidIdentifier);
bool argumentsSawInvalidIdentifier;
AppendGenericTypeArgumentList(builder, typeArguments, typeArgumentOffset, dynamicFlags, ref index, arity, escapeKeywordIdentifiers, out argumentsSawInvalidIdentifier);
AppendGenericTypeArguments(builder, typeArguments, typeArgumentOffset, dynamicFlags, ref index, arity, escapeKeywordIdentifiers, out argumentsSawInvalidIdentifier);
sawInvalidIdentifier |= argumentsSawInvalidIdentifier;
}
private void AppendTupleFields(
StringBuilder builder,
Type type,
DynamicFlagsCustomTypeInfo dynamicFlags,
ref int index,
bool escapeKeywordIdentifiers,
out bool sawInvalidIdentifier)
{
sawInvalidIdentifier = false;
builder.Append('(');
bool any = false;
while (true)
{
var typeArguments = type.GetGenericArguments();
int nTypeArgs = typeArguments.Length;
Debug.Assert(nTypeArgs > 0);
Debug.Assert(nTypeArgs <= TypeHelpers.TupleFieldRestPosition);
int nFields = Math.Min(nTypeArgs, TypeHelpers.TupleFieldRestPosition - 1);
for (int i = 0; i < nFields; i++)
{
if (any)
{
builder.Append(", ");
}
bool sawSingleInvalidIdentifier;
AppendQualifiedTypeName(builder, typeArguments[i], dynamicFlags, ref index, escapeKeywordIdentifiers, out sawSingleInvalidIdentifier);
sawInvalidIdentifier |= sawSingleInvalidIdentifier;
any = true;
}
if (nTypeArgs < TypeHelpers.TupleFieldRestPosition)
{
break;
}
Debug.Assert(!dynamicFlags[index]);
index++;
type = typeArguments[nTypeArgs - 1];
}
builder.Append(')');
}
protected void AppendIdentifier(StringBuilder builder, bool escapeKeywordIdentifiers, string identifier, out bool sawInvalidIdentifier)
{
if (escapeKeywordIdentifiers)
......@@ -305,7 +348,7 @@ protected void AppendIdentifier(StringBuilder builder, bool escapeKeywordIdentif
protected abstract void AppendIdentifierEscapingPotentialKeywords(StringBuilder builder, string identifier, out bool sawInvalidIdentifier);
protected abstract void AppendGenericTypeArgumentList(
protected abstract void AppendGenericTypeArguments(
StringBuilder builder,
Type[] typeArguments,
int typeArgumentOffset,
......
......@@ -21,7 +21,7 @@ internal enum GetValueFlags
IncludeObjectId = 0x2,
}
// This class provides implementation for the "displaying values as strings" aspect of the default (C#) Formatter component.
// This class provides implementation for the "displaying values as strings" aspect of the Formatter component.
internal abstract partial class Formatter
{
private string GetValueString(DkmClrValue value, DkmInspectionContext inspectionContext, ObjectDisplayOptions options, GetValueFlags flags)
......@@ -100,6 +100,19 @@ private string GetValueString(DkmClrValue value, DkmInspectionContext inspection
? _nullString
: GetValueString(nullableValue, inspectionContext, ObjectDisplayOptions.None, GetValueFlags.IncludeTypeName);
}
else
{
int cardinality;
if (lmrType.IsTupleCompatible(out cardinality))
{
var values = ArrayBuilder<string>.GetInstance();
value.GetTupleFieldValues(cardinality, values, inspectionContext);
return IncludeObjectId(
value,
GetTupleExpression(values.ToArrayAndFree()),
flags);
}
}
// "value.EvaluateToString()" will check "Call string-conversion function on objects in variables windows"
// (Tools > Options setting) and call "value.ToString()" if appropriate.
......@@ -403,6 +416,8 @@ private static string IncludeObjectId(DkmClrValue value, string valueStr, GetVal
internal abstract string GetObjectCreationExpression(string type, string arguments);
internal abstract string GetTupleExpression(string[] values);
internal abstract string FormatLiteral(char c, ObjectDisplayOptions options);
internal abstract string FormatLiteral(int value, ObjectDisplayOptions options);
......
......@@ -347,6 +347,79 @@ internal static DkmClrValue GetNullableValue(this DkmClrValue value, DkmInspecti
return value.GetFieldValue(InternalWellKnownMemberNames.NullableValue, inspectionContext);
}
internal const int TupleFieldRestPosition = 8;
private const string TupleTypeNamePrefix = "ValueTuple`";
private const string TupleFieldItemNamePrefix = "Item";
private const string TupleFieldRestName = "Rest";
// See NamedTypeSymbol.IsTupleCompatible.
internal static bool IsTupleCompatible(this Type type, out int cardinality)
{
if (type.IsTupleCompatibleInternal(out cardinality) &&
cardinality > 1) // ValueTuple<T> is not a tuple.
{
return true;
}
cardinality = 0;
return false;
}
private static bool IsTupleCompatibleInternal(this Type type, out int cardinality)
{
if (type.IsGenericType &&
AreNamesEqual(type.Namespace, "System") &&
type.Name.StartsWith(TupleTypeNamePrefix, StringComparison.Ordinal))
{
var typeArguments = type.GetGenericArguments();
int n = typeArguments.Length;
if ((n > 0) && (n <= TupleFieldRestPosition))
{
if (!AreNamesEqual(type.Name, TupleTypeNamePrefix + n))
{
cardinality = 0;
return false;
}
if (n < TupleFieldRestPosition)
{
cardinality = n;
return true;
}
var restType = typeArguments[n - 1];
int restCardinality;
if (restType.IsTupleCompatibleInternal(out restCardinality))
{
cardinality = n - 1 + restCardinality;
return true;
}
}
}
cardinality = 0;
return false;
}
internal static void GetTupleFieldValues(this DkmClrValue tuple, int cardinality, ArrayBuilder<string> values, DkmInspectionContext inspectionContext)
{
while (true)
{
int n = Math.Min(cardinality, TupleFieldRestPosition - 1);
for (int i = 0; i < n; i++)
{
var value = GetFieldValue(tuple, TupleFieldItemNamePrefix + (i + 1), inspectionContext);
var str = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers);
values.Add(str);
}
cardinality -= n;
if (cardinality == 0)
{
return;
}
tuple = GetFieldValue(tuple, TupleFieldRestName, inspectionContext);
}
}
internal static Type GetBaseTypeOrNull(this Type underlyingType, DkmClrAppDomain appDomain, out DkmClrType type)
{
Debug.Assert((underlyingType.BaseType != null) || underlyingType.IsPointer || underlyingType.IsArray, "BaseType should only return null if the underlyingType is a pointer or array.");
......@@ -648,8 +721,13 @@ internal static bool IsType(this Type type, string @namespace, string name)
{
Debug.Assert((@namespace == null) || (@namespace.Length > 0)); // Type.Namespace is null not empty.
Debug.Assert(!string.IsNullOrEmpty(name));
return string.Equals(type.Namespace, @namespace, StringComparison.Ordinal) &&
string.Equals(type.Name, name, StringComparison.Ordinal);
return AreNamesEqual(type.Namespace, @namespace) &&
AreNamesEqual(type.Name, name);
}
private static bool AreNamesEqual(string nameA, string nameB)
{
return string.Equals(nameA, nameB, StringComparison.Ordinal);
}
internal static MemberInfo GetOriginalDefinition(this MemberInfo member)
......
......@@ -70,7 +70,7 @@ internal DkmClrType GetType(System.Type type)
return new DkmClrType(module, _appDomain, (TypeImpl)type);
}
internal DkmClrType GetType(string typeName)
internal DkmClrType GetType(string typeName, params System.Type[] typeArguments)
{
foreach (var module in this.Modules)
{
......@@ -78,7 +78,12 @@ internal DkmClrType GetType(string typeName)
var type = assembly.GetType(typeName);
if (type != null)
{
return new DkmClrType(module, _appDomain, (TypeImpl)type);
var result = new DkmClrType(module, _appDomain, (TypeImpl)type);
if (typeArguments.Length > 0)
{
result = result.MakeGenericType(typeArguments.Select(this.GetType).ToArray());
}
return result;
}
}
return null;
......
......@@ -10,6 +10,7 @@
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using Microsoft.VisualStudio.Debugger.Metadata;
using Roslyn.Utilities;
......@@ -57,6 +58,11 @@ public DkmClrType ElementType
}
}
internal System.Type UnderlyingType
{
get { return ((TypeImpl)_lmrType).Type; }
}
internal DkmClrType MakeGenericType(params DkmClrType[] genericArguments)
{
var type = new DkmClrType(
......@@ -75,10 +81,25 @@ internal DkmClrType MakeArrayType()
_lmrType.MakeArrayType());
}
internal object Instantiate(params object[] args)
internal DkmClrValue Instantiate(params object[] args)
{
return Instantiate(args, null, DkmEvaluationResultFlags.None);
}
internal DkmClrValue Instantiate(
object[] args,
string alias,
DkmEvaluationResultFlags evalFlags)
{
var t = ((TypeImpl)_lmrType).Type;
return t.Instantiate(args);
object value = UnderlyingType.Instantiate(args);
return new DkmClrValue(
value,
DkmClrValue.GetHostObjectValue(_lmrType, value),
this,
alias: alias,
evalFlags: evalFlags,
valueFlags: DkmClrValueFlags.None,
nativeComPointer: 0);
}
private static readonly ReadOnlyCollection<DkmClrType> s_emptyTypes = new ReadOnlyCollection<DkmClrType>(new DkmClrType[0]);
......
......@@ -141,7 +141,7 @@ public string GetValueString(DkmInspectionContext inspectionContext, ReadOnlyCol
throw new ArgumentNullException(nameof(inspectionContext));
}
return inspectionContext.InspectionSession.InvokeFormatter(MethodId.GetValueString, f => f.GetValueString(this, inspectionContext, formatSpecifiers));
return inspectionContext.InspectionSession.InvokeFormatter(this, MethodId.GetValueString, f => f.GetValueString(this, inspectionContext, formatSpecifiers));
}
public bool HasUnderlyingString(DkmInspectionContext inspectionContext)
......@@ -151,7 +151,7 @@ public bool HasUnderlyingString(DkmInspectionContext inspectionContext)
throw new ArgumentNullException(nameof(inspectionContext));
}
return inspectionContext.InspectionSession.InvokeFormatter(MethodId.HasUnderlyingString, f => f.HasUnderlyingString(this, inspectionContext));
return inspectionContext.InspectionSession.InvokeFormatter(this, MethodId.HasUnderlyingString, f => f.HasUnderlyingString(this, inspectionContext));
}
public string GetUnderlyingString(DkmInspectionContext inspectionContext)
......@@ -161,7 +161,7 @@ public string GetUnderlyingString(DkmInspectionContext inspectionContext)
throw new ArgumentNullException(nameof(inspectionContext));
}
return inspectionContext.InspectionSession.InvokeFormatter(MethodId.GetUnderlyingString, f => f.GetUnderlyingString(this, inspectionContext));
return inspectionContext.InspectionSession.InvokeFormatter(this, MethodId.GetUnderlyingString, f => f.GetUnderlyingString(this, inspectionContext));
}
public void GetResult(
......@@ -175,6 +175,7 @@ public string GetUnderlyingString(DkmInspectionContext inspectionContext)
DkmCompletionRoutine<DkmEvaluationAsyncResult> CompletionRoutine)
{
InspectionContext.InspectionSession.InvokeResultProvider(
this,
MethodId.GetResult,
r =>
{
......
......@@ -43,6 +43,7 @@ public abstract class DkmEvaluationResult : DkmDataContainer
public void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine)
{
InspectionContext.InspectionSession.InvokeResultProvider(
this,
MethodId.GetChildren,
r =>
{
......@@ -53,7 +54,7 @@ public void GetChildren(DkmWorkList workList, int initialRequestSize, DkmInspect
public string GetUnderlyingString()
{
return InspectionContext.InspectionSession.InvokeResultProvider(MethodId.GetUnderlyingString, r => r.GetUnderlyingString(this));
return InspectionContext.InspectionSession.InvokeResultProvider(this, MethodId.GetUnderlyingString, r => r.GetUnderlyingString(this));
}
}
}
......@@ -34,6 +34,7 @@ public static DkmEvaluationResultEnumContext Create(int Count, DkmStackWalkFrame
public void GetItems(DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine<DkmEvaluationEnumAsyncResult> completionRoutine)
{
InspectionContext.InspectionSession.InvokeResultProvider(
this,
MethodId.GetItems,
r =>
{
......
......@@ -58,7 +58,7 @@ internal DkmInspectionContext(DkmInspectionSession inspectionSession, DkmEvaluat
public string GetTypeName(DkmClrType ClrType, DkmClrCustomTypeInfo CustomTypeInfo, ReadOnlyCollection<string> FormatSpecifiers)
{
return InspectionSession.InvokeFormatter(MethodId.GetTypeName, f => f.GetTypeName(this, ClrType, CustomTypeInfo, FormatSpecifiers));
return InspectionSession.InvokeFormatter(this, MethodId.GetTypeName, f => f.GetTypeName(this, ClrType, CustomTypeInfo, FormatSpecifiers));
}
}
......
......@@ -34,34 +34,50 @@ internal DkmInspectionSession(ImmutableArray<IDkmClrFormatter> formatters, Immut
_resultProviders = new Dispatcher<IDkmClrResultProvider>(resultProviders);
}
internal T InvokeFormatter<T>(MethodId method, Func<IDkmClrFormatter, T> f)
internal T InvokeFormatter<T>(object instance, MethodId method, Func<IDkmClrFormatter, T> f)
{
return _formatters.Invoke(method, f);
return _formatters.Invoke(instance, method, f);
}
internal T InvokeResultProvider<T>(MethodId method, Func<IDkmClrResultProvider, T> f)
internal T InvokeResultProvider<T>(object instance, MethodId method, Func<IDkmClrResultProvider, T> f)
{
return _resultProviders.Invoke(method, f);
return _resultProviders.Invoke(instance, method, f);
}
private sealed class Dispatcher<TInterface>
{
private struct InstanceAndMethod
{
internal InstanceAndMethod(object instance, MethodId method)
{
Instance = instance;
Method = method;
}
internal readonly object Instance;
internal readonly MethodId Method;
internal bool Equals(InstanceAndMethod other)
{
return Instance == other.Instance && Method == other.Method;
}
}
private readonly ImmutableArray<TInterface> _implementations;
private readonly ArrayBuilder<MethodId> _calls;
private readonly ArrayBuilder<InstanceAndMethod> _calls;
internal Dispatcher(ImmutableArray<TInterface> items)
{
_implementations = items;
_calls = new ArrayBuilder<MethodId>();
_calls = new ArrayBuilder<InstanceAndMethod>();
}
internal TResult Invoke<TResult>(MethodId method, Func<TInterface, TResult> f)
internal TResult Invoke<TResult>(object instance, MethodId method, Func<TInterface, TResult> f)
{
// If the last n - 1 calls are to the same method,
// call the n-th implementation.
var instanceAndMethod = new InstanceAndMethod(instance, method);
int n = _calls.Count;
int index = 0;
while ((n - index > 0) && (_calls[n - index - 1] == method))
while ((n - index > 0) && _calls[n - index - 1].Equals(instanceAndMethod))
{
index++;
}
......@@ -70,7 +86,7 @@ internal TResult Invoke<TResult>(MethodId method, Func<TInterface, TResult> f)
throw new InvalidOperationException();
}
var item = _implementations[index];
_calls.Push(method);
_calls.Push(instanceAndMethod);
try
{
return f(item);
......
......@@ -87,7 +87,7 @@ public class DkmSuccessEvaluationResult : DkmEvaluationResult
public DkmClrValue GetClrValue()
{
return InspectionContext.InspectionSession.InvokeResultProvider(MethodId.GetClrValue, r => r.GetClrValue(this));
return InspectionContext.InspectionSession.InvokeResultProvider(this, MethodId.GetClrValue, r => r.GetClrValue(this));
}
}
}
......@@ -158,7 +158,7 @@ internal DkmEvaluationResult FormatResult(string name, DkmClrValue value, DkmClr
return FormatResult(name, name, value, declaredType, inspectionContext: inspectionContext);
}
internal DkmEvaluationResult FormatResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, bool[] declaredTypeInfo = null, DkmInspectionContext inspectionContext = null)
internal DkmEvaluationResult FormatResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmClrCustomTypeInfo declaredTypeInfo = null, DkmInspectionContext inspectionContext = null)
{
var asyncResult = FormatAsyncResult(name, fullName, value, declaredType, declaredTypeInfo, inspectionContext);
var exception = asyncResult.Exception;
......@@ -169,14 +169,14 @@ internal DkmEvaluationResult FormatResult(string name, string fullName, DkmClrVa
return asyncResult.Result;
}
internal DkmEvaluationAsyncResult FormatAsyncResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, bool[] declaredTypeInfo = null, DkmInspectionContext inspectionContext = null)
internal DkmEvaluationAsyncResult FormatAsyncResult(string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmClrCustomTypeInfo declaredTypeInfo = null, DkmInspectionContext inspectionContext = null)
{
DkmEvaluationAsyncResult asyncResult = default(DkmEvaluationAsyncResult);
var workList = new DkmWorkList();
value.GetResult(
workList,
DeclaredType: declaredType ?? value.Type,
CustomTypeInfo: DynamicFlagsCustomTypeInfo.Create(declaredTypeInfo).GetCustomTypeInfo(),
CustomTypeInfo: declaredTypeInfo,
InspectionContext: inspectionContext ?? DefaultInspectionContext,
FormatSpecifiers: Formatter.NoFormatSpecifiers,
ResultName: name,
......
......@@ -26,7 +26,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End If
End Sub
Protected Overrides Sub AppendGenericTypeArgumentList(
Protected Overrides Sub AppendGenericTypeArguments(
builder As StringBuilder,
typeArguments() As Type,
typeArgumentOffset As Integer,
......
......@@ -91,6 +91,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Return pooled.ToStringAndFree()
End Function
Friend Overrides Function GetTupleExpression(values() As String) As String
Debug.Assert(values IsNot Nothing)
Dim pooled = PooledStringBuilder.GetInstance()
Dim builder = pooled.Builder
builder.Append("("c)
Dim any As Boolean = False
For Each value In values
If any Then
builder.Append(", ")
End If
builder.Append(value)
any = True
Next
builder.Append(")"c)
Return pooled.ToStringAndFree()
End Function
Friend Overrides Function GetNamesForFlagsEnumValue(fields As ArrayBuilder(Of EnumField), value As Object, underlyingValue As ULong, options As ObjectDisplayOptions, typeToDisplayOpt As Type) As String
Dim usedFields = ArrayBuilder(Of EnumField).GetInstance()
FillUsedEnumFields(usedFields, fields, underlyingValue)
......
......@@ -71,6 +71,7 @@
<Compile Include="Helpers\TestTypeExtensions.vb" />
<Compile Include="ObjectIdTests.vb" />
<Compile Include="ResultsViewTests.vb" />
<Compile Include="TupleTests.vb" />
<Compile Include="TypeNameFormatterTests.vb" />
<Compile Include="TypeVariablesExpansionTests.vb" />
<Compile Include="ValueFormatterTests.vb" />
......@@ -85,4 +86,4 @@
<Import Project="..\..\Source\ResultProvider\BasicResultProvider.projitems" Label="Shared" />
<Import Project="..\..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</Project>
</Project>
\ No newline at end of file
......@@ -126,7 +126,7 @@ End Class"
runtime = New DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(GetAssembly(source)), getMemberValue:=getMemberValue)
Using runtime.Load()
Dim type = runtime.GetType("C")
Dim value = CreateDkmClrValue(type.Instantiate(), type:=type)
Dim value = type.Instantiate()
Dim result = FormatResult("o", value)
Verify(result,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable))
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Microsoft.VisualStudio.Debugger.Clr
Imports Microsoft.VisualStudio.Debugger.Evaluation
Imports System.Collections.Immutable
Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
Public Class TupleTests
Inherits VisualBasicResultProviderTestBase
<Fact>
Public Sub LongTuple()
Const source =
"Class C
Private _17 As (Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short) =
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
End Class"
Dim assembly0 = GenerateTupleAssembly()
Dim reference0 = AssemblyMetadata.CreateFromImage(assembly0).GetReference()
Dim compilation1 = CreateCompilationWithMscorlib({source}, options:=TestOptions.ReleaseDll, references:={reference0}, assemblyName:=GetUniqueName())
Dim assembly1 = compilation1.EmitToArray()
Dim runtime = New DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(ReflectionUtilities.Load(assembly0), ReflectionUtilities.Load(assembly1)))
Using runtime.Load()
Dim type = runtime.GetType("C")
Dim value = type.Instantiate()
Dim result = FormatResult("o", value)
Verify(result,
EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable))
Dim children = GetChildren(result)
Verify(children,
EvalResult(
"_17",
"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)",
"(Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short, Short)",
"o._17",
DkmEvaluationResultFlags.Expandable))
children = GetChildren(children(0))
Assert.Equal(8, children.Length) ' Should be 18. https://github.com/dotnet/roslyn/issues/13421
Dim child = children(children.Length - 1)
Verify(child,
EvalResult(
"Rest",
"(8, 9, 10, 11, 12, 13, 14, 15, 16, 17)",
"(Short, Short, Short, Short, Short, Short, Short, Short, Short, Short)",
"o._17.Rest",
DkmEvaluationResultFlags.Expandable))
children = GetChildren(child)
Assert.Equal(8, children.Length) ' Should be 11. https://github.com/dotnet/roslyn/issues/13421
child = children(children.Length - 1)
Verify(child,
EvalResult(
"Rest",
"(15, 16, 17)",
"(Short, Short, Short)",
"o._17.Rest.Rest",
DkmEvaluationResultFlags.Expandable))
End Using
End Sub
Private Shared Function GenerateTupleAssembly() As ImmutableArray(Of Byte)
Const source =
"Namespace System
Public Structure ValueTuple(Of T1)
Public Item1 As T1
Public Sub New(_1 As T1)
Item1 = _1
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2)
Public Item1 As T1
Public Item2 As T2
Public Sub New(_1 As T1, _2 As T2)
Item1 = _1
Item2 = _2
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Sub New(_1 As T1, _2 As T2, _3 As T3)
Item1 = _1
Item2 = _2
Item3 = _3
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Item4 As T4
Public Sub New(_1 As T1, _2 As T2, _3 As T3, _4 As T4)
Item1 = _1
Item2 = _2
Item3 = _3
Item4 = _4
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4, T5)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Item4 As T4
Public Item5 As T5
Public Sub New(_1 As T1, _2 As T2, _3 As T3, _4 As T4, _5 As T5)
Item1 = _1
Item2 = _2
Item3 = _3
Item4 = _4
Item5 = _5
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4, T5, T6)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Item4 As T4
Public Item5 As T5
Public Item6 As T6
Public Sub New(_1 As T1, _2 As T2, _3 As T3, _4 As T4, _5 As T5, _6 As T6)
Item1 = _1
Item2 = _2
Item3 = _3
Item4 = _4
Item5 = _5
Item6 = _6
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4, T5, T6, T7)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Item4 As T4
Public Item5 As T5
Public Item6 As T6
Public Item7 As T7
Public Sub New(_1 As T1, _2 As T2, _3 As T3, _4 As T4, _5 As T5, _6 As T6, _7 As T7)
Item1 = _1
Item2 = _2
Item3 = _3
Item4 = _4
Item5 = _5
Item6 = _6
Item7 = _7
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4, T5, T6, T7, T8)
Public Item1 As T1
Public Item2 As T2
Public Item3 As T3
Public Item4 As T4
Public Item5 As T5
Public Item6 As T6
Public Item7 As T7
Public Rest As T8
Public Sub New(_1 As T1, _2 As T2, _3 As T3, _4 As T4, _5 As T5, _6 As T6, _7 As T7, _8 As T8)
Item1 = _1
Item2 = _2
Item3 = _3
Item4 = _4
Item5 = _5
Item6 = _6
Item7 = _7
Rest = _8
End Sub
End Structure
End Namespace
Namespace System.Runtime.CompilerServices
Public Class TupleElementNamesAttribute
Inherits Attribute
Public Sub TupleElementNamesAttribute(names As String())
End Sub
End Class
End Namespace"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.ReleaseDll, assemblyName:=GetUniqueName())
comp.VerifyDiagnostics()
Return comp.EmitToArray()
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册