提交 6b3c7771 编写于 作者: C Charles Stoner 提交者: GitHub

Merge pull request #13984 from cston/locals-vb

Support tuple element names in locals and expressions in VB EE
......@@ -1206,8 +1206,7 @@ Friend Module CompilationUtils
Dim context = New ModuleCompilationState()
DirectCast(symbol, Symbol).AddSynthesizedAttributes(context, attributes)
Else
' Call AddSynthesizedReturnTypeAttributes() when available: https://github.com/dotnet/roslyn/issues/13948
' DirectCast(symbol, MethodSymbol).AddSynthesizedReturnTypeAttributes(attributes)
DirectCast(symbol, MethodSymbol).AddSynthesizedReturnTypeAttributes(attributes)
End If
Return If(attributes IsNot Nothing, attributes.ToImmutableAndFree(), ImmutableArray.Create(Of SynthesizedAttributeData)())
End Function
......
......@@ -1241,7 +1241,10 @@ OtherExpressions:
End Sub
Private Function DefineLocal(local As LocalSymbol, syntaxNode As SyntaxNode) As LocalDefinition
Dim specType = local.Type.SpecialType
Dim dynamicTransformFlags = ImmutableArray(Of TypedConstant).Empty
Dim tupleElementNames = If(Not local.IsCompilerGenerated AndAlso local.Type.ContainsTupleNames(),
VisualBasicCompilation.TupleNamesEncoder.Encode(local.Type, _module.Compilation.GetSpecialType(SpecialType.System_String)),
ImmutableArray(Of TypedConstant).Empty)
' We're treating constants of type Decimal and DateTime as local here to not create a new instance for each time
' the value is accessed. This means there will be one local in the scope for this constant.
......@@ -1259,8 +1262,8 @@ OtherExpressions:
local.Name,
If(local.Locations.FirstOrDefault(), Location.None),
compileTimeValue,
dynamicTransformFlags:=Nothing,
tupleElementNames:=Nothing)
dynamicTransformFlags:=dynamicTransformFlags,
tupleElementNames:=tupleElementNames)
' Reference in the scope for debugging purpose
_builder.AddLocalConstantToScope(localConstantDef)
Return Nothing
......@@ -1290,8 +1293,8 @@ OtherExpressions:
id:=localId,
pdbAttributes:=synthesizedKind.PdbAttributes(),
constraints:=constraints,
dynamicTransformFlags:=Nothing,
tupleElementNames:=Nothing,
dynamicTransformFlags:=dynamicTransformFlags,
tupleElementNames:=tupleElementNames,
isSlotReusable:=synthesizedKind.IsSlotReusable(_ilEmitStyle <> ILEmitStyle.Release))
' If named, add it to the local debug scope.
......
......@@ -698,10 +698,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return names
End Function
Private Shared Function TryGetNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
Friend Shared Function TryGetNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
type.VisitType(Function(t As TypeSymbol, builder As ArrayBuilder(Of String)) AddNames(t, builder), namesBuilder)
Debug.Assert(namesBuilder.Any())
Return namesBuilder.Any(Function(name) name IsNot Nothing)
End Function
......
......@@ -156,6 +156,7 @@
<Compile Include="PDB\PDBConstLocalTests.vb" />
<Compile Include="PDB\PDBExternalSourceDirectiveTests.vb" />
<Compile Include="PDB\PDBLambdaTests.vb" />
<Compile Include="PDB\PDBTupleTests.vb" />
<Compile Include="PDB\PDBVariableInitializerTests.vb" />
<Compile Include="PDB\PDBIteratorTests.vb" />
<Compile Include="PDB\PDBForEachTests.vb" />
......@@ -260,4 +261,4 @@
</ItemGroup>
<Import Project="..\..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</Project>
</Project>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB
Public Class PDBTupleTests
Inherits BasicTestBase
<Fact>
Public Sub Local()
Dim source =
<compilation>
<file><![CDATA[
Class C
Shared Sub F()
Dim t As (A As Integer, B As Integer, (C As Integer, Integer), Integer, Integer, G As Integer, H As Integer, I As Integer) = (1, 2, (3, 4), 5, 6, 7, 8, 9)
End Sub
End Class
]]></file>
</compilation>
Dim comp = CreateCompilationWithMscorlib(source, references:={ValueTupleRef}, options:=TestOptions.DebugDll)
comp.VerifyPdb("C.F",
<symbols>
<methods>
<method containingType="C" name="F">
<customDebugInfo>
<tupleElementNames>
<local elementNames="|A|B||||G|H|I|C||" slotIndex="0" localName="t" scopeStart="0x0" scopeEnd="0x0"/>
</tupleElementNames>
<encLocalSlotMap>
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="19"/>
<entry offset="0x1" startLine="3" startColumn="13" endLine="3" endColumn="163"/>
<entry offset="0x1b" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x1c">
<currentnamespace name=""/>
<local name="t" il_index="0" il_start="0x0" il_end="0x1c" attributes="0"/>
</scope>
</method>
</methods>
</symbols>)
End Sub
End Class
End Namespace
......@@ -22,16 +22,6 @@ public CSharpEESymbolProvider(SourceAssemblySymbol sourceAssembly, PEModuleSymbo
_method = method;
}
private TypeSymbol GetDynamicType(TypeSymbol type, RefKind refKind, ImmutableArray<bool> dynamicFlags)
{
return DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(type, _sourceAssembly, refKind, dynamicFlags, checkLength: false);
}
private TypeSymbol IncludeTupleElementNames(TypeSymbol type, ImmutableArray<string> tupleElementNames)
{
return TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, _sourceAssembly, tupleElementNames);
}
public override LocalSymbol GetLocalVariable(
string name,
int slotIndex,
......@@ -57,19 +47,10 @@ private TypeSymbol IncludeTupleElementNames(TypeSymbol type, ImmutableArray<stri
type = info.Type;
}
if (!dynamicFlagsOpt.IsDefault)
{
type = GetDynamicType(type, refKind, dynamicFlagsOpt);
}
if (!tupleElementNamesOpt.IsDefault)
{
type = IncludeTupleElementNames(type, tupleElementNamesOpt);
}
// Custom modifiers can be dropped since binding ignores custom
// modifiers from locals and since we only need to preserve
// the type of the original local in the generated method.
type = IncludeDynamicAndTupleElementNamesIfAny(type, refKind, dynamicFlagsOpt, tupleElementNamesOpt);
return new EELocalSymbol(_method, EELocalSymbol.NoLocations, name, slotIndex, kind, type, refKind, isPinned, isCompilerGenerated: false, canScheduleToStack: false);
}
......@@ -80,16 +61,7 @@ private TypeSymbol IncludeTupleElementNames(TypeSymbol type, ImmutableArray<stri
ImmutableArray<bool> dynamicFlagsOpt,
ImmutableArray<string> tupleElementNamesOpt)
{
if (!dynamicFlagsOpt.IsDefault)
{
type = GetDynamicType(type, RefKind.None, dynamicFlagsOpt);
}
if (!tupleElementNamesOpt.IsDefault)
{
type = IncludeTupleElementNames(type, tupleElementNamesOpt);
}
type = IncludeDynamicAndTupleElementNamesIfAny(type, RefKind.None, dynamicFlagsOpt, tupleElementNamesOpt);
return new EELocalConstantSymbol(_method, name, type, value);
}
......@@ -125,5 +97,22 @@ public override TypeSymbol GetType(EntityHandle handle)
bool isNoPiaLocalType;
return _metadataDecoder.GetSymbolForTypeHandleOrThrow(handle, out isNoPiaLocalType, allowTypeSpec: true, requireShortForm: false);
}
private TypeSymbol IncludeDynamicAndTupleElementNamesIfAny(
TypeSymbol type,
RefKind refKind,
ImmutableArray<bool> dynamicFlagsOpt,
ImmutableArray<string> tupleElementNamesOpt)
{
if (!dynamicFlagsOpt.IsDefault)
{
type = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(type, _sourceAssembly, refKind, dynamicFlagsOpt, checkLength: false);
}
if (!tupleElementNamesOpt.IsDefault)
{
type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, _sourceAssembly, tupleElementNamesOpt);
}
return type;
}
}
}
......@@ -182,8 +182,7 @@ internal sealed class EvaluationContext : EvaluationContextBase
var currentFrame = compilation.GetMethod(moduleVersionId, methodHandle);
Debug.Assert((object)currentFrame != null);
var sourceAssembly = compilation.SourceAssembly;
var symbolProvider = new CSharpEESymbolProvider(sourceAssembly, (PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
var symbolProvider = new CSharpEESymbolProvider(compilation.SourceAssembly, (PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
var metadataDecoder = new MetadataDecoder((PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
var localInfo = metadataDecoder.GetLocalInfo(localSignatureHandle);
......
......@@ -45,20 +45,14 @@ internal PlaceholderLocalSymbol(MethodSymbol method, string name, string display
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;
type = DecodeDynamicTypes(type, sourceAssembly, dynamicFlags);
}
if (tupleElementNames != null)
{
type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, sourceAssembly, tupleElementNames.AsImmutable());
}
var name = alias.FullName;
......@@ -207,5 +201,20 @@ internal static MethodSymbol GetIntrinsicMethod(CSharpCompilation compilation, s
Debug.Assert(members.Length == 1);
return (MethodSymbol)members[0];
}
private static TypeSymbol DecodeDynamicTypes(TypeSymbol type, AssemblySymbol sourceAssembly, ReadOnlyCollection<byte> bytes)
{
var builder = ArrayBuilder<bool>.GetInstance();
DynamicFlagsCustomTypeInfo.CopyTo(bytes, builder);
var dynamicType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
type,
sourceAssembly,
RefKind.None,
builder.ToImmutableAndFree(),
checkLength: false);
Debug.Assert((object)dynamicType != null);
Debug.Assert(dynamicType != type);
return dynamicType;
}
}
}
......@@ -353,7 +353,7 @@ internal static Alias Alias(DkmClrAliasKind kind, string name, string fullName,
var peModule = (PEModuleSymbol)peMethod.ContainingModule;
var symReader = runtime.Modules.Single(mi => mi.ModuleVersionId == peModule.Module.GetModuleVersionIdOrThrow()).SymReader;
var symbolProvider = new CSharpEESymbolProvider((SourceAssemblySymbol)peCompilation.Assembly, peModule, peMethod);
var symbolProvider = new CSharpEESymbolProvider(peCompilation.SourceAssembly, peModule, peMethod);
return MethodDebugInfo<TypeSymbol, LocalSymbol>.ReadMethodDebugInfo((ISymUnmanagedReader3)symReader, symbolProvider, MetadataTokens.GetToken(peMethod.Handle), methodVersion: 1, ilOffset: ilOffset, isVisualBasicMethod: false);
}
......
......@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using Roslyn.Test.Utilities;
......@@ -200,7 +201,7 @@ .maxstack 1
locals.Free();
});
}
[Fact]
public void DeclareLocal()
{
......@@ -234,7 +235,10 @@ static void M()
Assert.Equal(resultProperties.Flags, DkmClrCompilationResultFlags.PotentialSideEffect | DkmClrCompilationResultFlags.ReadOnlyResult);
ReadOnlyCollection<byte> customTypeInfo;
var customTypeInfoId = result.GetCustomTypeInfo(out customTypeInfo);
Assert.Null(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 = methodData.Method;
Assert.Null(GetTupleElementNamesAttributeIfAny(method));
......@@ -262,5 +266,70 @@ .maxstack 6
}");
});
}
[WorkItem(13589, "https://github.com/dotnet/roslyn/issues/13589")]
[Fact]
public void Alias()
{
var source =
@"class C
{
static (int, int) F;
static void M()
{
}
}";
var comp = CreateCompilationWithMscorlib(source, new[] { ValueTupleRef }, options: TestOptions.DebugDll);
WithRuntimeInstance(comp, 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();
context.CompileGetLocals(
locals,
argumentsOnly: false,
aliases: ImmutableArray.Create(alias),
diagnostics: diagnostics,
typeName: out typeName,
testData: testData);
diagnostics.Verify();
diagnostics.Free();
Assert.Equal(locals.Count, 1);
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 = testData.Methods.Single().Value.Method;
Assert.NotNull(GetTupleElementNamesAttributeIfAny(method));
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 ""(int A, (int, int D) B)[]""
IL_000f: ret
}");
locals.Free();
});
}
}
}
......@@ -92,21 +92,16 @@ public override int GetHashCode()
try
{
ImmutableArray<HoistedLocalScopeRecord> hoistedLocalScopeRecords;
ImmutableArray<ImmutableArray<ImportRecord>> importRecordGroups;
ImmutableArray<ExternAliasRecord> externAliasRecords;
ImmutableDictionary<int, ImmutableArray<bool>> dynamicLocalMap;
ImmutableDictionary<string, ImmutableArray<bool>> dynamicLocalConstantMap;
ImmutableDictionary<int, ImmutableArray<string>> tupleLocalMap;
ImmutableDictionary<LocalNameAndScope, ImmutableArray<string>> tupleLocalConstantMap;
string defaultNamespaceName;
var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion);
if (symMethod != null)
{
symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod);
}
ImmutableArray<ImmutableArray<ImportRecord>> importRecordGroups;
ImmutableArray<ExternAliasRecord> externAliasRecords;
string defaultNamespaceName;
if (isVisualBasicMethod)
{
ReadVisualBasicImportsDebugInfo(
......@@ -116,12 +111,7 @@ public override int GetHashCode()
out importRecordGroups,
out defaultNamespaceName);
hoistedLocalScopeRecords = ImmutableArray<HoistedLocalScopeRecord>.Empty;
externAliasRecords = ImmutableArray<ExternAliasRecord>.Empty;
dynamicLocalMap = null;
dynamicLocalConstantMap = null;
tupleLocalMap = null;
tupleLocalConstantMap = null;
}
else
{
......@@ -135,18 +125,38 @@ public override int GetHashCode()
out importRecordGroups,
out externAliasRecords);
ReadCSharpNativeCustomDebugInfo(
symReader,
methodToken,
methodVersion,
allScopes,
out hoistedLocalScopeRecords,
out dynamicLocalMap,
out dynamicLocalConstantMap,
defaultNamespaceName = "";
}
ImmutableArray<HoistedLocalScopeRecord> hoistedLocalScopeRecords = ImmutableArray<HoistedLocalScopeRecord>.Empty;
ImmutableDictionary<int, ImmutableArray<bool>> dynamicLocalMap = null;
ImmutableDictionary<string, ImmutableArray<bool>> dynamicLocalConstantMap = null;
ImmutableDictionary<int, ImmutableArray<string>> tupleLocalMap = null;
ImmutableDictionary<LocalNameAndScope, ImmutableArray<string>> tupleLocalConstantMap = null;
byte[] customDebugInfo = symReader.GetCustomDebugInfoBytes(methodToken, methodVersion);
if (customDebugInfo != null)
{
if (!isVisualBasicMethod)
{
var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.StateMachineHoistedLocalScopes);
if (!customDebugInfoRecord.IsDefault)
{
hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
.SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.EndOffset - s.StartOffset + 1));
}
GetCSharpDynamicLocalInfo(
customDebugInfo,
allScopes,
out dynamicLocalMap,
out dynamicLocalConstantMap);
}
GetTupleElementNamesLocalInfo(
customDebugInfo,
out tupleLocalMap,
out tupleLocalConstantMap);
defaultNamespaceName = "";
}
var constantsBuilder = ArrayBuilder<TLocalSymbol>.GetInstance();
......@@ -341,48 +351,6 @@ private static bool TryCreateImportRecordFromCSharpImportString(EESymbolProvider
return false;
}
private static void ReadCSharpNativeCustomDebugInfo(
ISymUnmanagedReader3 reader,
int methodToken,
int methodVersion,
IEnumerable<ISymUnmanagedScope> scopes,
out ImmutableArray<HoistedLocalScopeRecord> hoistedLocalScopeRecords,
out ImmutableDictionary<int, ImmutableArray<bool>> dynamicLocalMap,
out ImmutableDictionary<string, ImmutableArray<bool>> dynamicLocalConstantMap,
out ImmutableDictionary<int, ImmutableArray<string>> tupleLocalMap,
out ImmutableDictionary<LocalNameAndScope, ImmutableArray<string>> tupleLocalConstantMap)
{
hoistedLocalScopeRecords = ImmutableArray<HoistedLocalScopeRecord>.Empty;
dynamicLocalMap = null;
dynamicLocalConstantMap = null;
tupleLocalMap = null;
tupleLocalConstantMap = null;
byte[] customDebugInfoBytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion);
if (customDebugInfoBytes == null)
{
return;
}
var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBytes, CustomDebugInfoKind.StateMachineHoistedLocalScopes);
if (!customDebugInfoRecord.IsDefault)
{
hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
.SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.EndOffset - s.StartOffset + 1));
}
GetCSharpDynamicLocalInfo(
customDebugInfoBytes,
scopes,
out dynamicLocalMap,
out dynamicLocalConstantMap);
GetTupleElementNamesLocalInfo(
customDebugInfoBytes,
out tupleLocalMap,
out tupleLocalConstantMap);
}
/// <exception cref="InvalidOperationException">Bad data.</exception>
private static void GetCSharpDynamicLocalInfo(
byte[] customDebugInfo,
......
......@@ -4,7 +4,6 @@ Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Utilities
......@@ -36,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim local = PlaceholderLocalSymbol.Create(
typeNameDecoder,
containingMethod,
sourceAssembly,
[alias])
_implicitDeclarations.Add(local.Name, local)
Next
......
......@@ -2,7 +2,6 @@
Imports System
Imports System.Collections.Immutable
Imports System.Collections.ObjectModel
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Collections
......@@ -237,7 +236,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim methodName = GetNextMethodName(methodBuilder)
Dim syntax = SyntaxFactory.IdentifierName(SyntaxFactory.MissingToken(SyntaxKind.IdentifierToken))
Dim local = PlaceholderLocalSymbol.Create(typeNameDecoder, _currentFrame, [alias])
Dim local = PlaceholderLocalSymbol.Create(typeNameDecoder, _currentFrame, Compilation.SourceAssembly, [alias])
Dim aliasMethod = Me.CreateMethod(
container,
methodName,
......@@ -246,7 +245,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim expression = New BoundLocal(syntax, local, isLValue:=False, type:=local.Type)
Return New BoundReturnStatement(syntax, expression, Nothing, Nothing).MakeCompilerGenerated()
End Function)
localBuilder.Add(MakeLocalAndMethod(local, methodName, If(local.IsReadOnly, DkmClrCompilationResultFlags.ReadOnlyResult, DkmClrCompilationResultFlags.None)))
localBuilder.Add(MakeLocalAndMethod(local, aliasMethod, If(local.IsReadOnly, DkmClrCompilationResultFlags.ReadOnlyResult, DkmClrCompilationResultFlags.None)))
methodBuilder.Add(aliasMethod)
Next
End If
......@@ -256,7 +255,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 VisualBasicLocalAndMethod("Me", "Me", methodName, DkmClrCompilationResultFlags.None)) ' NOTE: writable in Dev11.
localBuilder.Add(New VisualBasicLocalAndMethod("Me", "Me", method, DkmClrCompilationResultFlags.None)) ' NOTE: writable in Dev11.
methodBuilder.Add(method)
End If
End If
......@@ -307,7 +306,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
localBuilder.Add(New VisualBasicLocalAndMethod(
ExpressionCompilerConstants.TypeVariablesLocalName,
ExpressionCompilerConstants.TypeVariablesLocalName,
methodName,
method,
DkmClrCompilationResultFlags.ReadOnlyResult))
methodBuilder.Add(method)
End If
......@@ -347,7 +346,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim methodName = GetNextMethodName(methodBuilder)
Dim method = Me.GetLocalMethod(container, methodName, local.Name, localIndex)
localBuilder.Add(MakeLocalAndMethod(local, methodName, resultFlags))
localBuilder.Add(MakeLocalAndMethod(local, method, resultFlags))
methodBuilder.Add(method)
End Sub
......@@ -364,17 +363,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim name = SyntaxHelpers.EscapeKeywordIdentifiers(parameter.Name)
Dim methodName = GetNextMethodName(methodBuilder)
Dim method = Me.GetParameterMethod(container, methodName, parameter.Name, parameterIndex)
localBuilder.Add(New VisualBasicLocalAndMethod(name, name, methodName, DkmClrCompilationResultFlags.None))
localBuilder.Add(New VisualBasicLocalAndMethod(name, name, method, DkmClrCompilationResultFlags.None))
methodBuilder.Add(method)
End Sub
Private Shared Function MakeLocalAndMethod(local As LocalSymbol, methodName As String, flags As DkmClrCompilationResultFlags) As LocalAndMethod
Private Shared Function MakeLocalAndMethod(local As LocalSymbol, method As MethodSymbol, flags As DkmClrCompilationResultFlags) As LocalAndMethod
' Note: The native EE doesn't do this, but if we don't escape keyword identifiers,
' the ResultProvider needs to be able to disambiguate cases Like "Me" And "[Me]",
' which it can't do correctly without semantic information.
Dim escapedName = SyntaxHelpers.EscapeKeywordIdentifiers(local.Name)
Dim displayName = If(TryCast(local, PlaceholderLocalSymbol)?.DisplayName, escapedName)
Return New VisualBasicLocalAndMethod(escapedName, displayName, methodName, flags)
Return New VisualBasicLocalAndMethod(escapedName, displayName, method, flags)
End Function
Private Shared Function CreateModuleBuilder(
......
' 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.Immutable
Imports System.Collections.ObjectModel
Imports System.Reflection.Metadata
Imports System.Reflection.Metadata.Ecma335
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
......@@ -95,6 +95,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
options:=s_compilationOptions)
End Function
<Extension>
Friend Function GetCustomTypeInfoPayload(compilation As VisualBasicCompilation, type As TypeSymbol) As ReadOnlyCollection(Of Byte)
Dim builder = ArrayBuilder(Of String).GetInstance()
Dim names = If(VisualBasicCompilation.TupleNamesEncoder.TryGetNames(type, builder) AndAlso compilation.HasTupleNamesAttributes,
New ReadOnlyCollection(Of String)(builder.ToArray()),
Nothing)
builder.Free()
Return CustomTypeInfo.Encode(Nothing, names)
End Function
Friend ReadOnly IdentityComparer As AssemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default
' XML file references, #r directives not supported:
......
......@@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class EEAssemblyBuilder
Inherits PEAssemblyBuilderBase
Private ReadOnly _methods As ImmutableArray(Of MethodSymbol)
Friend ReadOnly Methods As ImmutableArray(Of MethodSymbol)
Friend Sub New(
sourceAssembly As SourceAssemblySymbol,
......@@ -36,7 +36,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
manifestResources:=SpecializedCollections.EmptyEnumerable(Of ResourceDescription)(),
additionalTypes:=additionalTypes)
_methods = methods
Me.Methods = methods
If testData IsNot Nothing Then
SetMethodTestData(testData.Methods)
......@@ -74,12 +74,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend Overrides Function TryCreateVariableSlotAllocator(symbol As MethodSymbol, topLevelMethod As MethodSymbol, diagnostics As DiagnosticBag) As VariableSlotAllocator
Dim method = TryCast(symbol, EEMethodSymbol)
If method IsNot Nothing AndAlso _methods.Contains(method) Then
If method IsNot Nothing AndAlso Methods.Contains(method) Then
Dim defs = GetLocalDefinitions(method.Locals)
Return New SlotAllocator(defs)
End If
Debug.Assert(Not _methods.Contains(symbol))
Debug.Assert(Not Methods.Contains(symbol))
Return Nothing
End Function
......
......@@ -187,7 +187,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim currentFrame = compilation.GetMethod(moduleVersionId, methodHandle)
Debug.Assert(currentFrame IsNot Nothing)
Dim symbolProvider = New VisualBasicEESymbolProvider(DirectCast(currentFrame.ContainingModule, PEModuleSymbol), currentFrame)
Dim symbolProvider = New VisualBasicEESymbolProvider(compilation.SourceAssembly, DirectCast(currentFrame.ContainingModule, PEModuleSymbol), currentFrame)
Dim metadataDecoder = New MetadataDecoder(DirectCast(currentFrame.ContainingModule, PEModuleSymbol), currentFrame)
Dim localInfo = metadataDecoder.GetLocalInfo(localSignatureHandle)
......@@ -409,8 +409,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
resultProperties = properties
Return New VisualBasicCompileResult(
stream.ToArray(),
s_typeName,
s_methodName,
GetSynthesizedMethod(moduleBuilder),
formatSpecifiers)
End Using
End Function
......@@ -459,8 +458,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
properties.ModifierFlags)
Return New VisualBasicCompileResult(
stream.ToArray(),
s_typeName,
s_methodName,
GetSynthesizedMethod(modulebuilder),
formatSpecifiers:=Nothing)
End Using
End Function
......@@ -647,6 +645,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Private Shared Function IsValidMissingAssemblyIdentity(identity As AssemblyIdentity) As Boolean
Return identity IsNot Nothing AndAlso Not identity.Equals(MissingCorLibrarySymbol.Instance.Identity)
End Function
Private Shared Function GetSynthesizedMethod(moduleBuilder As CommonPEModuleBuilder) As MethodSymbol
Dim method = DirectCast(moduleBuilder, EEAssemblyBuilder).Methods.Single(Function(m) m.MetadataName = s_methodName)
Debug.Assert(method.ContainingType.MetadataName = s_typeName)
Return method
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.Immutable
Imports System.Collections.ObjectModel
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend Module SymbolExtensions
<Extension>
Friend Function GetCustomTypeInfoPayload(method As MethodSymbol) As ReadOnlyCollection(Of Byte)
Return method.DeclaringCompilation.GetCustomTypeInfoPayload(method.ReturnType)
End Function
<Extension>
Public Function IsContainingSymbolOfAllTypeParameters(containingSymbol As Symbol, type As TypeSymbol) As Boolean
Return type.VisitType(s_hasInvalidTypeParameterFunc, containingSymbol) Is Nothing
......
......@@ -578,6 +578,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End Select
End Function
Friend Overrides Sub AddSynthesizedReturnTypeAttributes(ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedReturnTypeAttributes(attributes)
Dim returnType = Me.ReturnType
If returnType.ContainsTupleNames() AndAlso DeclaringCompilation.HasTupleNamesAttributes() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(returnType))
End If
End Sub
Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
Return localPosition
End Function
......
' 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.Immutable
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
......@@ -25,6 +26,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend Overloads Shared Function Create(
typeNameDecoder As TypeNameDecoder(Of PEModuleSymbol, TypeSymbol),
containingMethod As MethodSymbol,
sourceAssembly As AssemblySymbol,
[alias] As [Alias]) As PlaceholderLocalSymbol
Dim typeName = [alias].Type
......@@ -33,6 +35,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim type = typeNameDecoder.GetTypeSymbolForSerializedType(typeName)
Debug.Assert(type IsNot Nothing)
Dim dynamicFlags As ReadOnlyCollection(Of Byte) = Nothing
Dim tupleElementNames As ReadOnlyCollection(Of String) = Nothing
CustomTypeInfo.Decode([alias].CustomTypeInfoId, [alias].CustomTypeInfo, dynamicFlags, tupleElementNames)
If tupleElementNames IsNot Nothing Then
type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, sourceAssembly, tupleElementNames.AsImmutable())
End If
Dim name = [alias].FullName
Dim displayName = [alias].Name
Select Case [alias].Kind
......
......@@ -2,23 +2,27 @@
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class VisualBasicCompileResult : Inherits CompileResult
Friend NotInheritable Class VisualBasicCompileResult
Inherits CompileResult
Private ReadOnly _method As MethodSymbol
Public Sub New(
assembly As Byte(),
typeName As String,
methodName As String,
method As MethodSymbol,
formatSpecifiers As ReadOnlyCollection(Of String))
MyBase.New(assembly, typeName, methodName, formatSpecifiers)
MyBase.New(assembly, method.ContainingType.MetadataName, method.MetadataName, formatSpecifiers)
_method = method
End Sub
Public Overrides Function GetCustomTypeInfo(ByRef payload As ReadOnlyCollection(Of Byte)) As Guid
payload = Nothing
Return Nothing
payload = _method.GetCustomTypeInfoPayload()
Return If(payload Is Nothing, Nothing, CustomTypeInfo.PayloadTypeId)
End Function
End Class
......
......@@ -13,10 +13,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class VisualBasicEESymbolProvider
Inherits EESymbolProvider(Of TypeSymbol, LocalSymbol)
Private ReadOnly _sourceAssembly As SourceAssemblySymbol
Private ReadOnly _metadataDecoder As MetadataDecoder
Private ReadOnly _method As PEMethodSymbol
Public Sub New([module] As PEModuleSymbol, method As PEMethodSymbol)
Public Sub New(sourceAssembly As SourceAssemblySymbol, [module] As PEModuleSymbol, method As PEMethodSymbol)
_sourceAssembly = sourceAssembly
_metadataDecoder = New MetadataDecoder([module], method)
_method = method
End Sub
......@@ -28,13 +30,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
dynamicFlagsOpt As ImmutableArray(Of Boolean),
tupleElementNamesOpt As ImmutableArray(Of String)) As LocalSymbol
' ignore dynamic flags (in theory the CDI might be present in bad PDB)
' Custom modifiers can be dropped since binding ignores custom
' modifiers from locals and since we only need to preserve
' the type of the original local in the generated method.
Dim kind = If(name = _method.Name, LocalDeclarationKind.FunctionValue, LocalDeclarationKind.Variable)
Return New EELocalSymbol(_method, EELocalSymbol.NoLocations, name, slotIndex, kind, info.Type, info.IsByRef, info.IsPinned, canScheduleToStack:=False)
Dim type = IncludeTupleElementNamesIfAny(info.Type, tupleElementNamesOpt)
Return New EELocalSymbol(_method, EELocalSymbol.NoLocations, name, slotIndex, kind, type, info.IsByRef, info.IsPinned, canScheduleToStack:=False)
End Function
Public Overrides Function GetLocalConstant(
......@@ -44,7 +45,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
dynamicFlagsOpt As ImmutableArray(Of Boolean),
tupleElementNamesOpt As ImmutableArray(Of String)) As LocalSymbol
' ignore dynamic flags (in theory the CDI might be present in bad PDB)
type = IncludeTupleElementNamesIfAny(type, tupleElementNamesOpt)
Return New EELocalConstantSymbol(_method, name, type, value)
End Function
......@@ -76,5 +77,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Return _metadataDecoder.GetSymbolForTypeHandleOrThrow(handle, isNoPiaLocalType, allowTypeSpec:=True, requireShortForm:=False)
End Function
Private Function IncludeTupleElementNamesIfAny(type As TypeSymbol, tupleElementNamesOpt As ImmutableArray(Of String)) As TypeSymbol
Return If(tupleElementNamesOpt.IsDefault,
type,
TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, _sourceAssembly, tupleElementNamesOpt))
End Function
End Class
End Namespace
......@@ -2,19 +2,23 @@
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend NotInheritable Class VisualBasicLocalAndMethod : Inherits LocalAndMethod
Public Sub New(localName As String, localDisplayName As String, methodName As String, flags As DkmClrCompilationResultFlags)
MyBase.New(localName, localDisplayName, methodName, flags)
Private ReadOnly _method As MethodSymbol
Public Sub New(localName As String, localDisplayName As String, method As MethodSymbol, flags As DkmClrCompilationResultFlags)
MyBase.New(localName, localDisplayName, method.Name, flags)
_method = method
End Sub
Public Overrides Function GetCustomTypeInfo(ByRef payload As ReadOnlyCollection(Of Byte)) As Guid
payload = Nothing
Return Nothing
payload = _method.GetCustomTypeInfoPayload()
Return If(payload Is Nothing, Nothing, CustomTypeInfo.PayloadTypeId)
End Function
End Class
......
......@@ -355,7 +355,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
Dim peMethod = peCompilation.GlobalNamespace.GetMember(Of PEMethodSymbol)(qualifiedMethodName)
Dim peModule = DirectCast(peMethod.ContainingModule, PEModuleSymbol)
Dim symReader = runtime.Modules.Single(Function(mi) mi.ModuleVersionId = peModule.Module.GetModuleVersionIdOrThrow()).SymReader
Dim symbolProvider = New VisualBasicEESymbolProvider(peModule, peMethod)
Dim symbolProvider = New VisualBasicEESymbolProvider(peCompilation.SourceAssembly, peModule, peMethod)
Return MethodDebugInfo(Of TypeSymbol, LocalSymbol).ReadMethodDebugInfo(DirectCast(symReader, ISymUnmanagedReader3), symbolProvider, MetadataTokens.GetToken(peMethod.Handle), methodVersion:=1, ilOffset:=ilOffset, isVisualBasicMethod:=True)
End Function
......
' 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.Immutable
Imports System.Collections.ObjectModel
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Microsoft.VisualStudio.Debugger.Clr
Imports Microsoft.VisualStudio.Debugger.Evaluation
Imports Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation
Imports Roslyn.Test.Utilities
Imports Xunit
......@@ -14,8 +18,104 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
Public Class TupleTests
Inherits ExpressionCompilerTestBase
<Fact>
Public Sub Literal()
Const source =
"Class C
Shared Sub M()
Dim o As (Integer, Integer)
End Sub
End Class"
Dim comp = CreateCompilationWithMscorlib({source}, references:={ValueTupleRef}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
Dim errorMessage As String = Nothing
Dim testData = New CompilationTestData()
Dim result = context.CompileExpression(
"(A:=1, B:=2)",
DkmEvaluationFlags.TreatAsExpression,
NoAliases,
errorMessage,
testData)
Assert.Null(errorMessage)
Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing
Dim typeInfoId = result.GetCustomTypeInfo(typeInfo)
Assert.NotNull(typeInfo)
Dim dynamicFlags As ReadOnlyCollection(Of Byte) = Nothing
Dim tupleElementNames As ReadOnlyCollection(Of String) = Nothing
CustomTypeInfo.Decode(typeInfoId, typeInfo, dynamicFlags, tupleElementNames)
Assert.Equal({"A", "B"}, tupleElementNames)
Dim methodData = testData.GetMethodData("<>x.<>m0")
Dim method = methodData.Method
Assert.True(method.ReturnType.IsTupleType)
Assert.NotNull(GetTupleElementNamesAttributeIfAny(method))
methodData.VerifyIL(
"{
// Code size 8 (0x8)
.maxstack 2
.locals init (System.ValueTuple(Of Integer, Integer) V_0) //o
IL_0000: ldc.i4.1
IL_0001: ldc.i4.2
IL_0002: newobj ""Sub System.ValueTuple(Of Integer, Integer)..ctor(Integer, Integer)""
IL_0007: ret
}")
End Sub)
End Sub
<Fact>
Public Sub TupleElementNamesAttribute_NotAvailable()
Const source =
"Namespace System
Public Structure ValueTuple(Of T1, T2)
Public Item1 As T1
Public Item2 As T2
Public Sub New(_1 As T1, _2 As T2)
Item1 = _1
Item2 = _2
End Sub
End Structure
End Namespace
Class C
Shared Sub M()
Dim o As (Integer, Integer)
End Sub
End Class"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
Dim errorMessage As String = Nothing
Dim testData = New CompilationTestData()
Dim result = context.CompileExpression(
"(A:=1, B:=2)",
DkmEvaluationFlags.TreatAsExpression,
NoAliases,
errorMessage,
testData)
Assert.Null(errorMessage)
Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing
Dim typeInfoId = result.GetCustomTypeInfo(typeInfo)
Assert.Null(typeInfo)
Dim methodData = testData.GetMethodData("<>x.<>m0")
Dim method = methodData.Method
Assert.True(method.ReturnType.IsTupleType)
Assert.Null(GetTupleElementNamesAttributeIfAny(method))
methodData.VerifyIL(
"{
// Code size 8 (0x8)
.maxstack 2
.locals init (System.ValueTuple(Of Integer, Integer) V_0) //o
IL_0000: ldc.i4.1
IL_0001: ldc.i4.2
IL_0002: newobj ""Sub System.ValueTuple(Of Integer, Integer)..ctor(Integer, Integer)""
IL_0007: ret
}")
End Sub)
End Sub
<WorkItem(13948, "https://github.com/dotnet/roslyn/issues/13948")>
<Fact(Skip:="13948")>
<Fact>
Public Sub Local()
Const source =
"class C
......@@ -47,7 +147,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
"{
// Code size 2 (0x2)
.maxstack 1
.locals init ((int A, int B) V_0) //o
.locals init ((A As Integer, B As Integer) V_0) //o
IL_0000: ldloc.0
IL_0001: ret
}")
......@@ -56,7 +156,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
End Sub
<WorkItem(13948, "https://github.com/dotnet/roslyn/issues/13948")>
<Fact(Skip:="13948")>
<Fact>
Public Sub Constant()
Const source =
"class A<T>
......@@ -104,6 +204,120 @@ class C
End Sub)
End Sub
''' <summary>
''' Locals declared in the VB EE do not have an explicit
''' type and are statically typed to Object, so tuple
''' element names on the value are not preserved.
''' </summary>
<Fact>
Public Sub DeclareLocal()
Const source =
"Class C
Shared Sub M()
Dim x = (1, 2)
End Sub
End Class"
Dim comp = CreateCompilationWithMscorlib({source}, references:={ValueTupleRef}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
Dim errorMessage As String = Nothing
Dim testData = New CompilationTestData()
Dim result = context.CompileExpression(
"y = DirectCast(x, (A As Integer, B As Integer))",
DkmEvaluationFlags.None,
NoAliases,
errorMessage,
testData)
Assert.Null(errorMessage)
Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing
Dim typeInfoId = result.GetCustomTypeInfo(typeInfo)
Assert.Null(typeInfo)
Dim methodData = testData.GetMethodData("<>x.<>m0")
Dim method = methodData.Method
Assert.Null(GetTupleElementNamesAttributeIfAny(method))
methodData.VerifyIL(
"{
// Code size 43 (0x2b)
.maxstack 4
.locals init (System.ValueTuple(Of Integer, Integer) V_0, //x
System.Guid V_1)
IL_0000: ldtoken ""Object""
IL_0005: call ""Function System.Type.GetTypeFromHandle(System.RuntimeTypeHandle) As System.Type""
IL_000a: ldstr ""y""
IL_000f: ldloca.s V_1
IL_0011: initobj ""System.Guid""
IL_0017: ldloc.1
IL_0018: ldnull
IL_0019: call ""Sub Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, String, System.Guid, Byte())""
IL_001e: ldstr ""y""
IL_0023: call ""Function Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress(Of Object)(String) As Object""
IL_0028: ldloc.0
IL_0029: stind.ref
IL_002a: ret
}")
End Sub)
End Sub
<WorkItem(13589, "https://github.com/dotnet/roslyn/issues/13589")>
<Fact>
Public Sub [Alias]()
Const source =
"Class C
Shared F As (Integer, Integer)
Shared Sub M()
End Sub
End Class"
Dim comp = CreateCompilationWithMscorlib({source}, references:={ValueTupleRef}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
Dim locals = ArrayBuilder(Of LocalAndMethod).GetInstance()
Dim typeName As String = Nothing
Dim aliasElementNames = New ReadOnlyCollection(Of String)({"A", "B", Nothing, "D"})
Dim [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(Nothing, aliasElementNames))
Dim diagnostics = DiagnosticBag.GetInstance()
Dim testData = New CompilationTestData()
Dim assembly = context.CompileGetLocals(
locals,
argumentsOnly:=False,
aliases:=ImmutableArray.Create([alias]),
diagnostics:=diagnostics,
typeName:=typeName,
testData:=testData)
diagnostics.Verify()
diagnostics.Free()
Assert.Equal(1, locals.Count)
Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing
Dim typeInfoId = locals(0).GetCustomTypeInfo(typeInfo)
Dim dynamicFlags As ReadOnlyCollection(Of Byte) = Nothing
Dim tupleElementNames As ReadOnlyCollection(Of String) = Nothing
CustomTypeInfo.Decode(typeInfoId, typeInfo, dynamicFlags, tupleElementNames)
Assert.Equal(aliasElementNames, tupleElementNames)
Dim method = testData.Methods.Single().Value.Method
Assert.NotNull(GetTupleElementNamesAttributeIfAny(method))
Dim returnType = DirectCast(method.ReturnType, TypeSymbol)
Assert.False(returnType.IsTupleType)
Assert.True(DirectCast(returnType, ArrayTypeSymbol).ElementType.IsTupleType)
VerifyLocal(testData, typeName, locals(0), "<>m0", "t", expectedILOpt:=
"{
// Code size 16 (0x10)
.maxstack 1
IL_0000: ldstr ""t""
IL_0005: call ""Function Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectByAlias(String) As Object""
IL_000a: castclass ""(A As Integer, B As (Integer, D As Integer))()""
IL_000f: ret
}")
locals.Free()
End Sub)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册