提交 9acdab40 编写于 作者: T Tomas Matousek

Enable Portable PDB in VB EEs, fix import scope issues

上级 38017cba
......@@ -5,6 +5,7 @@ Imports System.Reflection.Metadata
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
......@@ -1413,23 +1414,24 @@ OtherExpressions:
Private Sub EmitStateMachineScope(scope As BoundStateMachineScope)
_builder.OpenLocalScope()
'VB EE uses name mangling to match up original locals and the fields where they are hoisted
'The scoping information is passed by recording PDB scopes of "fake" locals named the same
'as the fields. These locals are not emitted to IL.
If _module.EmitOptions.DebugInformationFormat = DebugInformationFormat.Pdb Then
'Native PDBs: VB EE uses name mangling to match up original locals and the fields where they are hoisted
'The scoping information is passed by recording PDB scopes of "fake" locals named the same
'as the fields. These locals are not emitted to IL.
' vb\language\debugger\procedurecontext.cpp
' 813 // Since state machines lift (almost) all locals of a method, the lifted fields should
' 814 // only be shown in the debugger when the original local variable was in scope. So
' 815 // we first check if there's a local by the given name and attempt to remove it from
' 816 // m_localVariableMap. If it was present, we decode the original local's name, otherwise
' 817 // we skip loading this lifted field since it is out of scope.
' vb\language\debugger\procedurecontext.cpp
' 813 // Since state machines lift (almost) all locals of a method, the lifted fields should
' 814 // only be shown in the debugger when the original local variable was in scope. So
' 815 // we first check if there's a local by the given name and attempt to remove it from
' 816 // m_localVariableMap. If it was present, we decode the original local's name, otherwise
' 817 // we skip loading this lifted field since it is out of scope.
For Each field In scope.Fields
DefineUserDefinedStateMachineHoistedLocal(DirectCast(field, StateMachineFieldSymbol))
Next
For Each field In scope.Fields
DefineUserDefinedStateMachineHoistedLocal(DirectCast(field, StateMachineFieldSymbol))
Next
End If
EmitStatement(scope.Statement)
_builder.CloseLocalScope()
End Sub
......
......@@ -345,7 +345,7 @@ internal static Alias Alias(DkmClrAliasKind kind, string name, string fullName,
return new Alias(kind, name, fullName, type, customTypeInfo);
}
internal static MethodDebugInfo<TypeSymbol, LocalSymbol> GetMethodDebugInfo(RuntimeInstance runtime, string qualifiedMethodName)
internal static MethodDebugInfo<TypeSymbol, LocalSymbol> GetMethodDebugInfo(RuntimeInstance runtime, string qualifiedMethodName, int ilOffset = 0)
{
var peCompilation = runtime.Modules.SelectAsArray(m => m.MetadataBlock).ToCompilation();
var peMethod = peCompilation.GlobalNamespace.GetMember<PEMethodSymbol>(qualifiedMethodName);
......@@ -354,7 +354,7 @@ internal static Alias Alias(DkmClrAliasKind kind, string name, string fullName,
var symReader = runtime.Modules.Single(mi => mi.ModuleVersionId == peModule.Module.GetModuleVersionIdOrThrow()).SymReader;
var symbolProvider = new CSharpEESymbolProvider((SourceAssemblySymbol)peCompilation.Assembly, peModule, peMethod);
return MethodDebugInfo<TypeSymbol, LocalSymbol>.ReadMethodDebugInfo((ISymUnmanagedReader)symReader, symbolProvider, MetadataTokens.GetToken(peMethod.Handle), methodVersion: 1, ilOffset: 0, isVisualBasicMethod: false);
return MethodDebugInfo<TypeSymbol, LocalSymbol>.ReadMethodDebugInfo((ISymUnmanagedReader)symReader, symbolProvider, MetadataTokens.GetToken(peMethod.Handle), methodVersion: 1, ilOffset: ilOffset, isVisualBasicMethod: false);
}
}
}
......@@ -48,6 +48,51 @@ void M()
});
}
[Fact]
public void NestedScopes()
{
var source = @"
using System;
class C
{
void M()
{
int i = 1;
{
int j = 2;
}
}
}
";
var comp = CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll);
CompileAndVerify(comp).VerifyIL("C.M", @"
{
// Code size 8 (0x8)
.maxstack 1
.locals init (int V_0, //i
int V_1) //j
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: nop
IL_0004: ldc.i4.2
IL_0005: stloc.1
IL_0006: nop
IL_0007: ret
}
");
WithRuntimeInstance(comp, runtime =>
{
GetMethodDebugInfo(runtime, "C.M", ilOffset: 0x0004).ImportRecordGroups.Verify(@"
{
Namespace: string='System'
}");
});
}
[Fact]
public void NestedNamespaces()
{
......
......@@ -27,7 +27,7 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
}
var symReader4 = symReader as ISymUnmanagedReader4;
if (symReader4 != null && !isVisualBasicMethod) // TODO: VB Portable PDBs
if (symReader4 != null) // TODO: VB Portable PDBs
{
byte* metadata;
int size;
......@@ -41,7 +41,7 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
var mdReader = new MetadataReader(metadata, size);
try
{
return ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt);
return ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod);
}
catch (BadImageFormatException)
{
......@@ -349,8 +349,8 @@ private static bool TryCreateImportRecordFromCSharpImportString(EESymbolProvider
}
importRecordGroups = ImmutableArray.Create(
projectLevelImportRecords.ToImmutableAndFree(),
fileLevelImportRecords.ToImmutableAndFree());
fileLevelImportRecords.ToImmutableAndFree(),
projectLevelImportRecords.ToImmutableAndFree());
defaultNamespaceName = defaultNamespaceName ?? "";
}
......
// 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.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
......@@ -14,7 +15,7 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
{
/// <exception cref="BadImageFormatException">Invalid data format.</exception>
public static MethodDebugInfo<TTypeSymbol, TLocalSymbol> ReadFromPortable(MetadataReader reader, int methodToken, int ilOffset, EESymbolProvider<TTypeSymbol, TLocalSymbol> symbolProvider)
public static MethodDebugInfo<TTypeSymbol, TLocalSymbol> ReadFromPortable(MetadataReader reader, int methodToken, int ilOffset, EESymbolProvider<TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod)
{
string defaultNamespace;
ImmutableArray<HoistedLocalScopeRecord> hoistedLocalScopes;
......@@ -27,7 +28,7 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
var methodHandle = (MethodDefinitionHandle)MetadataTokens.EntityHandle(methodToken);
ReadLocalScopeInformation(reader, methodHandle, ilOffset, symbolProvider, out importGroups, out externAliases, out localVariableNames, out dynamicLocals, out localConstants, out reuseSpan);
ReadLocalScopeInformation(reader, methodHandle, ilOffset, symbolProvider, isVisualBasicMethod, out importGroups, out externAliases, out localVariableNames, out dynamicLocals, out localConstants, out reuseSpan);
ReadMethodCustomDebugInformation(reader, methodHandle, out hoistedLocalScopes, out defaultNamespace);
return new MethodDebugInfo<TTypeSymbol, TLocalSymbol>(
......@@ -46,6 +47,7 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
MethodDefinitionHandle methodHandle,
int ilOffset,
EESymbolProvider<TTypeSymbol, TLocalSymbol> symbolProvider,
bool isVisualBasicMethod,
out ImmutableArray<ImmutableArray<ImportRecord>> importGroups,
out ImmutableArray<ExternAliasRecord> externAliases,
out ImmutableArray<string> localVariableNames,
......@@ -53,13 +55,12 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
out ImmutableArray<TLocalSymbol> localConstants,
out ILSpan reuseSpan)
{
var importGroupsBuilder = ArrayBuilder<ImmutableArray<ImportRecord>>.GetInstance();
var externAliasesBuilder = ArrayBuilder<ExternAliasRecord>.GetInstance();
var localVariableNamesBuilder = ArrayBuilder<string>.GetInstance();
var localConstantsBuilder = ArrayBuilder<TLocalSymbol>.GetInstance();
ImmutableDictionary<int, ImmutableArray<bool>>.Builder lazyDynamicLocalsBuilder = null;
var innerMostImportScope = default(ImportScopeHandle);
uint reuseSpanStart = 0;
uint reuseSpanEnd = uint.MaxValue;
try
......@@ -87,13 +88,10 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.StartOffset);
reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.EndOffset);
// imports:
if (!scope.ImportScope.IsNil)
{
PopulateImports(reader, scope.ImportScope, symbolProvider, importGroupsBuilder, externAliasesBuilder);
}
// imports (use the inner-most):
innerMostImportScope = scope.ImportScope;
// locals:
// locals (from all contained scopes):
foreach (var variableHandle in scope.GetLocalVariables())
{
var variable = reader.GetLocalVariable(variableHandle);
......@@ -112,7 +110,7 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
}
}
// constants:
// constants (from all contained scopes):
foreach (var constantHandle in scope.GetLocalConstants())
{
var constant = reader.GetLocalConstant(constantHandle);
......@@ -134,13 +132,29 @@ partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
}
finally
{
importGroups = importGroupsBuilder.ToImmutableAndFree();
externAliases = externAliasesBuilder.ToImmutableAndFree();
localVariableNames = localVariableNamesBuilder.ToImmutableAndFree();
localConstants = localConstantsBuilder.ToImmutableAndFree();
dynamicLocals = lazyDynamicLocalsBuilder?.ToImmutable();
reuseSpan = new ILSpan(reuseSpanStart, reuseSpanEnd);
}
var importGroupsBuilder = ArrayBuilder<ImmutableArray<ImportRecord>>.GetInstance();
var externAliasesBuilder = ArrayBuilder<ExternAliasRecord>.GetInstance();
try
{
if (!innerMostImportScope.IsNil)
{
PopulateImports(reader, innerMostImportScope, symbolProvider, isVisualBasicMethod, importGroupsBuilder, externAliasesBuilder);
}
}
catch (Exception e) when (e is UnsupportedSignatureContent || e is BadImageFormatException)
{
// ignore invalid imports
}
importGroups = importGroupsBuilder.ToImmutableAndFree();
externAliases = externAliasesBuilder.ToImmutableAndFree();
}
private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
......@@ -154,6 +168,7 @@ private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
MetadataReader reader,
ImportScopeHandle handle,
EESymbolProvider<TTypeSymbol, TLocalSymbol> symbolProvider,
bool isVisualBasicMethod,
ArrayBuilder<ImmutableArray<ImportRecord>> importGroupsBuilder,
ArrayBuilder<ExternAliasRecord> externAliasesBuilder)
{
......@@ -229,7 +244,9 @@ private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
}
}
if (importGroupBuilder.Count > 0)
// VB always expects two import groups (even if they are empty).
// TODO: consider doing this for C# as well and handle empty groups in the binder.
if (isVisualBasicMethod || importGroupBuilder.Count > 0)
{
importGroupsBuilder.Add(importGroupBuilder.ToImmutable());
importGroupBuilder.Clear();
......@@ -249,7 +266,6 @@ private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
out string defaultNamespace)
{
hoistedLocalScopes = ImmutableArray<HoistedLocalScopeRecord>.Empty;
defaultNamespace = "";
foreach (var infoHandle in reader.GetCustomDebugInformation(methodHandle))
{
......@@ -257,7 +273,7 @@ private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
var id = reader.GetGuid(info.Kind);
if (id == PortableCustomDebugInfoKinds.StateMachineHoistedLocalScopes)
{
// only single CDI is allowed on a method:
// only single CDIof this kind is allowed on a method:
if (!hoistedLocalScopes.IsEmpty)
{
throw new BadImageFormatException();
......@@ -265,12 +281,28 @@ private static string ReadUtf8String(MetadataReader reader, BlobHandle handle)
hoistedLocalScopes = DecodeHoistedLocalScopes(reader.GetBlobReader(info.Value));
}
else if (id == PortableCustomDebugInfoKinds.DefaultNamespace)
}
// TODO: consider looking this up once per module (not for every method)
defaultNamespace = null;
foreach (var infoHandle in reader.GetCustomDebugInformation(EntityHandle.ModuleDefinition))
{
var info = reader.GetCustomDebugInformation(infoHandle);
var id = reader.GetGuid(info.Kind);
if (id == PortableCustomDebugInfoKinds.DefaultNamespace)
{
// only single CDI of this kind is allowed on the module:
if (defaultNamespace != null)
{
throw new BadImageFormatException();
}
var valueReader = reader.GetBlobReader(info.Value);
defaultNamespace = valueReader.ReadUTF8(valueReader.Length);
}
}
defaultNamespace = defaultNamespace ?? "";
}
/// <exception cref="BadImageFormatException">Invalid data format.</exception>
......
......@@ -632,9 +632,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Dim projectLevelXmlImports As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) = Nothing
Dim fileLevelXmlImports As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) = Nothing
Debug.Assert(importRecordGroups.Length = 2) ' First project-level, then file-level.
Dim projectLevelImportRecords = importRecordGroups(0)
Dim fileLevelImportRecords = importRecordGroups(1)
Debug.Assert(importRecordGroups.Length = 2) ' First file-level, then project-level.
Dim projectLevelImportRecords = importRecordGroups(1)
Dim fileLevelImportRecords = importRecordGroups(0)
' Use this to give the imports different positions
Dim position = 0
......@@ -792,12 +792,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Return False ' Don't add anything for this import.
End If
If importsBuilder Is Nothing Then
importsBuilder = ArrayBuilder(Of NamespaceOrTypeAndImportsClausePosition).GetInstance()
End If
' Native PDBs: aliased namespace is stored as NamespaceOrType
' Portable PDBs: aliased namespace is stored as Namespace
If [alias] Is Nothing Then
If importsBuilder Is Nothing Then
importsBuilder = ArrayBuilder(Of NamespaceOrTypeAndImportsClausePosition).GetInstance()
End If
' There's no real syntax, so there's no real position. We'll give them separate numbers though.
importsBuilder.Add(New NamespaceOrTypeAndImportsClausePosition(namespaceOrTypeSymbol, position))
' There's no real syntax, so there's no real position. We'll give them separate numbers though.
importsBuilder.Add(New NamespaceOrTypeAndImportsClausePosition(namespaceOrTypeSymbol, position))
Else
Dim aliasSymbol As New AliasSymbol(importBinder.Compilation, importBinder.ContainingNamespaceOrType, [alias], namespaceOrTypeSymbol, NoLocation.Singleton)
If aliases Is Nothing Then
aliases = New Dictionary(Of String, AliasAndImportsClausePosition)()
End If
' There's no real syntax, so there's no real position. We'll give them separate numbers though.
aliases([alias]) = New AliasAndImportsClausePosition(aliasSymbol, position)
End If
Case ImportTargetKind.NamespaceOrType ' Aliased namespace or type (native PDB only)
Dim unusedDiagnostics = DiagnosticBag.GetInstance()
......@@ -822,6 +835,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
' There's no real syntax, so there's no real position. We'll give them separate numbers though.
aliases([alias]) = New AliasAndImportsClausePosition(aliasSymbol, position)
Case ImportTargetKind.XmlNamespace
If xmlImports Is Nothing Then
xmlImports = New Dictionary(Of String, XmlNamespaceAndImportsClausePosition)()
......
......@@ -45,14 +45,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
_runtimeInstances.Free()
End Sub
' TODO: remove -- workaround for bugs in Portable PDB handling in EE
' TODO: remove -- workaround for bug https://github.com/dotnet/roslyn/issues/8473 in the VB compiler
' https://github.com/dotnet/roslyn/issues/8473
Friend Shared Sub WithRuntimeInstancePortableBug(compilation As Compilation, validator As Action(Of RuntimeInstance))
WithRuntimeInstancePortableBug(compilation, Nothing, validator)
End Sub
' TODO: remove -- workaround for bugs in Portable PDB handling in EE
Friend Shared Sub WithRuntimeInstancePortableBug(compilation As Compilation, references As IEnumerable(Of MetadataReference), validator As Action(Of RuntimeInstance))
Using instance = RuntimeInstance.Create(compilation, references, DebugInformationFormat.Pdb, True)
Using instance = RuntimeInstance.Create(compilation, Nothing, DebugInformationFormat.Pdb, True)
validator(instance)
End Using
End Sub
......@@ -357,5 +353,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
Friend Shared Function [Alias](kind As DkmClrAliasKind, name As String, fullName As String, typeAssemblyQualifiedName As String, customTypeInfo As CustomTypeInfo) As [Alias]
Return New [Alias](kind, name, fullName, typeAssemblyQualifiedName, customTypeInfo)
End Function
Friend Shared Function GetMethodDebugInfo(runtime As RuntimeInstance, qualifiedMethodName As String, Optional ilOffset As Integer = 0) As MethodDebugInfo(Of TypeSymbol, LocalSymbol)
Dim peCompilation = runtime.Modules.SelectAsArray(Function(m) m.MetadataBlock).ToCompilation()
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)
Return MethodDebugInfo(Of TypeSymbol, LocalSymbol).ReadMethodDebugInfo(DirectCast(symReader, ISymUnmanagedReader), symbolProvider, MetadataTokens.GetToken(peMethod.Handle), methodVersion:=1, ilOffset:=ilOffset, isVisualBasicMethod:=True)
End Function
End Class
End Namespace
......@@ -5,6 +5,7 @@ Imports System.Globalization
Imports System.IO
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.Test.Utilities
......@@ -1780,7 +1781,7 @@ End Class"
options:=TestOptions.DebugDll.WithRootNamespace("Root"),
references:=allReferences)
WithRuntimeInstancePortableBug(comp, allReferences,
WithRuntimeInstance(comp, allReferences,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "Root.C.M")
Dim errorMessage As String = Nothing
......@@ -3999,7 +4000,7 @@ Module Module1
End Sub
End Module"
Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(MakeSources(source), options:=TestOptions.DebugDll)
WithRuntimeInstance(compilation,
WithRuntimeInstancePortableBug(compilation,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "Module1._Closure$__.VB$StateMachine___Lambda$__0-0.MoveNext")
Dim errorMessage As String = Nothing
......@@ -4031,7 +4032,7 @@ Class C
End Sub
End Class"
Dim compilation = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll)
WithRuntimeInstancePortableBug(compilation,
WithRuntimeInstance(compilation,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
......@@ -4163,7 +4164,7 @@ End Class"
options:=TestOptions.DebugDll,
assemblyName:=ExpressionCompilerUtilities.GenerateUniqueName())
WithRuntimeInstancePortableBug(compilation0,
WithRuntimeInstance(compilation0,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
Dim errorMessage As String = Nothing
......
......@@ -101,9 +101,8 @@ End Class
}}
"
Dim comp = CreateCompilation(source)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context As EvaluationContext
Dim testData As CompilationTestData
Dim errorMessage As String = Nothing
......@@ -209,7 +208,7 @@ End Class
}}
"
Dim comp = CreateCompilation(source)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context As EvaluationContext
......@@ -291,7 +290,7 @@ End Class
}}
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll, assemblyName:=GetUniqueName())
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context As EvaluationContext
......@@ -1436,7 +1435,7 @@ Class C
End Class
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim blocks As ImmutableArray(Of MetadataBlock) = Nothing
Dim moduleVersionId As Guid = Nothing
......
......@@ -7,6 +7,7 @@ Imports System.Reflection.Metadata
Imports System.Reflection.Metadata.Ecma335
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
......@@ -35,10 +36,28 @@ End Class
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.ReleaseDll)
comp.GetDiagnostics().Where(Function(d) d.Severity > DiagnosticSeverity.Info).Verify()
Dim importStrings = GetImportStrings(comp, "M")
AssertEx.SetEqual(importStrings, "@F:System", "")
WithRuntimeInstance(comp,
Sub(runtime)
Dim info = GetMethodDebugInfo(runtime, "C.M")
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
info.ImportRecordGroups.Verify("
{
Namespace: string='System'
}
{
}")
Else
info.ImportRecordGroups.Verify("
{
Namespace: string='System'
CurrentNamespace: string=''
}
{
}")
End If
End Sub)
End Sub
<Fact>
......@@ -56,13 +75,51 @@ End Class
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.ReleaseDll)
comp.GetDiagnostics().Where(Function(d) d.Severity > DiagnosticSeverity.Info).Verify()
Dim importStrings1 = GetImportStrings(comp, "M1")
AssertEx.SetEqual(importStrings1, "@F:System.IO", "")
Dim importStrings2 = GetImportStrings(comp, "M2")
Assert.Equal(importStrings1.AsEnumerable(), importStrings2)
WithRuntimeInstance(comp,
Sub(runtime)
Dim info1 = GetMethodDebugInfo(runtime, "C.M1")
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
info1.ImportRecordGroups.Verify("
{
Namespace: string='System.IO'
}
{
}")
Else
info1.ImportRecordGroups.Verify("
{
Namespace: string='System.IO'
CurrentNamespace: string=''
}
{
}")
End If
Assert.Equal("", info1.DefaultNamespaceName)
Dim info2 = GetMethodDebugInfo(runtime, "C.M2")
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
info2.ImportRecordGroups.Verify("
{
Namespace: string='System.IO'
}
{
}")
Else
info2.ImportRecordGroups.Verify("
{
Namespace: string='System.IO'
CurrentNamespace: string=''
}
{
}")
End If
Assert.Equal("", info2.DefaultNamespaceName)
End Sub)
End Sub
<Fact>
......@@ -92,51 +149,56 @@ End Namespace
"<xmlns=""http://xml2"">",
"<xmlns:F=""http://xml3"">"
}))
Dim comp = CreateCompilationWithMscorlib({source}, options:=options)
comp.GetDiagnostics().Where(Function(d) d.Severity > DiagnosticSeverity.Info).Verify()
Dim importStrings = GetImportStrings(comp, "M")
AssertEx.SetEqual(
importStrings,
"@F:System", ' File-level namespace
"@FT:System.IO.Path", ' File-level type
"@FA:A=System.Collections", ' File-level aliased namespace
"@FA:B=System.Collections.ArrayList", ' File-level aliased type
"@FX:=http://xml0", ' File-level XML namespace
"@FX:C=http://xml1", ' File-level aliased XML namespace
"@P:System.Runtime", ' Project-level namespace
"@PT:System.Threading.Thread", ' Project-level type
"@PA:D=System.Threading.Tasks", ' Project-level aliased namespace
"@PA:E=System.Threading.Timer", ' Project-level aliased type
"@PX:=http://xml2", ' Project-level XML namespace
"@PX:F=http://xml3", ' Project-level aliased XML namespace
"*root", ' Root namespace
"root.N") ' Containing namespace
WithRuntimeInstance(comp,
Sub(runtime)
Dim info = GetMethodDebugInfo(runtime, "root.N.C.M")
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
info.ImportRecordGroups.Verify("
{
XmlNamespace: alias='' string='http://xml0'
XmlNamespace: alias='C' string='http://xml1'
Namespace: alias='A' string='System.Collections'
Type: alias='B' type='System.Collections.ArrayList'
Namespace: string='System'
Type: type='System.IO.Path'
}
{
XmlNamespace: alias='' string='http://xml2'
XmlNamespace: alias='F' string='http://xml3'
Namespace: alias='D' string='System.Threading.Tasks'
Type: alias='E' type='System.Threading.Timer'
Namespace: string='System.Runtime'
Type: type='System.Threading.Thread'
}")
Else
info.ImportRecordGroups.Verify("
{
XmlNamespace: alias='' string='http://xml0'
XmlNamespace: alias='C' string='http://xml1'
NamespaceOrType: alias='A' string='System.Collections'
NamespaceOrType: alias='B' string='System.Collections.ArrayList'
Namespace: string='System'
Type: string='System.IO.Path'
CurrentNamespace: string='root.N'
}
{
XmlNamespace: alias='' string='http://xml2'
XmlNamespace: alias='F' string='http://xml3'
NamespaceOrType: alias='D' string='System.Threading.Tasks'
NamespaceOrType: alias='E' string='System.Threading.Timer'
Namespace: string='System.Runtime'
Type: string='System.Threading.Thread'
}")
End If
Assert.Equal("root", info.DefaultNamespaceName)
End Sub)
End Sub
Private Shared Function GetImportStrings(compilation As Compilation, methodName As String) As ImmutableArray(Of String)
Assert.NotNull(compilation)
Assert.NotNull(methodName)
Using exebits As New MemoryStream()
Using pdbbits As New MemoryStream()
compilation.Emit(exebits, pdbbits)
exebits.Position = 0
Using metadata = ModuleMetadata.CreateFromStream(exebits, leaveOpen:=True)
Dim [module] = metadata.Module
Dim metadataReader = [module].MetadataReader
Dim methodHandle = metadataReader.MethodDefinitions.Single(Function(mh) metadataReader.GetString(metadataReader.GetMethodDefinition(mh).Name) = methodName)
Dim methodToken = metadataReader.GetToken(methodHandle)
pdbbits.Position = 0
Dim reader = SymReaderFactory.CreateReader(pdbbits)
Return reader.GetVisualBasicImportStrings(methodToken, methodVersion:=1)
End Using
End Using
End Using
End Function
#End Region
#Region "Invalid PDBs"
......@@ -319,17 +381,57 @@ End Namespace
"<xmlns=""http://xml2"">",
"<xmlns:F=""http://xml3"">"
}))
Dim comp = CreateCompilationWithMscorlib({source}, options:=options)
comp.GetDiagnostics().Where(Function(d) d.Severity > DiagnosticSeverity.Info).Verify()
Dim rootNamespace As NamespaceSymbol = Nothing
Dim currentNamespace As NamespaceSymbol = Nothing
Dim typesAndNamespaces As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition) = Nothing
Dim aliases As Dictionary(Of String, AliasAndImportsClausePosition) = Nothing
Dim xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) = Nothing
WithRuntimeInstancePortableBug(comp,
Dim comp = CreateCompilationWithMscorlib({source}, options:=options)
WithRuntimeInstance(comp,
Sub(runtime)
Dim info = GetMethodDebugInfo(runtime, "root.N.C.M")
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
info.ImportRecordGroups.Verify("
{
XmlNamespace: alias='' string='http://xml0'
XmlNamespace: alias='C' string='http://xml1'
Namespace: alias='A' string='System.Collections'
Type: alias='B' type='System.Collections.ArrayList'
Namespace: string='System'
Type: type='System.IO.Path'
}
{
XmlNamespace: alias='' string='http://xml2'
XmlNamespace: alias='F' string='http://xml3'
Namespace: alias='D' string='System.Threading.Tasks'
Type: alias='E' type='System.Threading.Timer'
Namespace: string='System.Runtime'
Type: type='System.Threading.Thread'
}")
Else
info.ImportRecordGroups.Verify("
{
XmlNamespace: alias='' string='http://xml0'
XmlNamespace: alias='C' string='http://xml1'
NamespaceOrType: alias='A' string='System.Collections'
NamespaceOrType: alias='B' string='System.Collections.ArrayList'
Namespace: string='System'
Type: string='System.IO.Path'
CurrentNamespace: string='root.N'
}
{
XmlNamespace: alias='' string='http://xml2'
XmlNamespace: alias='F' string='http://xml3'
NamespaceOrType: alias='D' string='System.Threading.Tasks'
NamespaceOrType: alias='E' string='System.Threading.Timer'
Namespace: string='System.Runtime'
Type: string='System.Threading.Thread'
}")
End If
Dim rootNamespace As NamespaceSymbol = Nothing
Dim currentNamespace As NamespaceSymbol = Nothing
Dim typesAndNamespaces As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition) = Nothing
Dim aliases As Dictionary(Of String, AliasAndImportsClausePosition) = Nothing
Dim xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) = Nothing
GetImports(
runtime,
"root.N.C.M",
......@@ -343,7 +445,11 @@ End Namespace
Assert.Equal("root", rootNamespace.ToTestDisplayString())
Assert.Equal("root.N", currentNamespace.ToTestDisplayString())
AssertEx.SetEqual(typesAndNamespaces.Select(Function(i) i.NamespaceOrType.ToTestDisplayString()), "System", "System.IO.Path", "System.Runtime", "System.Threading.Thread", "root.N")
Dim expectedNamespaces = If(runtime.DebugFormat = DebugInformationFormat.PortablePdb,
{"System", "System.IO.Path", "System.Runtime", "System.Threading.Thread"},
{"System", "System.IO.Path", "System.Runtime", "System.Threading.Thread", "root.N"})
AssertEx.SetEqual(expectedNamespaces, typesAndNamespaces.Select(Function(i) i.NamespaceOrType.ToTestDisplayString()))
AssertEx.SetEqual(aliases.Keys, "A", "B", "D", "E")
Assert.Equal("System.Collections", aliases("A").Alias.Target.ToTestDisplayString())
......@@ -374,7 +480,7 @@ End Namespace
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.ReleaseDll.WithRootNamespace(rootNamespaceName))
comp.GetDiagnostics().Where(Function(d) d.Severity > DiagnosticSeverity.Info).Verify()
WithRuntimeInstancePortableBug(comp,
WithRuntimeInstance(comp,
Sub(runtime)
Dim rootNamespace As NamespaceSymbol = Nothing
Dim currentNamespace As NamespaceSymbol = Nothing
......@@ -395,7 +501,13 @@ End Namespace
Assert.True(rootNamespace.IsGlobalNamespace)
Assert.Equal("N", currentNamespace.ToTestDisplayString())
Assert.Equal("N", typesAndNamespaces.Single().NamespaceOrType.ToTestDisplayString())
' Portable PDB doesn't include CurrentNamespace:
If runtime.DebugFormat = DebugInformationFormat.PortablePdb Then
Assert.True(typesAndNamespaces.IsDefault)
Else
Assert.Equal("N", typesAndNamespaces.Single().NamespaceOrType.ToTestDisplayString())
End If
Assert.Null(aliases)
Assert.Null(xmlNamespaces)
End Sub)
......@@ -439,7 +551,7 @@ End Namespace
Dim aliases As Dictionary(Of String, AliasAndImportsClausePosition) = Nothing
Dim xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition) = Nothing
WithRuntimeInstancePortableBug(comp,
WithRuntimeInstance(comp,
Sub(runtime)
GetImports(
runtime,
......@@ -455,7 +567,11 @@ End Namespace
Assert.Equal("root.N", currentNamespace.ToTestDisplayString())
' CONSIDER: We could de-dup unaliased imports as well.
AssertEx.SetEqual(typesAndNamespaces.Select(Function(i) i.NamespaceOrType.ToTestDisplayString()), "System", "System.IO.Path", "System", "System.IO.Path", "root.N")
Dim expectedNamespaces = If(runtime.DebugFormat = DebugInformationFormat.PortablePdb,
{"System", "System.IO.Path", "System", "System.IO.Path"},
{"System", "System.IO.Path", "System", "System.IO.Path", "root.N"})
AssertEx.SetEqual(expectedNamespaces, typesAndNamespaces.Select(Function(i) i.NamespaceOrType.ToTestDisplayString()))
AssertEx.SetEqual(aliases.Keys, "A", "B")
Assert.Equal("System.Collections", aliases("A").Alias.Target.ToTestDisplayString())
......@@ -523,9 +639,7 @@ IL_000a: ret
<Out> ByRef aliases As Dictionary(Of String, AliasAndImportsClausePosition),
<Out> ByRef xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition))
Dim evalContext = CreateMethodContext(
runtime,
methodName:=methodName)
Dim evalContext = CreateMethodContext(runtime, methodName)
Dim compContext = evalContext.CreateCompilationContext(syntax)
GetImports(compContext, rootNamespace, currentNamespace, typesAndNamespaces, aliases, xmlNamespaces)
......
......@@ -602,7 +602,7 @@ Class P
End Class"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugExe)
WithRuntimeInstancePortableBug(comp,
WithRuntimeInstance(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, "C.M")
......@@ -1263,7 +1263,7 @@ Class C
End Class
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_2_F.MoveNext", atLineNumber:=999)
Dim testData As New CompilationTestData()
......@@ -1318,7 +1318,7 @@ Class C
End Class
"
Dim comp = CreateCompilationWithMscorlib({source}, options:=TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_1_F.MoveNext", atLineNumber:=999)
Dim testData As New CompilationTestData()
......@@ -1392,7 +1392,7 @@ End Structure
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="S.VB$StateMachine_2_F.MoveNext")
Dim testData As New CompilationTestData()
......@@ -1483,7 +1483,7 @@ End Class
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_2_M.MoveNext")
Dim testData As New CompilationTestData()
......@@ -1618,7 +1618,7 @@ End Class"
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C._Closure$__.VB$StateMachine___Lambda$__1-0.MoveNext")
Dim testData As New CompilationTestData()
......@@ -2485,7 +2485,7 @@ End Class"
MakeSources(source),
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_2_M.MoveNext", atLineNumber:=999)
Dim testData = New CompilationTestData()
......@@ -2544,7 +2544,7 @@ End Class"
MakeSources(source),
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_2_M.MoveNext", atLineNumber:=999)
Dim testData = New CompilationTestData()
......@@ -2701,7 +2701,7 @@ End Class
MakeSources(source),
{MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929},
TestOptions.DebugDll)
WithRuntimeInstance(comp,
WithRuntimeInstancePortableBug(comp,
Sub(runtime)
Dim context = CreateMethodContext(runtime, methodName:="C.VB$StateMachine_1_M.MoveNext", atLineNumber:=999)
Dim testData As New CompilationTestData()
......
......@@ -311,7 +311,7 @@ End Class"
options:=TestOptions.DebugDll,
references:={MscorlibRef, referenceA1})
WithRuntimeInstancePortableBug(compilationB, {MscorlibRef, SystemRef, MsvbRef, referenceA1, referenceA2},
WithRuntimeInstance(compilationB, {MscorlibRef, SystemRef, MsvbRef, referenceA1, referenceA2},
Sub(runtime)
Dim blocks As ImmutableArray(Of MetadataBlock) = Nothing
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册