private static void ValidateCustomTypeInfo(params byte[] payload) { Assert.NotNull(payload); var dkmClrCustomTypeInfo = CustomTypeInfo.Create( new ReadOnlyCollection <byte>(payload), null ); Assert.Equal(CustomTypeInfo.PayloadTypeId, dkmClrCustomTypeInfo.PayloadTypeId); Assert.NotNull(dkmClrCustomTypeInfo.Payload); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( dkmClrCustomTypeInfo.PayloadTypeId, dkmClrCustomTypeInfo.Payload, out dynamicFlags, out tupleElementNames ); ValidateBytes(dynamicFlags, payload); Assert.Null(tupleElementNames); }
public void EncodeAndDecode() { var encoded = CustomTypeInfo.Encode(null, null); Assert.Null(encoded); var bytes = GetBytesInRange(0, 256); encoded = CustomTypeInfo.Encode(bytes, null); Assert.Null(encoded); bytes = GetBytesInRange(0, 255); encoded = CustomTypeInfo.Encode(bytes, null); Assert.Equal(256, encoded.Count); Assert.Equal(255, encoded[0]); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames); Assert.Equal(bytes, dynamicFlags); Assert.Null(tupleElementNames); var names = new ReadOnlyCollection <string>(new[] { null, "A", null, "B" }); encoded = CustomTypeInfo.Encode(bytes, names); Assert.Equal(255, encoded[0]); CustomTypeInfo.Decode(CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames); Assert.Equal(bytes, dynamicFlags); Assert.Equal(names, tupleElementNames); encoded = CustomTypeInfo.Encode(null, names); CustomTypeInfo.Decode(CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames); Assert.Null(dynamicFlags); Assert.Equal(names, tupleElementNames); }
public void Literal() { var source = @"class C { static void M() { (int, int) o; } }"; var comp = CreateCompilationWithMscorlib40( source, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugDll ); WithRuntimeInstance( comp, new[] { ValueTupleRef, SystemRuntimeFacadeRef, MscorlibRef }, runtime => { var context = CreateMethodContext(runtime, "C.M"); var testData = new CompilationTestData(); string error; var result = context.CompileExpression("(A: 1, B: 2)", out error, testData); Assert.Null(error); ReadOnlyCollection <byte> customTypeInfo; var customTypeInfoId = result.GetCustomTypeInfo(out customTypeInfo); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( customTypeInfoId, customTypeInfo, out dynamicFlags, out tupleElementNames ); Assert.Equal(new[] { "A", "B" }, tupleElementNames); var methodData = testData.GetMethodData("<>x.<>m0"); var method = (MethodSymbol)methodData.Method; Assert.True(method.ReturnType.IsTupleType); CheckAttribute( result.Assembly, method, AttributeDescription.TupleElementNamesAttribute, expected: true ); methodData.VerifyIL( @"{ // Code size 8 (0x8) .maxstack 2 .locals init (System.ValueTuple<int, int> V_0) //o IL_0000: ldc.i4.1 IL_0001: ldc.i4.2 IL_0002: newobj ""System.ValueTuple<int, int>..ctor(int, int)"" IL_0007: ret }" ); } ); }
internal static LocalSymbol Create( TypeNameDecoder <PEModuleSymbol, TypeSymbol> typeNameDecoder, MethodSymbol containingMethod, AssemblySymbol sourceAssembly, Alias alias) { var typeName = alias.Type; Debug.Assert(typeName.Length > 0); var type = typeNameDecoder.GetTypeSymbolForSerializedType(typeName); Debug.Assert((object)type != null); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(alias.CustomTypeInfoId, alias.CustomTypeInfo, out dynamicFlags, out tupleElementNames); if (dynamicFlags != null) { type = DecodeDynamicTypes(type, sourceAssembly, dynamicFlags); } if (tupleElementNames != null) { type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, sourceAssembly, tupleElementNames.AsImmutable()); } var name = alias.FullName; var displayName = alias.Name; switch (alias.Kind) { case DkmClrAliasKind.Exception: return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetExceptionMethodName)); case DkmClrAliasKind.StowedException: return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetStowedExceptionMethodName)); case DkmClrAliasKind.ReturnValue: { int index; PseudoVariableUtilities.TryParseReturnValueIndex(name, out index); Debug.Assert(index >= 0); return(new ReturnValueLocalSymbol(containingMethod, name, displayName, type, index)); } case DkmClrAliasKind.ObjectId: return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: false)); case DkmClrAliasKind.Variable: return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: true)); default: throw ExceptionUtilities.UnexpectedValue(alias.Kind); } }
public void CustomTypeInfoConstructor_OtherGuid() { var customTypeInfo = DkmClrCustomTypeInfo.Create(Guid.NewGuid(), new ReadOnlyCollection <byte>(new byte[] { 0x01 })); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( customTypeInfo.PayloadTypeId, customTypeInfo.Payload, out dynamicFlags, out tupleElementNames); Assert.Null(dynamicFlags); Assert.Null(tupleElementNames); }
public void Constant() { var source = @"class A<T> { internal class B<U> { } } class C { static (object, object) F; static void M() { const A<(int, int A)>.B<(object B, object)>[] c = null; } }"; var comp = CreateCompilationWithMscorlib40(source, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugDll); WithRuntimeInstance(comp, new[] { ValueTupleRef, SystemRuntimeFacadeRef, MscorlibRef }, runtime => { var context = CreateMethodContext(runtime, "C.M"); var testData = new CompilationTestData(); var locals = ArrayBuilder <LocalAndMethod> .GetInstance(); string typeName; var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); Assert.Equal(1, locals.Count); ReadOnlyCollection <byte> customTypeInfo; var customTypeInfoId = locals[0].GetCustomTypeInfo(out customTypeInfo); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(customTypeInfoId, customTypeInfo, out dynamicFlags, out tupleElementNames); Assert.Equal(new[] { null, "A", "B", null }, tupleElementNames); var method = (MethodSymbol)testData.GetExplicitlyDeclaredMethods().Single().Value.Method; CheckAttribute(assembly, method, AttributeDescription.TupleElementNamesAttribute, expected: true); var returnType = method.ReturnType; Assert.False(returnType.IsTupleType); Assert.True(returnType.ContainsTuple()); VerifyLocal(testData, typeName, locals[0], "<>m0", "c", expectedFlags: DkmClrCompilationResultFlags.ReadOnlyResult, expectedILOpt: @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldnull IL_0001: ret }"); locals.Free(); }); }
public void Local() { var source = @"class C { static void M() { (int A\u1234, int \u1234B) o = (1, 2); } }"; var comp = CreateCompilationWithMscorlib40(source, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugDll); WithRuntimeInstance(comp, new[] { ValueTupleRef, SystemRuntimeFacadeRef, MscorlibRef }, runtime => { var context = CreateMethodContext(runtime, "C.M"); var testData = new CompilationTestData(); var locals = ArrayBuilder <LocalAndMethod> .GetInstance(); string typeName; var assembly = context.CompileGetLocals(locals, argumentsOnly: false, typeName: out typeName, testData: testData); Assert.Equal(1, locals.Count); ReadOnlyCollection <byte> customTypeInfo; var customTypeInfoId = locals[0].GetCustomTypeInfo(out customTypeInfo); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(customTypeInfoId, customTypeInfo, out dynamicFlags, out tupleElementNames); Assert.Equal(new[] { "A\u1234", "\u1234B" }, tupleElementNames); var method = (MethodSymbol)testData.GetExplicitlyDeclaredMethods().Single().Value.Method; CheckAttribute(assembly, method, AttributeDescription.TupleElementNamesAttribute, expected: true); Assert.True(method.ReturnType.IsTupleType); VerifyLocal(testData, typeName, locals[0], "<>m0", "o", expectedILOpt: string.Format(@"{{ // Code size 2 (0x2) .maxstack 1 .locals init (System.ValueTuple<int, int> V_0) //o IL_0000: ldloc.0 IL_0001: ret }}", '\u1234')); locals.Free(); }); }
public void AliasElement() { var source = @"class C { static (int, int) F; static void M() { } }"; var comp = CreateCompilationWithMscorlib40(source, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugDll); WithRuntimeInstance(comp, new[] { ValueTupleRef, SystemRuntimeFacadeRef, MscorlibRef }, runtime => { var context = CreateMethodContext( runtime, "C.M"); // (int A, (int, int D) B)[] t; var aliasElementNames = new ReadOnlyCollection <string>(new[] { "A", "B", null, "D" }); var alias = new Alias( DkmClrAliasKind.Variable, "t", "t", "System.ValueTuple`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.ValueTuple`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51]][], System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51", CustomTypeInfo.PayloadTypeId, CustomTypeInfo.Encode(null, aliasElementNames)); var locals = ArrayBuilder <LocalAndMethod> .GetInstance(); string typeName; var diagnostics = DiagnosticBag.GetInstance(); var testData = new CompilationTestData(); var assembly = context.CompileGetLocals( locals, argumentsOnly: false, aliases: ImmutableArray.Create(alias), diagnostics: diagnostics, typeName: out typeName, testData: testData); diagnostics.Verify(); diagnostics.Free(); Assert.Equal(1, locals.Count); ReadOnlyCollection <byte> customTypeInfo; var customTypeInfoId = locals[0].GetCustomTypeInfo(out customTypeInfo); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(customTypeInfoId, customTypeInfo, out dynamicFlags, out tupleElementNames); Assert.Equal(aliasElementNames, tupleElementNames); var method = (MethodSymbol)testData.GetExplicitlyDeclaredMethods().Single().Value.Method; CheckAttribute(assembly, method, AttributeDescription.TupleElementNamesAttribute, expected: true); var returnType = (TypeSymbol)method.ReturnType; Assert.False(returnType.IsTupleType); Assert.True(((ArrayTypeSymbol)returnType).ElementType.IsTupleType); VerifyLocal(testData, typeName, locals[0], "<>m0", "t", expectedILOpt: @"{ // Code size 16 (0x10) .maxstack 1 IL_0000: ldstr ""t"" IL_0005: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectByAlias(string)"" IL_000a: castclass ""System.ValueTuple<int, System.ValueTuple<int, int>>[]"" IL_000f: ret }"); locals.Free(); }); }
public void DeclareLocal() { var source = @"class C { static void M() { var x = (1, 2); } }"; var comp = CreateCompilationWithMscorlib40(source, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugDll); WithRuntimeInstance(comp, new[] { ValueTupleRef, SystemRuntimeFacadeRef, MscorlibRef }, runtime => { var context = CreateMethodContext(runtime, "C.M"); var testData = new CompilationTestData(); string error; ResultProperties resultProperties; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; var result = context.CompileExpression( "(int A, int B) y = x;", DkmEvaluationFlags.None, NoAliases, DebuggerDiagnosticFormatter.Instance, out resultProperties, out error, out missingAssemblyIdentities, EnsureEnglishUICulture.PreferredOrNull, testData); Assert.Null(error); Assert.Equal(resultProperties.Flags, DkmClrCompilationResultFlags.PotentialSideEffect | DkmClrCompilationResultFlags.ReadOnlyResult); ReadOnlyCollection <byte> customTypeInfo; var customTypeInfoId = result.GetCustomTypeInfo(out customTypeInfo); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(customTypeInfoId, customTypeInfo, out dynamicFlags, out tupleElementNames); Assert.Null(tupleElementNames); var methodData = testData.GetMethodData("<>x.<>m0"); var method = (MethodSymbol)methodData.Method; CheckAttribute(result.Assembly, method, AttributeDescription.TupleElementNamesAttribute, expected: false); methodData.VerifyIL( @"{ // Code size 64 (0x40) .maxstack 6 .locals init (System.ValueTuple<int, int> V_0) //x IL_0000: ldtoken ""System.ValueTuple<int, int>"" IL_0005: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" IL_000a: ldstr ""y"" IL_000f: ldstr ""108766ce-df68-46ee-b761-0dcb7ac805f1"" IL_0014: newobj ""System.Guid..ctor(string)"" IL_0019: ldc.i4.5 IL_001a: newarr ""byte"" IL_001f: dup IL_0020: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=5 <PrivateImplementationDetails>.845151BC3876B3B783409FD71AF3665D783D8036161B4A2D2ACD27E1A0FCEDF7"" IL_0025: call ""void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"" IL_002a: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string, System.Guid, byte[])"" IL_002f: ldstr ""y"" IL_0034: call ""System.ValueTuple<int, int> Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress<System.ValueTuple<int, int>>(string)"" IL_0039: ldloc.0 IL_003a: stobj ""System.ValueTuple<int, int>"" IL_003f: ret }"); }); }
public void EncodeAndDecode() { var encoded = CustomTypeInfo.Encode(null, null); Assert.Null(encoded); ReadOnlyCollection <byte> bytes; ReadOnlyCollection <string> names; // Exceed max bytes. bytes = GetBytesInRange(0, 256); encoded = CustomTypeInfo.Encode(bytes, null); Assert.Null(encoded); // Max bytes. bytes = GetBytesInRange(0, 255); encoded = CustomTypeInfo.Encode(bytes, null); Assert.Equal(256, encoded.Count); Assert.Equal(255, encoded[0]); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Equal(bytes, dynamicFlags); Assert.Null(tupleElementNames); // Empty dynamic flags collection bytes = new ReadOnlyCollection <byte>(new byte[0]); // ... with names. names = new ReadOnlyCollection <string>(new[] { "A" }); encoded = CustomTypeInfo.Encode(bytes, names); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Null(dynamicFlags); Assert.Equal(names, tupleElementNames); // ... without names. encoded = CustomTypeInfo.Encode(bytes, null); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Null(dynamicFlags); Assert.Null(tupleElementNames); // Empty names collection names = new ReadOnlyCollection <string>(new string[0]); // ... with dynamic flags. bytes = GetBytesInRange(0, 255); encoded = CustomTypeInfo.Encode(bytes, names); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Equal(bytes, dynamicFlags); Assert.Null(tupleElementNames); // ... without dynamic flags. encoded = CustomTypeInfo.Encode(null, names); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Null(dynamicFlags); Assert.Null(tupleElementNames); // Single null name names = new ReadOnlyCollection <string>(new string[] { null }); // ... with dynamic flags. bytes = GetBytesInRange(0, 255); encoded = CustomTypeInfo.Encode(bytes, names); Assert.Equal(255, encoded[0]); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Equal(bytes, dynamicFlags); Assert.Equal(names, tupleElementNames); // ... without dynamic flags. encoded = CustomTypeInfo.Encode(null, names); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Null(dynamicFlags); Assert.Equal(names, tupleElementNames); // Multiple names names = new ReadOnlyCollection <string>(new[] { null, "A", null, "B" }); // ... with dynamic flags. bytes = GetBytesInRange(0, 255); encoded = CustomTypeInfo.Encode(bytes, names); Assert.Equal(255, encoded[0]); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Equal(bytes, dynamicFlags); Assert.Equal(names, tupleElementNames); // ... without dynamic flags. encoded = CustomTypeInfo.Encode(null, names); CustomTypeInfo.Decode( CustomTypeInfo.PayloadTypeId, encoded, out dynamicFlags, out tupleElementNames ); Assert.Null(dynamicFlags); Assert.Equal(names, tupleElementNames); }
internal static LocalSymbol Create( TypeNameDecoder <PEModuleSymbol, TypeSymbol> typeNameDecoder, MethodSymbol containingMethod, AssemblySymbol sourceAssembly, Alias alias) { var typeName = alias.Type; Debug.Assert(typeName.Length > 0); var type = typeNameDecoder.GetTypeSymbolForSerializedType(typeName); Debug.Assert((object)type != null); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode(alias.CustomTypeInfoId, alias.CustomTypeInfo, out dynamicFlags, out tupleElementNames); // Preserve tuple element names. See https://github.com/dotnet/roslyn/issues/13589. if (dynamicFlags != null) { var flagsBuilder = ArrayBuilder <bool> .GetInstance(); DynamicFlagsCustomTypeInfo.CopyTo(dynamicFlags, flagsBuilder); var dynamicType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags( type, sourceAssembly, RefKind.None, flagsBuilder.ToImmutableAndFree(), checkLength: false); Debug.Assert(dynamicType != null); Debug.Assert(dynamicType != type); type = dynamicType; } var name = alias.FullName; var displayName = alias.Name; switch (alias.Kind) { case DkmClrAliasKind.Exception: return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetExceptionMethodName)); case DkmClrAliasKind.StowedException: return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetStowedExceptionMethodName)); case DkmClrAliasKind.ReturnValue: { int index; PseudoVariableUtilities.TryParseReturnValueIndex(name, out index); Debug.Assert(index >= 0); return(new ReturnValueLocalSymbol(containingMethod, name, displayName, type, index)); } case DkmClrAliasKind.ObjectId: return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: false)); case DkmClrAliasKind.Variable: return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: true)); default: throw ExceptionUtilities.UnexpectedValue(alias.Kind); } }