提交 f2cac222 编写于 作者: A Andrew Casey

Add support for "dynamic" in the expression compiler

This is the second of a sequence of changes.  (The first was 3dd1f2bf.)  In
this change we start returning custom type info (effectively just the
flags of DynamicAttribute packed into a byte array) from calls to the
expression compiler so that they can be consumed by the result provider.

TODO: The API for locals is still in flux and we don't presently have a
place to return the custom type info.

TODO: This change does not associate custom type info with locals declared
in the Immediate window.
上级 c36177f4
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
internal sealed class CSharpCompileResult : CompileResult
{
private readonly MethodSymbol _method;
internal CSharpCompileResult(
byte[] assembly,
MethodSymbol method,
ReadOnlyCollection<string> formatSpecifiers)
: base(assembly, method.ContainingType.MetadataName, method.MetadataName, formatSpecifiers)
{
Debug.Assert(method is EEMethodSymbol); // Expected but not required.
_method = method;
}
public override CustomTypeInfo GetCustomTypeInfo() =>
new CustomTypeInfo(DynamicFlagsCustomTypeInfo.PayloadTypeId, _method.GetCustomTypeInfoPayload());
}
}
......@@ -62,7 +62,9 @@
<Compile Include="Binders\EEMethodBinder.cs" />
<Compile Include="Binders\WithTypeArgumentsBinder.cs" />
<Compile Include="Binders\PlaceholderLocalBinder.cs" />
<Compile Include="CSharpCompileResult.cs" />
<Compile Include="CSharpInScopeHoistedLocals.cs" />
<Compile Include="CSharpLocalAndMethod.cs" />
<Compile Include="SymUnmanagedReaderExtensions.cs" />
<Compile Include="CompilationContext.cs" />
<Compile Include="CompilationExtensions.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
internal sealed class CSharpLocalAndMethod : LocalAndMethod
{
private readonly MethodSymbol _method;
public CSharpLocalAndMethod(string localName, MethodSymbol method, DkmClrCompilationResultFlags flags)
: base(localName, method.Name, flags)
{
Debug.Assert(method is EEMethodSymbol); // Expected but not required.
_method = method;
}
public override CustomTypeInfo GetCustomTypeInfo() =>
new CustomTypeInfo(DynamicFlagsCustomTypeInfo.PayloadTypeId, _method.GetCustomTypeInfoPayload());
}
}
......@@ -303,7 +303,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder)
{
var methodName = GetNextMethodName(methodBuilder);
var method = this.GetPseudoVariableMethod(typeNameDecoder, container, methodName, alias);
localBuilder.Add(new LocalAndMethod(alias.FullName, methodName, alias.GetLocalResultFlags()));
localBuilder.Add(new CSharpLocalAndMethod(alias.FullName, method, alias.GetLocalResultFlags()));
methodBuilder.Add(method);
}
}
......@@ -314,7 +314,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder)
{
var methodName = GetNextMethodName(methodBuilder);
var method = this.GetThisMethod(container, methodName);
localBuilder.Add(new LocalAndMethod("this", methodName, DkmClrCompilationResultFlags.None)); // Note: writable in dev11.
localBuilder.Add(new CSharpLocalAndMethod("this", method, DkmClrCompilationResultFlags.None)); // Note: writable in dev11.
methodBuilder.Add(method);
}
}
......@@ -372,7 +372,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder)
var methodName = GetNextMethodName(methodBuilder);
var returnType = typeVariablesType.Construct(allTypeParameters.Cast<TypeParameterSymbol, TypeSymbol>());
var method = this.GetTypeVariablesMethod(container, methodName, returnType);
localBuilder.Add(new LocalAndMethod(ExpressionCompilerConstants.TypeVariablesLocalName, methodName, DkmClrCompilationResultFlags.ReadOnlyResult));
localBuilder.Add(new CSharpLocalAndMethod(ExpressionCompilerConstants.TypeVariablesLocalName, method, DkmClrCompilationResultFlags.ReadOnlyResult));
methodBuilder.Add(method);
}
}
......@@ -418,7 +418,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder)
name = SyntaxHelpers.EscapeKeywordIdentifiers(name);
var methodName = GetNextMethodName(methodBuilder);
var method = getMethod(container, methodName, name, localOrParameterIndex);
localBuilder.Add(new LocalAndMethod(name, methodName, resultFlags));
localBuilder.Add(new CSharpLocalAndMethod(name, method, resultFlags));
methodBuilder.Add(method);
}
......
......@@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
internal sealed class EEAssemblyBuilder : PEAssemblyBuilderBase
{
private readonly ImmutableHashSet<MethodSymbol> _methods;
internal readonly ImmutableHashSet<MethodSymbol> Methods;
public EEAssemblyBuilder(
SourceAssemblySymbol sourceAssembly,
......@@ -33,7 +33,7 @@ internal sealed class EEAssemblyBuilder : PEAssemblyBuilderBase
assemblySymbolMapper: null,
additionalTypes: additionalTypes)
{
_methods = ImmutableHashSet.CreateRange(methods);
Methods = ImmutableHashSet.CreateRange(methods);
if (testData != null)
{
......@@ -71,13 +71,13 @@ internal override bool IgnoreAccessibility
internal override VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol symbol)
{
var method = symbol as EEMethodSymbol;
if (((object)method != null) && _methods.Contains(method))
if (((object)method != null) && Methods.Contains(method))
{
var defs = GetLocalDefinitions(method.Locals);
return new SlotAllocator(defs);
}
Debug.Assert(!_methods.Contains(symbol));
Debug.Assert(!Methods.Contains(symbol));
return null;
}
......
......@@ -238,7 +238,7 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (syntax == null)
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
var context = this.CreateCompilationContext(syntax);
......@@ -247,7 +247,7 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (moduleBuilder == null)
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
using (var stream = new MemoryStream())
......@@ -265,18 +265,24 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (diagnostics.HasAnyErrors())
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
resultProperties = properties;
return new CompileResult(
return new CSharpCompileResult(
stream.ToArray(),
typeName: TypeName,
methodName: MethodName,
GetSynthesizedMethod(moduleBuilder),
formatSpecifiers: formatSpecifiers);
}
}
private static MethodSymbol GetSynthesizedMethod(CommonPEModuleBuilder moduleBuilder)
{
var method = ((EEAssemblyBuilder)moduleBuilder).Methods.Single(m => m.MetadataName == MethodName);
Debug.Assert(method.ContainingType.MetadataName == TypeName);
return method;
}
private static CSharpSyntaxNode Parse(
string expr,
bool treatAsExpression,
......@@ -324,7 +330,7 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (assignment == null)
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
var context = this.CreateCompilationContext(assignment);
......@@ -333,7 +339,7 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (moduleBuilder == null)
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
using (var stream = new MemoryStream())
......@@ -351,14 +357,13 @@ internal CompilationContext CreateCompilationContext(CSharpSyntaxNode syntax)
if (diagnostics.HasAnyErrors())
{
resultProperties = default(ResultProperties);
return default(CompileResult);
return null;
}
resultProperties = properties;
return new CompileResult(
return new CSharpCompileResult(
stream.ToArray(),
typeName: TypeName,
methodName: MethodName,
GetSynthesizedMethod(moduleBuilder),
formatSpecifiers: null);
}
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
......@@ -14,5 +18,12 @@ internal static ImmutableArray<TypeParameterSymbol> GetAllTypeParameters(this Me
builder.AddRange(method.TypeParameters);
return builder.ToImmutableAndFree();
}
internal static ReadOnlyCollection<byte> GetCustomTypeInfoPayload(this MethodSymbol method)
{
bool[] dynamicFlags = CSharpCompilation.DynamicTransformsEncoder.Encode(method.ReturnType, method.ReturnTypeCustomModifiers.Length, RefKind.None).ToArray();
var dynamicFlagsInfo = new DynamicFlagsCustomTypeInfo(new BitArray(dynamicFlags));
return dynamicFlagsInfo.GetCustomTypeInfoPayload();
}
}
}
......@@ -255,7 +255,7 @@ static void M(object x)
result = context.CompileExpression(InspectionContextFactory.Empty, "string.Empty, nq;", DkmEvaluationFlags.None, DiagnosticFormatter.Instance, out resultProperties, out error, out missingAssemblyIdentities, EnsureEnglishUICulture.PreferredOrNull, testData);
Assert.Empty(missingAssemblyIdentities);
Assert.Equal(error, "(1,13): error CS1002: ; expected");
Assert.Equal(result.FormatSpecifiers, null);
Assert.Null(result);
// Assignment without ';' as statement.
testData = new CompilationTestData();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
......@@ -8,9 +10,6 @@
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using Roslyn.Test.PdbUtilities;
using Roslyn.Test.Utilities;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
......@@ -44,6 +43,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, method.ReturnType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x01);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -81,6 +81,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((ArrayTypeSymbol)method.ReturnType).ElementType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -118,6 +119,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((NamedTypeSymbol)method.ReturnType).TypeArguments.Single().TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -161,6 +163,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, method.ReturnType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x01);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", DkmClrCompilationResultFlags.ReadOnlyResult, expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -203,6 +206,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((ArrayTypeSymbol)method.ReturnType).ElementType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", DkmClrCompilationResultFlags.ReadOnlyResult, expectedILOpt: @"
{
// Code size 2 (0x2)
......@@ -250,6 +254,7 @@ class Generic<T>
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((NamedTypeSymbol)method.ReturnType).TypeArguments.Single().TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", DkmClrCompilationResultFlags.ReadOnlyResult, expectedILOpt: @"
{
// Code size 2 (0x2)
......@@ -285,6 +290,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, method.ReturnType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x01);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -320,6 +326,7 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((ArrayTypeSymbol)method.ReturnType).ElementType.TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -355,6 +362,55 @@ static dynamic ForceDynamicAttribute()
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
Assert.Equal(TypeKind.Dynamic, ((NamedTypeSymbol)method.ReturnType).TypeArguments.Single().TypeKind);
VerifyCustomTypeInfo(locals[0], 0x02);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
}
[WorkItem(1087216, "DevDiv")]
[Fact]
public void ComplexDynamicType()
{
var source =
@"class C
{
static void M(Outer<dynamic[], object[]>.Inner<Outer<object, dynamic>[], dynamic> d)
{
}
static dynamic ForceDynamicAttribute()
{
return null;
}
}
public class Outer<T, U>
{
public class Inner<V, W>
{
public enum E
{
A
}
}
}
";
var comp = CreateCompilationWithMscorlib(source, new[] { SystemCoreRef, CSharpRef }, TestOptions.DebugDll);
var runtime = CreateRuntimeInstance(comp);
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);
var method = testData.Methods.Single().Value.Method;
AssertHasDynamicAttribute(method);
VerifyCustomTypeInfo(locals[0], 0x04, 0x03);
VerifyLocal(testData, typeName, locals[0], "<>m0", "d", expectedILOpt:
@"{
// Code size 2 (0x2)
......@@ -362,6 +418,17 @@ .maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
string error;
var result = context.CompileExpression("d", out error);
Assert.Null(error);
VerifyCustomTypeInfo(result, 0x04, 0x03);
// Note that the method produced by CompileAssignment returns void
// so there is never custom type info.
result = context.CompileAssignment("d", "d", out error);
Assert.Null(error);
VerifyCustomTypeInfo(result, null);
}
[Fact]
......@@ -419,8 +486,9 @@ void M()
var context = CreateMethodContext(runtime, "C.M");
var testData = new CompilationTestData();
string error;
var assembly = context.CompileExpression("d.M()", out error, testData);
var result = context.CompileExpression("d.M()", out error, testData);
Assert.Null(error);
VerifyCustomTypeInfo(result, 0x01);
var methodData = testData.GetMethodData("<>x.<>m0");
Assert.Equal(TypeKind.Dynamic, methodData.Method.ReturnType.TypeKind);
methodData.VerifyIL(@"
......@@ -477,8 +545,9 @@ static void Foo(dynamic y)
var context = CreateMethodContext(runtime, "C.Foo");
var testData = new CompilationTestData();
string error;
context.CompileAssignment("a", "() => Foo(x)", out error, testData);
var result = context.CompileAssignment("a", "() => Foo(x)", out error, testData);
Assert.Null(error);
VerifyCustomTypeInfo(result, null);
testData.GetMethodData("<>x.<>c.<<>m0>b__0_0").VerifyIL(@"
{
// Code size 106 (0x6a)
......@@ -519,8 +588,9 @@ .maxstack 9
context = CreateMethodContext(runtime, "C.<>c.<Foo>b__1_0");
testData = new CompilationTestData();
context.CompileExpression("Foo(x)", out error, testData);
result = context.CompileExpression("Foo(x)", out error, testData);
Assert.Null(error);
VerifyCustomTypeInfo(result, 0x01);
var methodData = testData.GetMethodData("<>x.<>m0");
methodData.VerifyIL(@"
{
......@@ -586,8 +656,9 @@ static void Foo(int x)
var context = CreateMethodContext(runtime, "C.M");
var testData = new CompilationTestData();
string error;
context.CompileExpression("Foo(x)", out error, testData);
var result = context.CompileExpression("Foo(x)", out error, testData);
Assert.Null(error);
VerifyCustomTypeInfo(result, 0x01);
testData.GetMethodData("<>c.<>m0()").VerifyIL(@"
{
// Code size 166 (0xa6)
......@@ -641,8 +712,9 @@ .maxstack 11
IL_00a4: stloc.0
IL_00a5: ret
}");
context.CompileExpression("Foo(y)", out error, testData);
result = context.CompileExpression("Foo(y)", out error, testData);
Assert.Null(error);
VerifyCustomTypeInfo(result, 0x01);
testData.GetMethodData("<>c.<>m0()").VerifyIL(@"
{
// Code size 166 (0xa6)
......@@ -697,5 +769,21 @@ .maxstack 11
IL_00a5: ret
}");
}
private static void VerifyCustomTypeInfo(LocalAndMethod localAndMethod, params byte[] expectedBytes)
{
VerifyCustomTypeInfo(localAndMethod.GetCustomTypeInfo(), expectedBytes);
}
private static void VerifyCustomTypeInfo(CompileResult compileResult, params byte[] expectedBytes)
{
VerifyCustomTypeInfo(compileResult.GetCustomTypeInfo(), expectedBytes);
}
private static void VerifyCustomTypeInfo(CustomTypeInfo customTypeInfo, byte[] expectedBytes)
{
Assert.Equal(DynamicFlagsCustomTypeInfo.PayloadTypeId, customTypeInfo.PayloadTypeId);
Assert.Equal(expectedBytes, customTypeInfo.Payload);
}
}
}
......@@ -105,7 +105,7 @@ public void ParseError()
methodName: "C.M");
string error;
var result = context.CompileExpression("M(", out error);
Assert.Null(result.Assembly);
Assert.Null(result);
Assert.Equal(error, "(1,3): error CS1026: ) expected");
}
......@@ -148,7 +148,7 @@ public void FormatterCultureInfo()
out missingAssemblyIdentities,
preferredUICulture: null,
testData: null);
Assert.Null(result.Assembly);
Assert.Null(result);
Assert.Equal(error, "LCID=1031, Code=1026");
Assert.Empty(missingAssemblyIdentities);
}
......@@ -544,8 +544,7 @@ static object F(string x, string y)
CheckFormatSpecifiers(result, "g", "h");
// Format specifiers on assignment value.
result = context.CompileAssignment("x", "null, y", out error);
Assert.Null(result.Assembly);
Assert.Null(result.FormatSpecifiers);
Assert.Null(result);
Assert.Equal(error, "(1,1): error CS1073: Unexpected token ','");
// Trailing semicolon, no format specifiers.
result = context.CompileExpression("x; ", out error);
......@@ -1628,7 +1627,7 @@ private static void CheckResultFlags(EvaluationContext context, string expr, Dkm
var testData = new CompilationTestData();
var result = context.CompileExpression(expr, out resultProperties, out error, testData);
Assert.Equal(expectedError, error);
Assert.NotEqual(expectedError == null, result.Assembly == null);
Assert.NotEqual(expectedError == null, result == null);
Assert.Equal(expectedFlags, resultProperties.Flags);
}
......
......@@ -599,7 +599,7 @@ void M()
numRetries++;
Assert.InRange(numRetries, 0, 2); // We don't want to loop forever...
diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_NoTypeDef, "MissingType", missingIdentity), Location.None));
return default(CompileResult);
return null;
},
(AssemblyIdentity assemblyIdentity, out uint uSize) =>
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.ObjectModel;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal struct CompileResult
internal abstract class CompileResult
{
internal readonly byte[] Assembly; // [] rather than ReadOnlyCollection<> to allow caller to create Stream easily
internal readonly string TypeName;
internal readonly string MethodName;
internal readonly ReadOnlyCollection<string> FormatSpecifiers;
internal CompileResult(
byte[] assembly,
string typeName,
......@@ -18,9 +24,6 @@ internal struct CompileResult
this.FormatSpecifiers = formatSpecifiers;
}
internal readonly byte[] Assembly; // [] rather than ReadOnlyCollection<> to allow caller to create Stream easily
internal readonly string TypeName;
internal readonly string MethodName;
internal readonly ReadOnlyCollection<string> FormatSpecifiers;
public abstract CustomTypeInfo GetCustomTypeInfo();
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
/// <remarks>
/// We can't instantiate <see cref="DkmClrCustomTypeInfo"/> in the unit tests
/// (since we run against a reference assembly), so we use this type as an
/// intermediary.
/// </remarks>
internal struct CustomTypeInfo
{
public Guid PayloadTypeId;
public ReadOnlyCollection<byte> Payload;
public CustomTypeInfo(Guid payloadTypeId, ReadOnlyCollection<byte> payload)
{
this.PayloadTypeId = payloadTypeId;
this.Payload = payload;
}
public DkmClrCustomTypeInfo ToDkmClrCustomTypeInfo()
{
return Payload == null
? null
: DkmClrCustomTypeInfo.Create(PayloadTypeId, Payload);
}
}
}
......@@ -155,7 +155,7 @@ internal static object GetSymReader(this DkmClrModuleInstance clrModule)
Access: resultProperties.AccessType,
StorageType: resultProperties.StorageType,
TypeModifierFlags: resultProperties.ModifierFlags,
CustomTypeInfo: null);
CustomTypeInfo: compResult.GetCustomTypeInfo().ToDkmClrCustomTypeInfo());
}
internal static ResultProperties GetResultProperties<TSymbol>(this TSymbol symbol, DkmClrCompilationResultFlags flags, bool isConstant)
......
......@@ -45,7 +45,7 @@ public DynamicFlagsCustomTypeInfo(DkmClrCustomTypeInfo typeInfo)
}
}
public DkmClrCustomTypeInfo GetCustomTypeInfo()
internal ReadOnlyCollection<byte> GetCustomTypeInfoPayload()
{
if (!Any())
{
......@@ -69,7 +69,13 @@ public DkmClrCustomTypeInfo GetCustomTypeInfo()
}
}
return DkmClrCustomTypeInfo.Create(PayloadTypeId, new ReadOnlyCollection<byte>(bytes));
return new ReadOnlyCollection<byte>(bytes);
}
public DkmClrCustomTypeInfo GetCustomTypeInfo()
{
var payload = GetCustomTypeInfoPayload();
return payload == null ? null : DkmClrCustomTypeInfo.Create(PayloadTypeId, payload);
}
public DynamicFlagsCustomTypeInfo SkipOne()
......
......@@ -34,6 +34,7 @@
</Compile>
<Compile Include="AssemblyReaders.cs" />
<Compile Include="AssemblyReference.cs" />
<Compile Include="CustomTypeInfo.cs" />
<Compile Include="DynamicFlagsCustomTypeInfo.cs" />
<Compile Include="Placeholders.cs" />
<Compile Include="ReflectionHelpers.cs" />
......
......@@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
/// The name of a local or argument and the name of
/// the corresponding method to access that object.
/// </summary>
internal struct LocalAndMethod
internal abstract class LocalAndMethod
{
public readonly string LocalName;
public readonly string MethodName;
......@@ -20,5 +20,7 @@ public LocalAndMethod(string localName, string methodName, DkmClrCompilationResu
this.MethodName = methodName;
this.Flags = flags;
}
public abstract CustomTypeInfo GetCustomTypeInfo();
}
}
......@@ -108,6 +108,8 @@
<Compile Include="Symbols\TypeSubstitutionExtensions.vb" />
<Compile Include="SyntaxHelpers.vb" />
<Compile Include="TypeParameterChecker.vb" />
<Compile Include="VisualBasicCompileResult.vb" />
<Compile Include="VisualBasicLocalAndMethod.vb" />
<Compile Include="VisualBasicMetadataContext.vb" />
<Compile Include="VisualBasicExpressionCompiler.vb" />
<Compile Include="VisualBasicFrameDecoder.vb" />
......@@ -134,4 +136,4 @@
<Import Project="..\..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -237,7 +237,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
For Each [alias] In aliases
Dim methodName = GetNextMethodName(methodBuilder)
Dim method = GetPseudoVariableMethod(typeNameDecoder, container, methodName, [alias])
localBuilder.Add(New LocalAndMethod([alias].FullName, methodName, [alias].GetLocalResultFlags()))
localBuilder.Add(New VisualBasicLocalAndMethod([alias].FullName, methodName, [alias].GetLocalResultFlags()))
methodBuilder.Add(method)
Next
End If
......@@ -247,7 +247,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
If Not m.IsShared AndAlso (Not m.ContainingType.IsClosureOrStateMachineType() OrElse _displayClassVariables.ContainsKey(GeneratedNames.MakeStateMachineCapturedMeName())) Then
Dim methodName = GetNextMethodName(methodBuilder)
Dim method = Me.GetMeMethod(container, methodName)
localBuilder.Add(New LocalAndMethod("Me", methodName, DkmClrCompilationResultFlags.None)) ' NOTE: writable in Dev11.
localBuilder.Add(New VisualBasicLocalAndMethod("Me", methodName, DkmClrCompilationResultFlags.None)) ' NOTE: writable in Dev11.
methodBuilder.Add(method)
End If
End If
......@@ -297,7 +297,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim methodName = GetNextMethodName(methodBuilder)
Dim returnType = typeVariablesType.Construct(ImmutableArrayExtensions.Cast(Of TypeParameterSymbol, TypeSymbol)(allTypeParameters))
Dim method = Me.GetTypeVariableMethod(container, methodName, returnType)
localBuilder.Add(New LocalAndMethod(ExpressionCompilerConstants.TypeVariablesLocalName, methodName, DkmClrCompilationResultFlags.ReadOnlyResult))
localBuilder.Add(New VisualBasicLocalAndMethod(ExpressionCompilerConstants.TypeVariablesLocalName, methodName, DkmClrCompilationResultFlags.ReadOnlyResult))
methodBuilder.Add(method)
End If
End If
......@@ -343,7 +343,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
name = SyntaxHelpers.EscapeKeywordIdentifiers(name)
Dim methodName = GetNextMethodName(methodBuilder)
Dim method = getMethod(container, methodName, name, localOrParameterIndex)
localBuilder.Add(New LocalAndMethod(name, methodName, resultFlags))
localBuilder.Add(New VisualBasicLocalAndMethod(name, methodName, resultFlags))
methodBuilder.Add(method)
End Sub
......
......@@ -382,7 +382,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End If
resultProperties = properties
Return New CompileResult(
Return New VisualBasicCompileResult(
stream.ToArray(),
s_typeName,
s_methodName,
......@@ -431,7 +431,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
properties.AccessType,
properties.StorageType,
properties.ModifierFlags)
Return New CompileResult(
Return New VisualBasicCompileResult(
stream.ToArray(),
s_typeName,
s_methodName,
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class VisualBasicCompileResult : Inherits CompileResult
Public Sub New(
assembly As Byte(),
typeName As String,
methodName As String,
formatSpecifiers As ReadOnlyCollection(Of String))
MyBase.New(assembly, typeName, methodName, formatSpecifiers)
End Sub
Public Overrides Function GetCustomTypeInfo() As CustomTypeInfo
Return Nothing
End Function
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class VisualBasicLocalAndMethod : Inherits LocalAndMethod
Public Sub New(localName As String, methodName As String, flags As DkmClrCompilationResultFlags)
MyBase.New(localName, methodName, flags)
End Sub
Public Overrides Function GetCustomTypeInfo() As CustomTypeInfo
Return Nothing
End Function
End Class
End Namespace
......@@ -90,7 +90,7 @@ End Class
Dim errorMessage As String = Nothing
Dim result = context.CompileExpression("M(", errorMessage, Nothing, VisualBasicDiagnosticFormatter.Instance)
Assert.Null(result.Assembly)
Assert.Null(result)
Assert.Equal("(1) : error BC30201: Expression expected.", errorMessage)
End Sub
......@@ -124,7 +124,7 @@ End Class
preferredUICulture:=Nothing,
testData:=Nothing)
Assert.Empty(missingAssemblyIdentities)
Assert.Null(result.Assembly)
Assert.Null(result)
Assert.Equal("LCID=1031, Code=30201", errorMessage)
Finally
Thread.CurrentThread.CurrentUICulture = previousUICulture
......@@ -444,8 +444,7 @@ End Class
' Format specifiers on assignment value.
result = context.CompileAssignment("x", "Nothing, y", errorMessage, Nothing, VisualBasicDiagnosticFormatter.Instance)
Assert.Null(result.Assembly)
Assert.Null(result.FormatSpecifiers)
Assert.Null(result)
Assert.Equal("(1) : error BC30035: Syntax error.", errorMessage)
' Format specifiers, no expression.
......@@ -1565,7 +1564,7 @@ End Class
Dim testData = New CompilationTestData()
Dim result = context.CompileExpression(expr, resultProperties, errorMessage, testData)
Assert.Equal(expectedErrorMessage, errorMessage)
Assert.NotEqual(expectedErrorMessage Is Nothing, result.Assembly Is Nothing)
Assert.NotEqual(expectedErrorMessage Is Nothing, result Is Nothing)
Assert.Equal(expectedFlags, resultProperties.Flags)
End Sub
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册