File: ExpansionTests.cs
Web Access
Project: ..\..\..\src\ExpressionEvaluator\CSharp\Test\ResultProvider\Microsoft.CodeAnalysis.CSharp.ResultProvider.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ResultProvider.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.ComponentInterfaces;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Symbols;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.UnitTests
{
    public class ExpansionTests : CSharpResultProviderTestBase
    {
        [Fact]
        public void Primitives()
        {
            // System.Object
            Verify(FormatResult("null", CreateDkmClrValue(null, typeof(object), evalFlags: DkmEvaluationResultFlags.None)), EvalResult("null", "null", "object", "null"));
            Verify(FormatResult("new object()", CreateDkmClrValue(new object())), EvalResult("new object()", "{object}", "object", "new object()"));
            // System.DBNull
            Verify(FormatResult("DBNull.Value", CreateDkmClrValue(DBNull.Value)), EvalResult("DBNull.Value", "{}", "System.DBNull", "DBNull.Value", DkmEvaluationResultFlags.Expandable));
            // System.Boolean
            Verify(FormatResult("new Boolean()", CreateDkmClrValue(new Boolean())), EvalResult("new Boolean()", "false", "bool", "new Boolean()", DkmEvaluationResultFlags.Boolean));
            Verify(FormatResult("false", CreateDkmClrValue(false, typeof(bool), evalFlags: DkmEvaluationResultFlags.Boolean)), EvalResult("false", "false", "bool", "false", DkmEvaluationResultFlags.Boolean));
            Verify(FormatResult("true", CreateDkmClrValue(true, typeof(bool), evalFlags: DkmEvaluationResultFlags.Boolean | DkmEvaluationResultFlags.BooleanTrue)), EvalResult("true", "true", "bool", "true", DkmEvaluationResultFlags.Boolean | DkmEvaluationResultFlags.BooleanTrue));
            // System.Char
            Verify(FormatResult("new Char()", CreateDkmClrValue(new Char())), EvalResult("new Char()", "0 '\\0'", "char", "new Char()", editableValue: "'\\0'"));
            // System.SByte
            Verify(FormatResult("new SByte()", CreateDkmClrValue(new SByte())), EvalResult("new SByte()", "0", "sbyte", "new SByte()"));
            // System.Byte
            Verify(FormatResult("new Byte()", CreateDkmClrValue(new Byte())), EvalResult("new Byte()", "0", "byte", "new Byte()"));
            // System.Int16
            Verify(FormatResult("new Int16()", CreateDkmClrValue(new Int16())), EvalResult("new Int16()", "0", "short", "new Int16()"));
            // System.UInt16
            Verify(FormatResult("new UInt16()", CreateDkmClrValue(new UInt16())), EvalResult("new UInt16()", "0", "ushort", "new UInt16()"));
            // System.Int32
            Verify(FormatResult("new Int32()", CreateDkmClrValue(new Int32())), EvalResult("new Int32()", "0", "int", "new Int32()"));
            // System.UInt32
            Verify(FormatResult("new UInt32()", CreateDkmClrValue(new UInt32())), EvalResult("new UInt32()", "0", "uint", "new UInt32()"));
            // System.Int64
            Verify(FormatResult("new Int64()", CreateDkmClrValue(new Int64())), EvalResult("new Int64()", "0", "long", "new Int64()"));
            // System.UInt64
            Verify(FormatResult("new UInt64()", CreateDkmClrValue(new UInt64())), EvalResult("new UInt64()", "0", "ulong", "new UInt64()"));
            // System.Single
            Verify(FormatResult("new Single()", CreateDkmClrValue(new Single())), EvalResult("new Single()", "0", "float", "new Single()"));
            // System.Double
            Verify(FormatResult("new Double()", CreateDkmClrValue(new Double())), EvalResult("new Double()", "0", "double", "new Double()"));
            // System.Decimal
            Verify(FormatResult("new Decimal()", CreateDkmClrValue(new Decimal())), EvalResult("new Decimal()", "0", "decimal", "new Decimal()", editableValue: "0M"));
            // System.DateTime
            // Set currentCulture to en-US for the test to pass in all locales
            using (new CultureContext(new CultureInfo("en-US", useUserOverride: false)))
            {
                // Skipped due to https://github.com/dotnet/roslyn/issues/21944
                //Verify(FormatResult("new DateTime()", CreateDkmClrValue(new DateTime())), EvalResult("new DateTime()", "{1/1/0001 12:00:00 AM}", "System.DateTime", "new DateTime()", DkmEvaluationResultFlags.Expandable));
            }
 
            // System.String
            Verify(FormatResult("stringNull", CreateDkmClrValue(null, typeof(string), evalFlags: DkmEvaluationResultFlags.None)), EvalResult("stringNull", "null", "string", "stringNull"));
            Verify(FormatResult("\"\"", CreateDkmClrValue("")), EvalResult("\"\"", "\"\"", "string", "\"\"", DkmEvaluationResultFlags.RawString, editableValue: "\"\""));
        }
 
        /// <summary>
        /// Get children in blocks.
        /// </summary>
        [Fact]
        public void GetChildrenTest()
        {
            var source =
@"class C
{
    internal object F1;
    protected object F2;
    private object F3;
    internal object P1 { get { return null; } }
    protected object P2 { get { return null; } }
    private object P3 { get { return null; } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = (DkmSuccessEvaluationResult)FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
 
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 1, null, out enumContext);
            Assert.Equal(1, children.Length);
 
            var resultsBuilder = ArrayBuilder<DkmEvaluationResult>.GetInstance();
            resultsBuilder.AddRange(children);
 
            while (resultsBuilder.Count < enumContext.Count)
            {
                var items = GetItems(enumContext, resultsBuilder.Count, 2);
                Assert.InRange(items.Length, 0, 2);
                resultsBuilder.AddRange(items);
            }
 
            Verify(resultsBuilder.ToArrayAndFree(),
                EvalResult("F1", "null", "object", "(new C()).F1", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F2", "null", "object", "(new C()).F2", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F3", "null", "object", "(new C()).F3", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P1", "null", "object", "(new C()).P1", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P2", "null", "object", "(new C()).P2", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P3", "null", "object", "(new C()).P3", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        /// <summary>
        /// Get children out or order.
        /// </summary>
        [Fact]
        public void GetChildrenOutOfOrder()
        {
            var source =
@"class C
{
    internal object F1;
    protected object F2;
    private object F3;
    internal object P1 { get { return null; } }
    protected object P2 { get { return null; } }
    private object P3 { get { return null; } }
}";
 
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
 
            var builder = ArrayBuilder<DkmEvaluationResult>.GetInstance();
 
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 0, null, out enumContext);
            builder.AddRange(children);
 
            builder.AddRange(GetItems(enumContext, 3, 2));
            builder.AddRange(GetItems(enumContext, 1, 1));
            builder.AddRange(GetItems(enumContext, 1, 1));
            builder.AddRange(GetItems(enumContext, 2, 0));
 
            Verify(builder.ToArrayAndFree(),
                EvalResult("P1", "null", "object", "(new C()).P1", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P2", "null", "object", "(new C()).P2", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F2", "null", "object", "(new C()).F2", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F2", "null", "object", "(new C()).F2", DkmEvaluationResultFlags.CanFavorite));
        }
 
        /// <summary>
        /// GetChildren should return the smaller number
        /// of items if request is outside range.
        /// </summary>
        [Fact]
        public void GetChildrenRequestOutsideRange()
        {
            var source =
@"class C
{
    internal object F1;
    internal object F2;
    internal object F3;
    internal object F4;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult("o", value);
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 100, null, out enumContext);
            Assert.Equal(4, enumContext.Count);
            Verify(children,
                EvalResult("F1", "null", "object", "o.F1", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F2", "null", "object", "o.F2", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F3", "null", "object", "o.F3", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F4", "null", "object", "o.F4", DkmEvaluationResultFlags.CanFavorite));
        }
 
        /// <summary>
        /// GetItems should return the smaller number
        /// of items if request is outside range.
        /// </summary>
        [Fact]
        public void GetItemsRequestOutsideRange()
        {
            var source =
@"class C
{
    internal object F1;
    internal object F2;
    internal object F3;
    internal object F4;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult("o", value);
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 0, null, out enumContext);
            Assert.Equal(4, enumContext.Count);
            Verify(children);
            children = GetItems(enumContext, 2, 4);
            Verify(children,
                EvalResult("F3", "null", "object", "o.F3", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("F4", "null", "object", "o.F4", DkmEvaluationResultFlags.CanFavorite));
            children = GetItems(enumContext, 4, 1);
            Verify(children);
            children = GetItems(enumContext, 6, 2);
            Verify(children);
        }
 
        /// <summary>
        /// Null instance should not be expandable.
        /// </summary>
        [Fact]
        public void NullInstance()
        {
            var source =
@"class C
{
    object o;
    string s;
    C c;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("c", "null", "C", "(new C()).c", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o", "null", "object", "(new C()).o", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("s", "null", "string", "(new C()).s", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void BaseAndDerived()
        {
            var source =
@"abstract class A
{
    internal object F;
    internal abstract object P { get; }
}
class B : A
{
    internal override object P { get { return null; } }
    internal virtual object Q { get { return null; } }
}
class C : B
{
}
class P
{
    object o = new C();
    A a = new C();
    B b = new C();
    C c = new C();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("P");
            var rootExpr = "new P()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{P}", "P", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("a", "{C}", "A {C}", "(new P()).a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "{C}", "B {C}", "(new P()).b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("c", "{C}", "C", "(new P()).c", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o", "{C}", "object {C}", "(new P()).o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            // B b = new C();
            Verify(GetChildren(children[1]),
                EvalResult("F", "null", "object", "(new P()).b.F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P", "null", "object", "(new P()).b.P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("Q", "null", "object", "(new P()).b.Q", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void Interface()
        {
            var source =
@"interface IA
{
}
interface IB : IA
{
}
class A : IB
{
    internal object F = 4;
}
class B : A
{
}
class C
{
    IA a = new B();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("a", "{B}", "IA {B}", "(new C()).a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("F", "4", "object {int}", "((A)(new C()).a).F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void ExplicitInterfaceImplementation()
        {
            var source = @"
interface I<T>
{
    int P1 { get; }
    int P2 { get; }
}
 
class C : I<I<string>>
{
    public int P1 { get { return 1; } }
    int I<I<string>>.P2 { get { return 2; } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = (DkmSuccessEvaluationResult)FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
 
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 2, null, out enumContext);
            Verify(children,
                EvalResult("I<I<string>>.P2", "2", "int", "((I<I<string>>)(new C())).P2", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P1", "1", "int", "(new C()).P1", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void ExplicitInterfaceImplementation2()
        {
            var source = @"
interface I<T>
{
    int P1 { get; }
    int P2 { get; }
}
 
class C : I<bool>, I<char>
{
    public int P1 { get { return 1; } }
    int I<bool>.P2 { get { return 2; } }
    int I<char>.P2 { get { return 3; } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = (DkmSuccessEvaluationResult)FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
 
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 3, null, out enumContext);
            Verify(children,
                EvalResult("I<bool>.P2", "2", "int", "((I<bool>)(new C())).P2", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("I<char>.P2", "3", "int", "((I<char>)(new C())).P2", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P1", "1", "int", "(new C()).P1", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void ExplicitInterfaceImplementationVb()
        {
            var source = @"
.class interface private abstract auto ansi I
{
  .method public newslot specialname abstract strict virtual 
          instance int32  get_P() cil managed
  {
  }
 
  .property instance int32 P()
  {
    .get instance int32 I::get_P()
  }
} // end of class I
 
.class private auto ansi C
       extends [mscorlib]System.Object
       implements I
{
  .method public specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    ldarg.0
    call       instance void [mscorlib]System.Object::.ctor()
    ret
  }
 
  .method public newslot specialname strict virtual final 
          instance int32  get_Q() cil managed
  {
    .override I::get_P
    ldc.i4.1
    ret
  }
 
  .property instance int32 Q()
  {
    .get instance int32 C::get_Q()
  }
} // end of class C
";
            ImmutableArray<byte> assemblyBytes;
            ImmutableArray<byte> pdbBytes;
            CSharpTestBase.EmitILToArray(source, appendDefaultHeader: true, includePdb: false, assemblyBytes: out assemblyBytes, pdbBytes: out pdbBytes);
            var assembly = ReflectionUtilities.Load(assemblyBytes);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = (DkmSuccessEvaluationResult)FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
 
            DkmEvaluationResultEnumContext enumContext;
            var children = GetChildren(evalResult, 3, null, out enumContext);
            Verify(children,
                EvalResult("Q", "1", "int", "(new C()).Q", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void EmptyBaseAndDerived()
        {
            var source =
@"class A
{
}
class B : A
{
}
class C
{
    object o = new B();
    A a = new B();
    B b = new B();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("a", "{B}", "A {B}", "(new C()).a", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "{B}", "B", "(new C()).b", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o", "{B}", "object {B}", "(new C()).o", DkmEvaluationResultFlags.CanFavorite));
 
            // A a = new B();
            var more = GetChildren(children[0]);
            Verify(more);
 
            // B b = new B();
            more = GetChildren(children[1]);
            Verify(more);
 
            // object o = new B();
            more = GetChildren(children[2]);
            Verify(more);
        }
 
        [Fact]
        public void ValueTypeBaseAndDerived()
        {
            var source =
@"struct S
{
    object F;
}
class C
{
    object o = new S();
    System.ValueType v = new S();
    S s = new S();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("o", "{S}", "object {S}", "(new C()).o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("s", "{S}", "S", "(new C()).s", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("v", "{S}", "System.ValueType {S}", "(new C()).v", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            // object o = new S();
            var more = GetChildren(children[0]);
            Verify(more,
                EvalResult("F", "null", "object", "((S)(new C()).o).F", DkmEvaluationResultFlags.CanFavorite));
 
            // S s = new S();
            more = GetChildren(children[1]);
            Verify(more,
                EvalResult("F", "null", "object", "(new C()).s.F", DkmEvaluationResultFlags.CanFavorite));
 
            // System.ValueType v = new S();
            more = GetChildren(children[2]);
            Verify(more,
                EvalResult("F", "null", "object", "((S)(new C()).v).F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void WriteOnlyProperty()
        {
            var source =
@"class C
{
    object P { set { } }
    static object Q { set { } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr));
            var children = GetChildren(evalResult);
            Verify(children);
        }
 
        [Fact]
        public void Enums()
        {
            var source =
@"using System;
enum E { A, B }
enum F : byte { }
[Flags] enum @if { @else = 1, fi }
class C
{
    E e = E.B;
    F f = default(F);
    @if g = @if.@else | @if.fi;
    @if h = (@if)5;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("e", "B", "E", "(new C()).e", DkmEvaluationResultFlags.CanFavorite, editableValue: "E.B"),
                EvalResult("f", "0", "F", "(new C()).f", DkmEvaluationResultFlags.CanFavorite, editableValue: "0"),
                EvalResult("g", "else | fi", "if", "(new C()).g", DkmEvaluationResultFlags.CanFavorite, editableValue: "@if.@else | @if.fi"),
                EvalResult("h", "5", "if", "(new C()).h", DkmEvaluationResultFlags.CanFavorite, editableValue: "5"));
        }
 
        [Fact]
        public void Nullable()
        {
            var source =
@"enum E
{
    A
}
struct S
{
    internal S(int f) { F = f; }
    object F;
}
class C
{
    E? e1 = E.A;
    E? e2 = null;
    S? s1 = new S(1);
    S? s2 = null;
    object o1 = new System.Nullable<S>(default(S));
    object o2 = new System.Nullable<S>();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var rootExpr = "new C()";
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("e1", "A", "E?", "(new C()).e1", DkmEvaluationResultFlags.CanFavorite, editableValue: "E.A"),
                EvalResult("e2", "null", "E?", "(new C()).e2", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o1", "{S}", "object {S}", "(new C()).o1", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o2", "null", "object", "(new C()).o2", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("s1", "{S}", "S?", "(new C()).s1", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("s2", "null", "S?", "(new C()).s2", DkmEvaluationResultFlags.CanFavorite));
            // object o1 = new System.Nullable<S>(default(S));
            Verify(GetChildren(children[2]),
                EvalResult("F", "null", "object", "((S)(new C()).o1).F", DkmEvaluationResultFlags.CanFavorite));
            // S? s1 = new S();
            Verify(GetChildren(children[4]),
                EvalResult("F", "1", "object {int}", "(new C()).s1.F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NullableProperty()
        {
            var source =
@"
class R
{
    public int? A { get; set; }
    public int? B { get; set; }
}
class C
{
    R r = new R();
    public C()
    {
        r.A = 1;
        r.B = null;
    }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var rootExpr = "new C()";
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("r", "{R}", "R", "(new C()).r", flags: DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
            Verify(GetChildren(children[0]),
                EvalResult("A", "1", "int?", "(new C()).r.A", flags: DkmEvaluationResultFlags.CanFavorite, category: DkmEvaluationResultCategory.Property),
                EvalResult("B", "null", "int?", "(new C()).r.B", flags: DkmEvaluationResultFlags.CanFavorite, category: DkmEvaluationResultCategory.Property));
        }
 
        [Fact]
        public void Pointers()
        {
            var source =
@"unsafe class C
{
    internal C(long p)
    {
        this.p = (int*)p;
    }
    int* p;
    int* q;
}";
            var assembly = GetUnsafeAssembly(source);
            unsafe
            {
                int i = 4;
                long p = (long)&i;
                var type = assembly.GetType("C");
                var rootExpr = string.Format("new C({0})", p);
                var value = CreateDkmClrValue(type.Instantiate(p));
                var evalResult = FormatResult(rootExpr, value);
                Verify(evalResult,
                    EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("p", PointerToString(new IntPtr(p)), "int*", string.Format("({0}).p", rootExpr), DkmEvaluationResultFlags.Expandable),
                    EvalResult("q", PointerToString(IntPtr.Zero), "int*", string.Format("({0}).q", rootExpr)));
                string fullName = string.Format("*({0}).p", rootExpr);
                Verify(GetChildren(children[0]),
                    EvalResult(fullName, "4", "int", fullName));
            }
        }
 
        /// <summary>
        /// This tests the managed address-of functionality.  When you take the address
        /// of a managed object, what you get back is an IntPtr*.  As in dev12, this
        /// exposes two pointers, the one to the IntPtr and the one to the actual data
        /// (in the IntPtr).  For example, if you have a string "str", then "&amp;str" yields
        /// an IntPtr*.  The pointer is to the "string&amp;" (typed as IntPtr, since Roslyn
        /// doesn't have a representation for reference types) and the IntPtr is a pointer
        /// to the actual string object on the heap.
        /// </summary>
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1022632")]
        public void IntPtrPointer()
        {
            var source = @"
using System;
 
unsafe class C
{
    internal C(long p)
    {
        this.p = (IntPtr*)p;
    }
    IntPtr* p;
    IntPtr* q;
}";
            var assembly = GetUnsafeAssembly(source);
            unsafe
            {
                // NOTE: We're depending on endian-ness to put
                // the interesting bytes first when we run this
                // test as 32-bit.
                long i = 4;
                long p = (long)&i;
                var type = assembly.GetType("C");
                var rootExpr = string.Format("new C({0})", p);
                var value = CreateDkmClrValue(type.Instantiate(p));
                var evalResult = FormatResult(rootExpr, value);
                Verify(evalResult,
                    EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("p", PointerToString(new IntPtr(p)), "System.IntPtr*", string.Format("({0}).p", rootExpr), DkmEvaluationResultFlags.Expandable),
                    EvalResult("q", PointerToString(IntPtr.Zero), "System.IntPtr*", string.Format("({0}).q", rootExpr)));
                string fullName = string.Format("*({0}).p", rootExpr);
                children = GetChildren(children[0]);
                Verify(children,
                    EvalResult(fullName, IntPtr.Size == 8 ? "0x0000000000000004" : "0x00000004", "System.IntPtr", fullName, DkmEvaluationResultFlags.None));
            }
        }
 
        [Fact]
        public void UIntPtrPointer()
        {
            var source = @"
using System;
 
unsafe class C
{
    internal C(ulong p)
    {
        this.p = (UIntPtr*)p;
    }
    UIntPtr* p;
    UIntPtr* q;
}";
            var assembly = GetUnsafeAssembly(source);
            unsafe
            {
                // NOTE: We're depending on endian-ness to put
                // the interesting bytes first when we run this
                // test as 32-bit.
                ulong i = 4;
                ulong p = (ulong)&i;
                var type = assembly.GetType("C");
                var rootExpr = string.Format("new C({0})", p);
                var value = CreateDkmClrValue(type.Instantiate(p));
                var evalResult = FormatResult(rootExpr, value);
                Verify(evalResult,
                    EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("p", PointerToString(new UIntPtr(p)), "System.UIntPtr*", string.Format("({0}).p", rootExpr), DkmEvaluationResultFlags.Expandable),
                    EvalResult("q", PointerToString(UIntPtr.Zero), "System.UIntPtr*", string.Format("({0}).q", rootExpr)));
                string fullName = string.Format("*({0}).p", rootExpr);
                children = GetChildren(children[0]);
                Verify(children,
                    EvalResult(fullName, UIntPtr.Size == 8 ? "0x0000000000000004" : "0x00000004", "System.UIntPtr", fullName, DkmEvaluationResultFlags.None));
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1154608")]
        public void VoidPointer()
        {
            var source = @"
using System;
 
unsafe class C
{
    internal C(long p)
    {
        this.v = (void*)p;
        this.vv = (void**)p;
    }
    void* v;
    void** vv;
}";
            var assembly = GetUnsafeAssembly(source);
            unsafe
            {
                // NOTE: We're depending on endian-ness to put
                // the interesting bytes first when we run this
                // test as 32-bit.
                long i = 4;
                long p = (long)&i;
                long pp = (long)&p;
                var type = assembly.GetType("C");
                var rootExpr = $"new C({pp})";
                var value = CreateDkmClrValue(type.Instantiate(pp));
                var evalResult = FormatResult(rootExpr, value);
                Verify(evalResult,
                    EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("v", PointerToString(new IntPtr(pp)), "void*", $"({rootExpr}).v"),
                    EvalResult("vv", PointerToString(new IntPtr(pp)), "void**", $"({rootExpr}).vv", DkmEvaluationResultFlags.Expandable));
                string fullName = $"*({rootExpr}).vv";
                children = GetChildren(children[1]);
                Verify(children,
                    EvalResult(fullName, PointerToString(new IntPtr(p)), "void*", fullName));
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1064176")]
        public void NullPointer()
        {
            /*
            unsafe class C
            {
                void M()
                {
                    byte *ptr = null;
                }
            }
            */
            var rootExpr = "ptr";
            var type = typeof(byte*);
            var value = CreateDkmClrValue(0, type);
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "0x00000000", "byte*", rootExpr)); // should not be expandable
            Assert.Empty(GetChildren(evalResult));
            value = CreateDkmClrValue(0L, type);
            evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "0x0000000000000000", "byte*", rootExpr)); // should not be expandable
            Assert.Empty(GetChildren(evalResult));
        }
 
        [Fact]
        public void InvalidPointer()
        {
            /*
            unsafe class C
            {
                void M()
                {
                    byte *ptr = <invalid address>;
                }
            }
            */
            var rootExpr = "ptr";
            var type = typeof(byte*);
            var value = CreateDkmClrValue(0x1337, type);
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "0x00001337", "byte*", rootExpr, DkmEvaluationResultFlags.Expandable));
            Verify(GetChildren(evalResult),
                EvalResult("*ptr", "Cannot dereference '*ptr'. The pointer is not valid.", "byte", "*ptr", DkmEvaluationResultFlags.ExceptionThrown));
        }
 
        [Fact]
        public void StaticMembers()
        {
            var source =
@"class A
{
    const int F = 1;
    static readonly int G = 2;
}
class B : A
{
}
struct S
{
    const object F = null;
    static object P { get { return 3; } }
}
enum E
{
    A,
    B
}
class C
{
    A a = default(A);
    B b = null;
    S s = new S();
    S? sn = null;
    E e = E.B;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("a", "null", "A", "(new C()).a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "null", "B", "(new C()).b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("e", "B", "E", "(new C()).e", DkmEvaluationResultFlags.CanFavorite, editableValue: "E.B"),
                EvalResult("s", "{S}", "S", "(new C()).s", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("sn", "null", "S?", "(new C()).sn", DkmEvaluationResultFlags.CanFavorite));
 
            // A a = default(A);
            var more = GetChildren(children[0]);
            Verify(more,
                EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            more = GetChildren(more[0]);
            Verify(more,
                EvalResult("F", "1", "int", "A.F", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("G", "2", "int", "A.G", DkmEvaluationResultFlags.ReadOnly));
 
            // S s = new S();
            more = GetChildren(children[3]);
            Verify(more,
                EvalResult("Static members", null, "", "S", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            more = GetChildren(more[0]);
            Verify(more,
                EvalResult("F", "null", "object", "S.F", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P", "3", "object {int}", "S.P", DkmEvaluationResultFlags.ReadOnly));
        }
 
        [Fact]
        public void StaticMembersBaseAndDerived()
        {
            var source =
@"class A
{
    static readonly int F = 1;
}
class B : A
{
}
class C : B
{
    static object P { get { return 2; } }
}
class P
{
    B b = new C();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("P");
            var rootExpr = "new P()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{P}", "P", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("b", "{C}", "B {C}", "(new P()).b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("Static members", null, "", "C", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("F", "1", "int", "A.F", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P", "2", "object {int}", "C.P", DkmEvaluationResultFlags.ReadOnly));
        }
 
        [Fact]
        public void NoExpansion_Members()
        {
            var source =
@"class A
{
    readonly int F = 1;
}
class B : A
{
}
class C : B
{
    static object P { get { return 2; } }
}
class D
{
    C F = new C();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
 
            // Non-null value.
            var value = CreateDkmClrValue(Activator.CreateInstance(type),
                type: type);
            var evalResult = FormatResult("o", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(evalResult,
                EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.None));
 
            // Null value.
            value = CreateDkmClrValue(null,
                type: type);
            evalResult = FormatResult("o", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(evalResult,
                EvalResult("o", "null", "C", "o", DkmEvaluationResultFlags.None));
 
            // NoExpansion for children.
            value = CreateDkmClrValue(Activator.CreateInstance(assembly.GetType("D")));
            evalResult = FormatResult("o", value);
            Verify(evalResult,
                EvalResult("o", "{D}", "D", "o", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(
                evalResult,
                inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(children,
                EvalResult("F", "{C}", "C", "o.F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NoExpansion_DebuggerTypeProxy()
        {
            var source =
@"using System.Diagnostics;
[DebuggerTypeProxy(typeof(P))]
class C
{
    internal object F;
}
class D
{
    C F = new C();
}
internal class P
{
    private readonly C c;
    public P(C c)
    {
        this.c = c;
    }
    public object PF
    {
        get { return this.c.F; }
    }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type),
                type: type);
            var evalResult = FormatResult("o", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(evalResult,
                EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.None));
 
            // NoExpansion for children.
            value = CreateDkmClrValue(Activator.CreateInstance(assembly.GetType("D")));
            evalResult = FormatResult("o", value);
            Verify(evalResult,
                EvalResult("o", "{D}", "D", "o", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(
                evalResult,
                inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(children,
                EvalResult("F", "{C}", "C", "o.F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NoExpansion_Array()
        {
            var value = CreateDkmClrValue(new[] { 1, 2, 3 });
            var evalResult = FormatResult("a", value, inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
            Verify(evalResult,
                EvalResult("a", "{int[3]}", "int[]", "a", DkmEvaluationResultFlags.None));
        }
 
        [Fact]
        public void NoExpansion_Pointer()
        {
            var source =
@"unsafe class C
{
    internal C(long p)
    {
        this.P = (int*)p;
    }
    int* P;
}";
            var assembly = GetUnsafeAssembly(source);
            unsafe
            {
                int i = 4;
                long p = (long)&i;
                var type = assembly.GetType("C");
                var value = CreateDkmClrValue(type.Instantiate(p));
                var evalResult = FormatResult("o", value);
                Verify(evalResult,
                    EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(
                    evalResult,
                    inspectionContext: CreateDkmInspectionContext(DkmEvaluationFlags.NoExpansion));
                Verify(children,
                    EvalResult("P", PointerToString(new IntPtr(p)), "int*", "o.P", DkmEvaluationResultFlags.None));
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void StaticMemberOfBaseType()
        {
            var source =
@"class A
{
    internal static object F = new B();
}
class B
{
    internal object G = 1;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("A");
            var value = CreateDkmClrValue(
                value: type.Instantiate(),
                type: type,
                evalFlags: DkmEvaluationResultFlags.None);
            var evalResult = FormatResult("o", value);
            Verify(evalResult,
                EvalResult("o", "{A}", "A", "o", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("F", "{B}", "object {B}", "A.F", DkmEvaluationResultFlags.Expandable));
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("G", "1", "object {int}", "((B)A.F).G", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void BaseTypeWithNamespace()
        {
            var source =
@"namespace N
{
    class B
    {
        int i = 0;
    }
}
class C : N.B
{
    int j = 0;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("i", "0", "int", "(new C()).i", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("j", "0", "int", "(new C()).j", DkmEvaluationResultFlags.CanFavorite));
        }
 
        /// <summary>
        /// Members should be in alphabetical order.
        /// </summary>
        [Fact]
        public void OrderedMembers()
        {
            var source =
@"interface I
{
    int M4 { get; }
}
class A : I
{
    public int M1 = 0;
    protected int m0 = 1;
    internal int m5 = 2;
    private int m4 = 3;
    int I.M4 { get { return 4; } }
    public int M7 { get { return 5; } }
    protected int m6 { get { return 6; } }
    internal int M3 { get { return 7; } }
    private int M2 { get { return 8; } }
 
}
    class B
    {
    public static int m2 = 0;
    protected static int m3 = 1;
    internal static int m6 = 2;
    private static int m7 = 3;
    public static int M4 { get { return 4; } }
    protected static int M5 { get { return 5; } }
    internal static int M0 { get { return 6; } }
    private static int M1 { get { return 7; } }
}
class C
{
    A a = new A();
    B b = new B();
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var rootExpr = "new C()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{C}", "C", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("a", "{A}", "A", "(new C()).a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "{B}", "B", "(new C()).b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            // A a = new A();
            var more = GetChildren(children[0]);
            Verify(more,
                EvalResult("I.M4", "4", "int", "((I)(new C()).a).M4", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("M1", "0", "int", "(new C()).a.M1", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("M2", "8", "int", "(new C()).a.M2", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("M3", "7", "int", "(new C()).a.M3", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("M7", "5", "int", "(new C()).a.M7", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("m0", "1", "int", "(new C()).a.m0", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("m4", "3", "int", "(new C()).a.m4", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("m5", "2", "int", "(new C()).a.m5", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("m6", "6", "int", "(new C()).a.m6", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            // B b = new B();
            more = GetChildren(children[1]);
            Verify(more,
                EvalResult("Static members", null, "", "B", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            more = GetChildren(more[0]);
            Verify(more,
                EvalResult("M0", "6", "int", "B.M0", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("M1", "7", "int", "B.M1", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("M4", "4", "int", "B.M4", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("M5", "5", "int", "B.M5", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("m2", "0", "int", "B.m2"),
                EvalResult("m3", "1", "int", "B.m3"),
                EvalResult("m6", "2", "int", "B.m6"),
                EvalResult("m7", "3", "int", "B.m7"));
        }
 
        /// <summary>
        /// Hide members that have compiler-generated names.
        /// </summary>
        /// <remarks>
        /// As in dev11, the FullName expressions don't parse.
        /// </remarks> 
        [Fact]
        public void HiddenMembers()
        {
            var source =
@".class public A
{
  .method public hidebysig specialname rtspecialname instance void .ctor() { ret }
  .field public object '@'
  .field public object '<'
  .field public static object '>'
  .field public static object '><'
  .field public object '<>'
  .field public object '1<>'
  .field public object '<2'
  .field public object '<>__'
  .field public object '<>k'
  .field public static object '<3>k'
  .field public static object '<<>>k'
  .field public static object '<>>k'
  .field public static object '<<>k'
  .field public static object '< >k'
  .field public object 'CS$'
  .field public object 'CS$<>0_'
  .field public object 'CS$<>7__8'
  .field public object 'CS$$<>7__8'
  .field public object 'CS<>7__8'
  .field public static object '$<>7__8'
  .field public static object 'CS$<M>7'
}
.class public B
{
  .method public hidebysig specialname rtspecialname instance void .ctor() { ret }
  .method public instance object '<>k__get'() { ldnull ret }
  .method public static object '<M>7__get'() { ldnull ret }
  .property instance object '@'() { .get instance object B::'<>k__get'() }
  .property instance object '<'() { .get instance object B::'<>k__get'() }
  .property object '>'() { .get object B::'<M>7__get'() }
  .property object '><'() { .get object B::'<M>7__get'() }
  .property instance object '<>'() { .get instance object B::'<>k__get'() }
  .property instance object '1<>'() { .get instance object B::'<>k__get'() }
  .property instance object '<2'() { .get instance object B::'<>k__get'() }
  .property instance object '<>__'() { .get instance object B::'<>k__get'() }
  .property instance object '<>k'() { .get instance object B::'<>k__get'() }
  .property object '<3>k'() { .get object B::'<M>7__get'() }
  .property object '<<>>k'() { .get object B::'<M>7__get'() }
  .property object '<>>k'() { .get object B::'<M>7__get'() }
  .property object '<<>k'() { .get object B::'<M>7__get'() }
  .property object '< >k'() { .get object B::'<M>7__get'() }
  .property instance object 'VB$'() { .get instance object B::'<>k__get'() }
  .property instance object 'VB$<>0_'() { .get instance object B::'<>k__get'() }
  .property instance object 'VB$Me7__8'() { .get instance object B::'<>k__get'() }
  .property instance object 'VB$$<>7__8'() { .get instance object B::'<>k__get'() }
  .property instance object 'VB<>7__8'() { .get instance object B::'<>k__get'() }
  .property object '$<>7__8'() { .get object B::'<M>7__get'() }
  .property object 'CS$<M>7'() { .get object B::'<M>7__get'() }
}";
            ImmutableArray<byte> assemblyBytes;
            ImmutableArray<byte> pdbBytes;
            CSharpTestBase.EmitILToArray(source, appendDefaultHeader: true, includePdb: false, assemblyBytes: out assemblyBytes, pdbBytes: out pdbBytes);
            var assembly = ReflectionUtilities.Load(assemblyBytes);
 
            var type = assembly.GetType("A");
            var rootExpr = "new A()";
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{A}", "A", rootExpr, DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("1<>", "null", "object", fullName: null, DkmEvaluationResultFlags.CanFavorite),
                EvalResult("@", "null", "object", fullName: null, DkmEvaluationResultFlags.CanFavorite),
                EvalResult("CS<>7__8", "null", "object", fullName: null, DkmEvaluationResultFlags.CanFavorite),
                EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            children = GetChildren(children[children.Length - 1]);
            Verify(children,
                EvalResult(">", "null", "object", fullName: null),
                EvalResult("><", "null", "object", fullName: null));
 
            type = assembly.GetType("B");
            rootExpr = "new B()";
            value = CreateDkmClrValue(Activator.CreateInstance(type));
            evalResult = FormatResult(rootExpr, value);
            Verify(evalResult,
                EvalResult(rootExpr, "{B}", "B", rootExpr, DkmEvaluationResultFlags.Expandable));
            children = GetChildren(evalResult);
            Verify(children,
                EvalResult("1<>", "null", "object", fullName: null, flags: DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("@", "null", "object", fullName: null, flags: DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("VB<>7__8", "null", "object", fullName: null, flags: DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("Static members", null, "", "B", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            children = GetChildren(children[children.Length - 1]);
            Verify(children,
                EvalResult(">", "null", "object", fullName: null, flags: DkmEvaluationResultFlags.ReadOnly),
                EvalResult("><", "null", "object", fullName: null, flags: DkmEvaluationResultFlags.ReadOnly));
        }
 
        /// <summary>
        /// ImmutableArray includes [DebuggerDisplay(...)]
        /// that returns the underlying array.
        /// </summary>
        [Fact]
        public void ImmutableArray()
        {
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(typeof(ImmutableArray<>).Assembly));
            var rawValue = System.Collections.Immutable.ImmutableArray.Create(1, 2, 3);
            var type = runtime.GetType(typeof(ImmutableArray<>)).MakeGenericType(runtime.GetType(typeof(int)));
            var value = CreateDkmClrValue(
                value: rawValue,
                type: type,
                evalFlags: DkmEvaluationResultFlags.None);
            var evalResult = FormatResult("c", value);
            Verify(evalResult,
                EvalResult("c", "Length = 3", "System.Collections.Immutable.ImmutableArray<int>", "c", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("[0]", "1", "int", "c.array[0]"),
                EvalResult("[1]", "2", "int", "c.array[1]"),
                EvalResult("[2]", "3", "int", "c.array[2]"),
                EvalResult("Static members", null, "", "System.Collections.Immutable.ImmutableArray<int>", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void DeclaredTypeObject()
        {
            var source = @"
class A
{
    internal object F;
}
class B : A
{
    internal B(object f)
    {
        F = f;
    }
    internal object P { get { return this.F; } }
}
class C
{
    A a = new B(1);
    B b = new B(2);
    object o = new B(3);
}
";
            var assembly = GetAssembly(source);
            var typeC = assembly.GetType("C");
            var instanceC = typeC.Instantiate();
 
            var children = GetChildren(FormatResult("c", CreateDkmClrValue(instanceC)));
            Verify(children,
                EvalResult("a", "{B}", "A {B}", "c.a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "{B}", "B", "c.b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o", "{B}", "object {B}", "c.o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(children[0]), // as A
                EvalResult("F", "1", "object {int}", "c.a.F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P", "1", "object {int}", "((B)c.a).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(children[1]), // as B
                EvalResult("F", "2", "object {int}", "c.b.F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P", "2", "object {int}", "c.b.P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(children[2]), // as object
                EvalResult("F", "3", "object {int}", "((A)c.o).F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("P", "3", "object {int}", "((B)c.o).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void DeclaredTypeObject_Array()
        {
            var source = @"
interface I
{
    int Q { get; set; }
}
class A
{
    internal object F;
}
class B : A, I
{
    internal B(object f)
    {
        F = f;
    }
    internal object P { get { return this.F; } }
    int I.Q { get; set; }
}
class C
{
    A[] a = new A[] { new B(1) };
    B[] b = new B[] { new B(2) };
    I[] i = new I[] { new B(3) };
    object[] o = new object[] { new B(4) };
}
";
            var assembly = GetAssembly(source);
            var typeC = assembly.GetType("C");
            var instanceC = typeC.Instantiate();
 
            var children = GetChildren(FormatResult("c", CreateDkmClrValue(instanceC)));
            Verify(children,
                EvalResult("a", "{A[1]}", "A[]", "c.a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("b", "{B[1]}", "B[]", "c.b", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("i", "{I[1]}", "I[]", "c.i", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("o", "{object[1]}", "object[]", "c.o", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(GetChildren(children[0]).Single()), // as A[]
                EvalResult("F", "1", "object {int}", "c.a[0].F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("I.Q", "0", "int", "((I)c.a[0]).Q"),
                EvalResult("P", "1", "object {int}", "((B)c.a[0]).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(GetChildren(children[1]).Single()), // as B[]
                EvalResult("F", "2", "object {int}", "c.b[0].F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("I.Q", "0", "int", "((I)c.b[0]).Q"),
                EvalResult("P", "2", "object {int}", "c.b[0].P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(GetChildren(children[2]).Single()), // as I[]
                EvalResult("F", "3", "object {int}", "((A)c.i[0]).F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("I.Q", "0", "int", "c.i[0].Q"),
                EvalResult("P", "3", "object {int}", "((B)c.i[0]).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
 
            Verify(GetChildren(GetChildren(children[3]).Single()), // as object[]
                EvalResult("F", "4", "object {int}", "((A)c.o[0]).F", DkmEvaluationResultFlags.CanFavorite),
                EvalResult("I.Q", "0", "int", "((I)c.o[0]).Q"),
                EvalResult("P", "4", "object {int}", "((B)c.o[0]).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void DeclaredTypeObject_Static()
        {
            var source = @"
class A
{
    internal static object F = new B();
}
class B
{
    internal object G = 1;
}
class C
{
    A a = new A();
}
";
            var assembly = GetAssembly(source);
            var typeC = assembly.GetType("C");
            var instanceC = typeC.Instantiate();
 
            var children = GetChildren(FormatResult("c", CreateDkmClrValue(instanceC)));
            Verify(children,
                EvalResult("a", "{A}", "A", "c.a", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
 
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
 
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("F", "{B}", "object {B}", "A.F", DkmEvaluationResultFlags.Expandable));
 
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("G", "1", "object {int}", "((B)A.F).G", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void ExceptionThrownFlag()
        {
            var source = @"
struct S
{
    int x;
 
    S This 
    { 
        get 
        { 
            throw new System.Exception(); 
        }
    }
}
";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("S");
            var value = type.Instantiate();
 
            var children = GetChildren(FormatResult("s", CreateDkmClrValue(value)));
            Verify(children,
                EvalResult("This", "'s.This' threw an exception of type 'System.Exception'", "S {System.Exception}", "s.This", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("x", "0", "int", "s.x", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void ExceptionThrownFlag_ProxyType()
        {
            var source = @"
struct S
{
    int x;
 
    S This
    {
        get
        {
            throw new E();
        }
    }
}
 
[System.Diagnostics.DebuggerTypeProxy(typeof(EProxy))]
class E : System.Exception
{
    public int y = 1;
}
 
class EProxy
{
    public int z;
 
    public EProxy(E e)
    {
        this.z = e.y;
    }
}
";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("S");
            var value = type.Instantiate();
 
            var children = GetChildren(FormatResult("s", CreateDkmClrValue(value)));
            Verify(children,
                EvalResult("This", "'s.This' threw an exception of type 'E'", "S {E}", "s.This", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("x", "0", "int", "s.x", DkmEvaluationResultFlags.CanFavorite));
 
            children = GetChildren(children[0]);
            Verify(children,
                EvalResult("z", "1", "int", null),
                EvalResult("Raw View", null, "", "s.This, raw", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown, DkmEvaluationResultCategory.Data));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/967366")]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void ExceptionThrownFlag_DerivedExceptionType()
        {
            var source = @"
struct S
{
    int x;
 
    S This
    {
        get
        {
            throw new System.NullReferenceException();
        }
    }
}
";
            using (new EnsureEnglishUICulture())
            {
                var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(GetAssembly(source)));
                using (runtime.Load())
                {
                    var type = runtime.GetType("S");
                    var value = type.Instantiate();
                    var children = GetChildren(FormatResult("s", value));
                    Verify(children,
                        EvalResult(
                            "This",
                            "'s.This' threw an exception of type 'System.NullReferenceException'",
                            "S {System.NullReferenceException}",
                            "s.This",
                            DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                        EvalResult("x", "0", "int", "s.x", DkmEvaluationResultFlags.CanFavorite));
 
                    // NOTE: The real EE will show only the exception message, but our mock does not support autoexp.
                    children = GetChildren(children[0]);
                    Verify(children[6],
                        EvalResult("Message", "\"Object reference not set to an instance of an object.\"", "string", null, DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly));
                }
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/933845")]
        public void ExceptionThrownFlag_DebuggerDisplay()
        {
            var source = @"
struct S
{
    int x;
 
    S This
    {
        get
        {
            throw new E();
        }
    }
}
 
[System.Diagnostics.DebuggerDisplay(""DisplayValue"")]
class E : System.Exception
{
}
";
            using (new EnsureEnglishUICulture())
            {
                var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
                using (runtime.Load())
                {
                    var type = runtime.GetType("S");
                    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 | DkmEvaluationResultFlags.CanFavorite),
                        EvalResult("x", "0", "int", "s.x", DkmEvaluationResultFlags.CanFavorite));
                    children = GetChildren(children[0]);
                    Verify(children[6],
                        EvalResult("Message", "\"Exception of type 'E' was thrown.\"", "string", null, DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly));
                }
            }
        }
 
        [Fact]
        public void ExceptionThrownFlag_AtRoot()
        {
            var value = CreateDkmClrValue(
                new NullReferenceException(),
                evalFlags: DkmEvaluationResultFlags.ExceptionThrown);
            var evalResult = FormatResult("c.P", value);
            Verify(evalResult,
                EvalResult(
                    "c.P",
                    "'c.P' threw an exception of type 'System.NullReferenceException'",
                    "System.NullReferenceException", "c.P",
                    DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ExceptionThrown));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1043730")]
        public void ExceptionThrownFlag_Nullable()
        {
            /*
            var source =
@"class C
{
    string str;
}";
            */
            using (new EnsureEnglishUICulture())
            {
                var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib());
                var type = runtime.GetType(typeof(NullReferenceException));
                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,
                    EvalResult(
                        "c?.str.Length",
                        "'c?.str.Length' threw an exception of type 'System.NullReferenceException'",
                        "int? {System.NullReferenceException}",
                        "c?.str.Length",
                        DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ExceptionThrown));
                var children = GetChildren(evalResult);
                Verify(children[6],
                    EvalResult(
                        "Message",
                        "\"Object reference not set to an instance of an object.\"",
                        "string",
                        null,
                        DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly));
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1043730")]
        public void ExceptionThrownFlag_NullableMember()
        {
            var source =
@"class C
{
    int? P
    {
        get { throw new System.NullReferenceException(); }
    }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(type.Instantiate());
            var evalResult = FormatResult("c", value);
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult(
                    "P",
                    "'c.P' threw an exception of type 'System.NullReferenceException'",
                    "int? {System.NullReferenceException}",
                    "c.P",
                    DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void MultilineString()
        {
            var str = "\r\nline1\r\nline2";
            var quotedStr = "\"\\r\\nline1\\r\\nline2\"";
            var value = CreateDkmClrValue(str, evalFlags: DkmEvaluationResultFlags.RawString);
            var evalResult = FormatResult("str", value);
            Verify(evalResult,
                EvalResult("str", quotedStr, "string", "str", DkmEvaluationResultFlags.RawString, editableValue: quotedStr));
        }
 
        [Fact]
        public void UnicodeChar()
        {
            // This char is printable, so we expect the EditableValue to just be the char.
            var value = CreateDkmClrValue('\u1234');
            var evalResult = FormatResult("c", value);
            Verify(evalResult,
                EvalResult("c", "4660 '\u1234'", "char", "c", editableValue: "'\u1234'"));
 
            // This char is not printable, so we expect the EditableValue to be the unicode escape representation.
            value = CreateDkmClrValue('\u001f');
            evalResult = FormatResult("c", value, inspectionContext: CreateDkmInspectionContext(radix: 16));
            Verify(evalResult,
                EvalResult("c", "0x001f '\\u001f'", "char", "c", editableValue: "'\\u001f'"));
 
            // This char is not printable, but there is a specific escape character.
            value = CreateDkmClrValue('\u0007');
            evalResult = FormatResult("c", value, inspectionContext: CreateDkmInspectionContext(radix: 16));
            Verify(evalResult,
                EvalResult("c", "0x0007 '\\a'", "char", "c", editableValue: "'\\a'"));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1138095")]
        public void UnicodeString()
        {
            var value = CreateDkmClrValue("\u1234\u001f\u0007");
            var evalResult = FormatResult("s", value);
            Verify(evalResult,
                EvalResult("s", $"\"{'\u1234'}\\u001f\\a\"", "string", "s", editableValue: $"\"{'\u1234'}\\u001f\\a\"", flags: DkmEvaluationResultFlags.RawString));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1002381")]
        public void BaseTypeEditableValue()
        {
            var source =
@"using System;
using System.Collections.Generic;
[Flags] enum E { A = 1, B = 2 }
class C
{
    IEnumerable<char> s = string.Empty;
    object d = 1M;
    ValueType e = E.A | E.B;
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult("o", value);
            Verify(evalResult,
                EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("d", "1", "object {decimal}", "o.d", DkmEvaluationResultFlags.CanFavorite, editableValue: "1M"),
                EvalResult("e", "A | B", "System.ValueType {E}", "o.e", DkmEvaluationResultFlags.CanFavorite, editableValue: "E.A | E.B"),
                EvalResult("s", "\"\"", "System.Collections.Generic.IEnumerable<char> {string}", "o.s", DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.CanFavorite, editableValue: "\"\""));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965892")]
        public void DeclaredTypeAndRuntimeTypeDifferent()
        {
            var source =
@"class A { }
class B : A { }
";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("B");
            var declaredType = assembly.GetType("A");
            var value = CreateDkmClrValue(Activator.CreateInstance(type), type);
            var evalResult = FormatResult("a", value, new DkmClrType((TypeImpl)declaredType));
            Verify(evalResult,
                EvalResult("a", "{B}", "A {B}", "a", DkmEvaluationResultFlags.None));
            var children = GetChildren(evalResult);
            Verify(children);
        }
 
        [Fact]
        public void DeclaredTypeAndRuntimeTypeDifferByCase()
        {
            var source =
@"class Object { }";
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
            using (runtime.Load())
            {
                var value = runtime.GetType("Object").Instantiate();
                var evalResult = FormatResult("o", value, declaredType: runtime.GetType("System.Object"));
                Verify(evalResult,
                    EvalResult("o", "{Object}", "object {Object}", "o", DkmEvaluationResultFlags.None));
            }
        }
 
        /// <summary>
        /// Full name should be null for members of thrown
        /// exception since there's no valid expression.
        /// </summary>
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1003260")]
        public void ExceptionThrown_Member()
        {
            var source =
@"class E : System.Exception
{
    internal object F;
}
class C
{
    internal object P { get { throw new E() { F = 1 }; } }
    internal object Q { get { return new E() { F = 2 }; } }
}";
            using (new EnsureEnglishUICulture())
            {
                var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
                using (runtime.Load())
                {
                    var type = runtime.GetType("C");
                    var value = type.Instantiate();
                    var evalResult = FormatResult("o", value);
                    Verify(evalResult,
                        EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
                    var children = GetChildren(evalResult);
                    Verify(children,
                        EvalResult("P", "'o.P' threw an exception of type 'E'", "object {E}", "o.P", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                        EvalResult("Q", "{E: Exception of type 'E' was thrown.}", "object {E}", "o.Q", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
                    var moreChildren = GetChildren(children[0]);
                    Verify(moreChildren[1],
                        EvalResult("F", "1", "object {int}", null));
                    Verify(moreChildren[7],
                        EvalResult("Message", "\"Exception of type 'E' was thrown.\"", "string", null, DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly));
                    moreChildren = GetChildren(children[1]);
                    Verify(moreChildren[1],
                        EvalResult("F", "2", "object {int}", "((E)o.Q).F", DkmEvaluationResultFlags.CanFavorite));
                    Verify(moreChildren[7],
                        EvalResult("Message", "\"Exception of type 'E' was thrown.\"", "string", "((System.Exception)o.Q).Message", DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
                }
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1026721")]
        public void ExceptionThrown_ReadOnly()
        {
            var source =
@"class RO : System.Exception
{
}
class RW : System.Exception
{
    internal object F;
}
class C
{
    internal object RO1 { get { throw new RO(); } }
    internal object RO2 { get { throw new RW(); } }
    internal object RW1 { get { throw new RO(); } set { } }
    internal object RW2 { get { throw new RW(); } set { } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var value = CreateDkmClrValue(Activator.CreateInstance(type));
            var evalResult = FormatResult("o", value);
            Verify(evalResult,
                EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable));
            var children = GetChildren(evalResult);
            Verify(children,
                EvalResult("RO1", "'o.RO1' threw an exception of type 'RO'", "object {RO}", "o.RO1", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("RO2", "'o.RO2' threw an exception of type 'RW'", "object {RW}", "o.RO2", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("RW1", "'o.RW1' threw an exception of type 'RO'", "object {RO}", "o.RW1", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("RW2", "'o.RW2' threw an exception of type 'RW'", "object {RW}", "o.RW2", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ExceptionThrown | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithFieldOnBase()
        {
            var source = @"
class A
{
    private int f;
}
class B : A
{
    internal double f;
}";
            var assembly = GetAssembly(source);
            var typeB = assembly.GetType("B");
            var instanceB = Activator.CreateInstance(typeB);
            var value = CreateDkmClrValue(instanceB, typeB);
            var result = FormatResult("b", value);
            Verify(GetChildren(result),
                EvalResult("f (A)", "0", "int", "((A)b).f"),
                EvalResult("f", "0", "double", "b.f", DkmEvaluationResultFlags.CanFavorite));
 
            var typeA = assembly.GetType("A");
            value = CreateDkmClrValue(instanceB, typeB);
            result = FormatResult("a", value, new DkmClrType((TypeImpl)typeA));
            Verify(GetChildren(result),
                EvalResult("f (A)", "0", "int", "a.f"),
                EvalResult("f", "0", "double", "((B)a).f", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithFieldsOnMultipleBase()
        {
            var source = @"
class A
{
    private int f;
}
class B : A
{
    internal double f;
}
class C : B
{
}";
            var assembly = GetAssembly(source);
            var typeC = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(typeC);
            var value = CreateDkmClrValue(instanceC, typeC);
            var result = FormatResult("c", value);
            Verify(GetChildren(result),
                EvalResult("f (A)", "0", "int", "((A)c).f"),
                EvalResult("f", "0", "double", "c.f", DkmEvaluationResultFlags.CanFavorite));
 
            var typeB = assembly.GetType("B");
            value = CreateDkmClrValue(instanceC, typeC);
            result = FormatResult("b", value, new DkmClrType((TypeImpl)typeB));
            Verify(GetChildren(result),
                EvalResult("f (A)", "0", "int", "((A)b).f"),
                EvalResult("f", "0", "double", "b.f", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithPropertyOnNestedBase()
        {
            var source = @"
class A
{
    private int P { get; set; }
 
    internal class B : A
    {
        internal double P { get; set; }
    }
}
class C : A.B
{
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(type);
            var value = CreateDkmClrValue(instanceC, type);
            var result = FormatResult("c", value);
            Verify(GetChildren(result),
                EvalResult("P (A)", "0", "int", "((A)c).P"),
                EvalResult("P", "0", "double", "c.P", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithPropertyOnGenericBase()
        {
            var source = @"
class A<T>
{
    public T P { get; set; }
}
class B : A<int>
{
    private double P { get; set; }
}
class C : B
{
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(type);
            var value = CreateDkmClrValue(instanceC, type);
            var result = FormatResult("c", value);
            Verify(GetChildren(result),
                EvalResult("P (A<int>)", "0", "int", "((A<int>)c).P"),
                EvalResult("P", "0", "double", "c.P", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void PropertyNameConflictsWithFieldOnBase()
        {
            var source = @"
class A
{
    public string F;
}
class B : A
{
    private double F { get; set; }
}
class C : B
{
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(type);
            var value = CreateDkmClrValue(instanceC, type);
            var result = FormatResult("c", value);
            Verify(GetChildren(result),
                EvalResult("F (A)", "null", "string", "((A)c).F"),
                EvalResult("F", "0", "double", "c.F", DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithIndexerOnBase()
        {
            var source = @"
class A
{
    public string this[string x]
    {
        get
        {
            return ""DeriveMe"";
        }
    }
}
class B : A
{
    public string @this { get { return ""Derived""; } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("B");
            var instanceB = Activator.CreateInstance(type);
            var value = CreateDkmClrValue(instanceB, type);
            var result = FormatResult("b", value);
            Verify(GetChildren(result),
                EvalResult("@this", "\"Derived\"", "string", "b.@this", DkmEvaluationResultFlags.RawString | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithPropertyHiddenByNameOnBase()
        {
            var source = @"
class A
{
    static int S = 42;
    internal virtual int P { get { return 43; } }
}
class B : A
{
    internal override int P { get { return 45; } }
}
class C : B
{
    new double P { get { return 4.4; } }
}";
            var assembly = GetAssembly(source);
            var type = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(type);
            var value = CreateDkmClrValue(instanceC, type);
            var result = FormatResult("c", value);
            var children = GetChildren(result);
            Verify(children,
                EvalResult("P (B)", "45", "int", "((B)c).P", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P", "4.4", "double", "c.P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite),
                EvalResult("Static members", null, "", "C", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class));
            Verify(GetChildren(children[2]),
                EvalResult("S", "42", "int", "A.S"));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1074435")]
        public void NameConflictsWithExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    int P { get; }
}
class A : I
{
    int I.P { get { return 1; } }
}
class B : A, I
{
    int I.P { get { return 2; } }
}
class C : B, I
{
    int I.P { get { return 3; } }
}";
            var assembly = GetAssembly(source);
            var typeB = assembly.GetType("B");
            var typeC = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(typeC);
            var value = CreateDkmClrValue(instanceC, typeC);
            var result = FormatResult("b", value, new DkmClrType((TypeImpl)typeB));
            var children = GetChildren(result);
            // Note:  The names and full names below aren't the best...  That is, we never
            // display a type name following the name for types declared on interfaces
            // (e.g. "I.P (A)"), and since only the most derived property (C.I.P) is actually
            // callable from C#, we don't have a way to generate a full name for the others.
            // I think this is OK, because the case is uncommon and native didn't support
            // "Add Watch" on explicit interface implementations (it just generated "c.I.P").
            Verify(children,
                EvalResult("I.P", "1", "int", "((I)b).P", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("I.P", "2", "int", "((I)b).P", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("I.P", "3", "int", "((I)b).P", DkmEvaluationResultFlags.ReadOnly));
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1074435")]
        public void NameConflictsWithInterfaceReimplementation()
        {
            var source = @"
interface I
{
    int P { get; }
}
class A : I
{
    public int P { get { return 1; } }
}
class B : A, I
{
    public int P { get { return 2; } }
}
class C : B, I
{
    public int P { get { return 3; } }
}";
            var assembly = GetAssembly(source);
            var typeB = assembly.GetType("B");
            var typeC = assembly.GetType("C");
            var instanceC = Activator.CreateInstance(typeC);
            var value = CreateDkmClrValue(instanceC, typeC);
            var result = FormatResult("b", value, new DkmClrType((TypeImpl)typeB));
            var children = GetChildren(result);
            Verify(children,
                EvalResult("P (A)", "1", "int", "((A)b).P", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P (B)", "2", "int", "b.P", DkmEvaluationResultFlags.ReadOnly),
                EvalResult("P", "3", "int", "((C)b).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        [Fact]
        public void NameConflictsWithVirtualPropertiesAcrossDeclaredType()
        {
            var source = @"
class A 
{
    public virtual int P { get { return 1; } }
}
class B : A
{
    public override int P { get { return 2; } }
}
class C : B
{
}
class D : C
{
    public override int P { get { return 3; } }
}";
            var assembly = GetAssembly(source);
            var typeC = assembly.GetType("C");
            var typeD = assembly.GetType("D");
            var instanceD = Activator.CreateInstance(typeD);
            var value = CreateDkmClrValue(instanceD, typeD);
            var result = FormatResult("c", value, new DkmClrType((TypeImpl)typeC));
            var children = GetChildren(result);
            // Ideally, we would only emit "c.P" for the full name here, but the added
            // complexity of figuring that out (vs. always just calling the most derived)
            // doesn't seem worth it.
            Verify(children,
                EvalResult("P", "3", "int", "((D)c).P", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.CanFavorite));
        }
 
        /// <summary>
        /// Do not copy state from parent.
        /// </summary>
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1028624")]
        public void DoNotCopyParentState()
        {
            var sourceA =
@"public class A
{
    public static object F = 1;
    internal object G = 2;
}";
            var sourceB =
@"class B
{
    private A _1 = new A();
    protected A _2 = new A();
    internal A _3 = new A();
    public A _4 = new A();
}";
            var compilationA = CSharpTestBase.CreateCompilation(sourceA, options: TestOptions.ReleaseDll);
            var bytesA = compilationA.EmitToArray();
            var referenceA = MetadataReference.CreateFromImage(bytesA);
 
            var compilationB = CSharpTestBase.CreateCompilation(sourceB, options: TestOptions.DebugDll, references: new MetadataReference[] { referenceA });
            var bytesB = compilationB.EmitToArray();
            var assemblyA = ReflectionUtilities.Load(bytesA);
            var assemblyB = ReflectionUtilities.Load(bytesB);
 
            DkmClrRuntimeInstance runtime = null;
            DkmClrModuleInstance getModule(DkmClrRuntimeInstance r, System.Reflection.Assembly a) => (a == assemblyB) ? new DkmClrModuleInstance(r, a, new DkmModule(a.GetName().Name + ".dll")) : null;
            runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(assemblyA, assemblyB), getModule: getModule);
            using (runtime.Load())
            {
                var type = runtime.GetType("B");
                var value = type.Instantiate();
                // Format with "Just my code".
                var inspectionContext = CreateDkmInspectionContext(DkmEvaluationFlags.HideNonPublicMembers, runtimeInstance: runtime);
                var evalResult = FormatResult("o", value, inspectionContext: inspectionContext);
                var children = GetChildren(evalResult, inspectionContext: inspectionContext);
                Verify(children,
                    EvalResult("_1", "{A}", "A", "o._1", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Private),
                    EvalResult("_2", "{A}", "A", "o._2", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Protected),
                    EvalResult("_3", "{A}", "A", "o._3", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Internal),
                    EvalResult("_4", "{A}", "A", "o._4", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.Public));
                var moreChildren = GetChildren(children[0], inspectionContext: inspectionContext);
                Verify(moreChildren,
                    EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
                    EvalResult("Non-Public members", null, "", "o._1, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
                moreChildren = GetChildren(children[1], inspectionContext: inspectionContext);
                Verify(moreChildren,
                    EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
                    EvalResult("Non-Public members", null, "", "o._2, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
                moreChildren = GetChildren(children[2], inspectionContext: inspectionContext);
                Verify(moreChildren,
                    EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
                    EvalResult("Non-Public members", null, "", "o._3, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
                moreChildren = GetChildren(children[3], inspectionContext: inspectionContext);
                Verify(moreChildren,
                    EvalResult("Static members", null, "", "A", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Class, DkmEvaluationResultAccessType.None),
                    EvalResult("Non-Public members", null, "", "o._4, hidden", DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.ReadOnly, DkmEvaluationResultCategory.Data, DkmEvaluationResultAccessType.None));
            }
        }
 
        [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1130978")]
        public void NullableValue_Error()
        {
            var source =
@"class C
{
    bool F() { return false; }
    int? P
    {
        get
        {
            while (!F()) { }
            return null;
        }
    }
}";
            DkmClrRuntimeInstance runtime = null;
            VisualStudio.Debugger.Evaluation.ClrCompilation.DkmClrValue getMemberValue(VisualStudio.Debugger.Evaluation.ClrCompilation.DkmClrValue v, string m) => (m == "P") ? CreateErrorValue(runtime.GetType(typeof(int?)), "Function evaluation timed out") : null;
            runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(GetAssembly(source)), getMemberValue: getMemberValue);
            using (runtime.Load())
            {
                var type = runtime.GetType("C");
                var value = type.Instantiate();
                var memberValue = value.GetMemberValue("P", (int)System.Reflection.MemberTypes.Property, "C", DefaultInspectionContext);
                var evalResult = FormatResult("o.P", memberValue);
                Verify(evalResult,
                    EvalFailedResult("o.P", "Function evaluation timed out", "int?", "o.P"));
            }
        }
 
        [Fact]
        public void RootCastExpression()
        {
            var source =
@"class C
{
    object F = 3;
}";
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
            using (runtime.Load())
            {
                var typeC = runtime.GetType("C");
 
                // var o = (object)new C(); var e = (C)o;
                var value = typeC.Instantiate();
                var evalResult = FormatResult("(C)o", value);
                Verify(evalResult,
                    EvalResult("(C)o", "{C}", "C", "(C)o", DkmEvaluationResultFlags.Expandable));
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("F", "3", "object {int}", "((C)o).F", DkmEvaluationResultFlags.CanFavorite));
 
                // var c = new C(); var e = (C)((object)c);
                value = typeC.Instantiate();
                evalResult = FormatResult("(C)((object)c)", value);
                Verify(evalResult,
                    EvalResult("(C)((object)c)", "{C}", "C", "(C)((object)c)", DkmEvaluationResultFlags.Expandable));
                children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("F", "3", "object {int}", "((C)((object)c)).F", DkmEvaluationResultFlags.CanFavorite));
 
                // var a = (object)new[] { new C() }; var e = ((C[])o)[0];
                value = typeC.Instantiate();
                evalResult = FormatResult("((C[])o)[0]", value);
                Verify(evalResult,
                    EvalResult("((C[])o)[0]", "{C}", "C", "((C[])o)[0]", DkmEvaluationResultFlags.Expandable));
                children = GetChildren(evalResult);
                Verify(children,
                    EvalResult("F", "3", "object {int}", "((C[])o)[0].F", DkmEvaluationResultFlags.CanFavorite));
            }
        }
 
        /// <summary>
        /// Get many items synchronously.
        /// </summary>
        [Fact]
        public void ManyItemsSync()
        {
            const int n = 10000;
            var value = CreateDkmClrValue(Enumerable.Range(0, n).ToArray());
            var evalResult = FormatResult("a", value);
            IDkmClrResultProvider resultProvider = new CSharpResultProvider();
            var workList = new DkmWorkList();
 
            // GetChildren
            var getChildrenResult = default(DkmGetChildrenAsyncResult);
            resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r);
            Assert.Equal(0, workList.Length);
            Assert.Equal(n, getChildrenResult.InitialChildren.Length);
 
            // GetItems
            var getItemsResult = default(DkmEvaluationEnumAsyncResult);
            resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r);
            Assert.Equal(0, workList.Length);
            Assert.Equal(n, getItemsResult.Items.Length);
        }
 
        /// <summary>
        /// Multiple items, some completed asynchronously.
        /// </summary>
        [Fact]
        public void MultipleItemsAsync()
        {
            var source =
@"using System.Diagnostics;
[DebuggerDisplay(""{F}"")]
class C
{
    object F;
}";
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
            using (runtime.Load())
            {
                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.UnderlyingType.Instantiate() : null).ToArray());
                var evalResult = FormatResult("a", value);
 
                IDkmClrResultProvider resultProvider = new CSharpResultProvider();
                var workList = new DkmWorkList();
 
                // GetChildren
                var getChildrenResult = default(DkmGetChildrenAsyncResult);
                resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r);
                Assert.Equal(1, workList.Length);
                workList.Execute();
                Assert.Equal(getChildrenResult.InitialChildren.Length, n);
 
                // GetItems
                var getItemsResult = default(DkmEvaluationEnumAsyncResult);
                resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r);
                Assert.Equal(1, workList.Length);
                workList.Execute();
                Assert.Equal(getItemsResult.Items.Length, n);
            }
        }
 
        [Fact]
        public void MultipleItemsAndExceptions()
        {
            var source =
@"using System.Diagnostics;
[DebuggerDisplay(""{P}"")]
class C
{
    public C(int f) { this.f = f; }
    private readonly int f;
    object P
    {
        get
        {
            if (this.f % 4 == 3) throw new System.ArgumentException();
            return this.f;
        }
    }
}";
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
            using (runtime.Load())
            {
                int n = 10;
                int nFailures = 2;
                var type = runtime.GetType("C");
                var value = CreateDkmClrValue(Enumerable.Range(0, n).Select(i => type.UnderlyingType.Instantiate(i)).ToArray());
                var evalResult = FormatResult("a", value);
 
                IDkmClrResultProvider resultProvider = new CSharpResultProvider();
                var workList = new DkmWorkList();
 
                // GetChildren
                var getChildrenResult = default(DkmGetChildrenAsyncResult);
                resultProvider.GetChildren(evalResult, workList, n, DefaultInspectionContext, r => getChildrenResult = r);
                Assert.Equal(1, workList.Length);
                workList.Execute();
                var items = getChildrenResult.InitialChildren;
                Assert.Equal(items.Length, n);
                Assert.Equal(items.OfType<DkmFailedEvaluationResult>().Count(), nFailures);
 
                // GetItems
                var getItemsResult = default(DkmEvaluationEnumAsyncResult);
                resultProvider.GetItems(getChildrenResult.EnumContext, workList, 0, n, r => getItemsResult = r);
                Assert.Equal(1, workList.Length);
                workList.Execute();
                items = getItemsResult.Items;
                Assert.Equal(items.Length, n);
                Assert.Equal(items.OfType<DkmFailedEvaluationResult>().Count(), nFailures);
            }
        }
 
        [Fact]
        public void NullFormatSpecifiers()
        {
            var value = CreateDkmClrValue(3);
            // With no format specifiers in full name.
            DkmEvaluationResult evalResult = null;
            value.GetResult(
                new DkmWorkList(),
                DeclaredType: value.Type,
                CustomTypeInfo: null,
                InspectionContext: DefaultInspectionContext,
                FormatSpecifiers: null,
                ResultName: "o",
                ResultFullName: "o",
                CompletionRoutine: asyncResult => evalResult = asyncResult.Result);
            Verify(evalResult,
                EvalResult("o", "3", "int", "o"));
            // With format specifiers in full name.
            evalResult = null;
            value.GetResult(
                new DkmWorkList(),
                DeclaredType: value.Type,
                CustomTypeInfo: null,
                InspectionContext: DefaultInspectionContext,
                FormatSpecifiers: null,
                ResultName: "o",
                ResultFullName: "o, nq",
                CompletionRoutine: asyncResult => evalResult = asyncResult.Result);
            Verify(evalResult,
                EvalResult("o", "3", "int", "o, nq"));
        }
 
        [Fact(Skip = "9895"), WorkItem("https://github.com/dotnet/roslyn/issues/9895")]
        public void ErrorValueWithNoType()
        {
            var rootExpr = "e";
            var message = "The system is down.";
            var value = CreateErrorValue(type: null, message: message);
            Verify(FormatResult(rootExpr, value),
                EvalResult(rootExpr, message, "", rootExpr));
        }
 
        [Fact(Skip = "62156")]
        [WorkItem("https://github.com/dotnet/roslyn/issues/62156")]
        public void RefField()
        {
            var source =
@"ref struct S
{
    public S(ref string s)
    {
        F = ref s;
    }
    public ref string F;
}";
            var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlib(GetAssembly(source)));
            using (runtime.Load())
            {
                var type = runtime.GetType("S");
                var value = type.Instantiate("Hello, world!");
                var evalResult = FormatResult("s", value);
                var children = GetChildren(evalResult);
                Verify(children,
                    EvalResult(
                        "F",
                        "Hello, world!",
                        "string",
                        "s.F",
                        DkmEvaluationResultFlags.Expandable | DkmEvaluationResultFlags.CanFavorite));
            }
        }
    }
}