提交 ef673369 编写于 作者: A acasey

Custom Debug Info: VB Imports

Three more kinds:
1) # - don't produce it, but silently discard it as in dev12.
2) $ - don't produce it, but silently discard it as in dev12.
3) & - produce it for each linked assembly, but silently discard it (not needed in roslyn).

CR: ChuckS, AnGocke (changeset 1368608)
上级 01c88bd5
......@@ -6,7 +6,7 @@
namespace Microsoft.Cci
{
/// <summary>
/// This is a list of the using directives (including aliases) in a lexial scope.
/// This is a list of the using directives (including aliases) in a lexical scope.
/// </summary>
/// <remarks>
/// This scope is tied to a particular method body, so that partial types can be accommodated.
......
......@@ -94,6 +94,12 @@ internal static UsedNamespaceOrType CreateVisualBasicDefaultNamespace(string nam
return new UsedNamespaceOrType(UsedNamespaceOrTypeKind.VBDefaultNamespace, name, null, externAlias: null, projectLevel: true);
}
internal static UsedNamespaceOrType CreateVisualBasicEmbeddedPia(string name)
{
Debug.Assert(name != null);
return new UsedNamespaceOrType(UsedNamespaceOrTypeKind.VBEmbeddedPia, name, null, externAlias: null);
}
private UsedNamespaceOrType(UsedNamespaceOrTypeKind kind, string name, string alias, string externAlias, bool projectLevel = false)
{
this.kind = kind;
......@@ -171,9 +177,12 @@ public string Encode()
return this.name;
case UsedNamespaceOrTypeKind.VBDefaultNamespace:
// VB marks the default/root namespace with an asteriks
// VB marks the default/root namespace with an asterisk
return "*" + this.name;
case UsedNamespaceOrTypeKind.VBEmbeddedPia:
return "&" + this.name;
default:
throw ExceptionUtilities.UnexpectedValue(this.kind);
}
......
......@@ -14,5 +14,6 @@ internal enum UsedNamespaceOrTypeKind
VBXmlNamespace, // e.g. Imports <xmlns:ns="http://NewNamespace"> (VB only)
VBCurrentNamespace, // the current namespace of the method's container
VBDefaultNamespace, // the default namespace of the project
VBEmbeddedPia, // indicates that a type has been embedded from a given PIA
}
}
......@@ -3,12 +3,7 @@
Imports System.Collections.Concurrent
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic
......@@ -19,6 +14,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' </summary>
Friend Class NamespaceScopeBuilder
' lazy embedded PIA imports
Private m_lazyEmbeddedPIAImports As Cci.NamespaceScope
' lazy project level imports
Private m_lazyProjectLevelImports As Cci.NamespaceScope
......@@ -52,6 +50,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim sourceModule = DirectCast(method.ContainingModule, SourceModuleSymbol)
If m_lazyEmbeddedPIAImports Is Nothing Then
Interlocked.CompareExchange(m_lazyEmbeddedPIAImports, BuildEmbeddedPiaImports(sourceModule), Nothing)
End If
If m_lazyProjectLevelImports Is Nothing Then
Interlocked.CompareExchange(m_lazyProjectLevelImports, BuildProjectLevelImports(sourceModule), Nothing)
End If
......@@ -61,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
' Dev11 outputs them in LIFO order, which we can't do this exactly the same way because we store parts of the
' needed information in tree's.
' needed information in trees.
' The order should be irrelevant because at the end it's a flat list, however we still output file level imports
' before project level imports the same way as Dev11 did.
......@@ -71,10 +73,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ImmutableArray.Create(sourceLevelImports,
m_lazyDefaultNamespaceImport,
m_lazyEmbeddedPIAImports,
m_lazyProjectLevelImports,
BuildCurrentNamespace(method))
End Function
''' <remarks>
''' Roslyn does not consume this information - it is only emitted for the benefit of legacy EEs.
''' See Builder::WriteNoPiaPdbList.
''' </remarks>
Private Function BuildEmbeddedPiaImports([module] As SourceModuleSymbol) As Cci.NamespaceScope
Dim embeddedPiasBuilder As ArrayBuilder(Of Cci.UsedNamespaceOrType) = Nothing
For Each referencedAssembly In [module].ReferencedAssemblySymbols
If referencedAssembly.IsLinked Then
If embeddedPiasBuilder Is Nothing Then
embeddedPiasBuilder = ArrayBuilder(Of Cci.UsedNamespaceOrType).GetInstance()
End If
' NOTE: Dev12 does not seem to emit anything but the name (i.e. no version, token, etc).
embeddedPiasBuilder.Add(Cci.UsedNamespaceOrType.CreateVisualBasicEmbeddedPia(referencedAssembly.Name))
End If
Next
Dim embeddedPias = If(embeddedPiasBuilder Is Nothing, ImmutableArray(Of Cci.UsedNamespaceOrType).Empty, embeddedPiasBuilder.ToImmutableAndFree())
Return New Cci.NamespaceScope(embeddedPias)
End Function
Private Function BuildProjectLevelImports([module] As SourceModuleSymbol) As Cci.NamespaceScope
Return BuildNamespaceScope([module].XmlNamespaces,
[module].AliasImports,
......
' Copyright (c) Microsoft Open Technologies, Inc. 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 PDBUsingTests
Inherits BasicTestBase
......@@ -288,5 +290,83 @@ End Class
AssertXmlEqual(expected, GetSequencePoints(GetPdbXml(source, TestOptions.DebugDll, "C1.Main")))
End Sub
<Fact>
Public Sub NoPia()
Dim piaSource = "
Imports System.Runtime.InteropServices
<assembly: PrimaryInteropAssembly(0, 0)>
<assembly: Guid(""863D5BC0-46A1-49AC-97AA-A5F0D441A9DA"")>
<ComImport>
<Guid(""863D5BC0-46A1-49AD-97AA-A5F0D441A9D9"")>
Public Interface I
Function F() As Object
End Interface
"
Dim piaComp = CreateCompilationWithMscorlib({piaSource}, compOptions:=TestOptions.DebugDll, assemblyName:="PIA")
AssertNoErrors(piaComp)
Dim piaRef = piaComp.EmitToImageReference(embedInteropTypes:=True)
Dim source = "
Namespace N1
Class C
Shared Sub M()
Dim o As I = Nothing
End Sub
End Class
End Namespace
Namespace N2
Class D
Shared Sub M()
End Sub
End Class
End Namespace
"
Dim comp = CreateCompilationWithMscorlib({source}, {piaRef}, TestOptions.DebugDll)
AssertNoErrors(comp)
Dim expected =
<symbols>
<methods>
<method containingType="N1.C" name="M" parameterNames="">
<customDebugInfo version="4" count="1">
<encLocalSlotMap version="4" kind="EditAndContinueLocalSlotMap" size="12">
<slot kind="0" offset="4"/>
</encLocalSlotMap>
</customDebugInfo>
<sequencepoints total="3">
<entry il_offset="0x0" start_row="4" start_column="9" end_row="4" end_column="23" file_ref="0"/>
<entry il_offset="0x1" start_row="5" start_column="17" end_row="5" end_column="33" file_ref="0"/>
<entry il_offset="0x3" start_row="6" start_column="9" end_row="6" end_column="16" file_ref="0"/>
</sequencepoints>
<locals>
<local name="o" il_index="0" il_start="0x0" il_end="0x4" attributes="0"/>
</locals>
<scope startOffset="0x0" endOffset="0x4">
<defunct name="&amp;PIA"/>
<currentnamespace name="N1"/>
<local name="o" il_index="0" il_start="0x0" il_end="0x4" attributes="0"/>
</scope>
</method>
<method containingType="N2.D" name="M" parameterNames="">
<sequencepoints total="2">
<entry il_offset="0x0" start_row="12" start_column="9" end_row="12" end_column="23" file_ref="0"/>
<entry il_offset="0x1" start_row="13" start_column="9" end_row="13" end_column="16" file_ref="0"/>
</sequencepoints>
<locals/>
<scope startOffset="0x0" endOffset="0x2">
<defunct name="&amp;PIA"/>
<currentnamespace name="N2"/>
</scope>
</method>
</methods>
</symbols>
Dim actual = GetPdbXml(comp)
AssertXmlEqual(expected, actual)
End Sub
End Class
End Namespace
......@@ -775,6 +775,13 @@ private void WriteNamespace(ISymUnmanagedNamespace @namespace)
writer.WriteEndElement(); // </externinfo>
}
break;
case ImportTargetKind.Defunct:
Debug.Assert(alias == null);
Debug.Assert(scope == ImportScope.Unspecified);
writer.WriteStartElement("defunct");
writer.WriteAttributeString("name", rawName);
writer.WriteEndElement(); // </defunct>
break;
default:
Debug.Assert(false, "Unexpected import kind '" + kind + "'");
writer.WriteStartElement("unknown");
......
......@@ -519,7 +519,8 @@ private static void CheckVersion(byte globalVersion, int methodToken)
/// </summary>
/// <remarks>
/// Doesn't consider forwarding.
/// TODO (acasey): VB doesn't just check the root scope - it digs around to find the best
///
/// CONSIDER: Dev12 doesn't just check the root scope - it digs around to find the best
/// match based on the IL offset and then walks up to the root scope (see PdbUtil::GetScopeFromOffset).
/// However, it's not clear that this matters, since imports can't be scoped in VB. This is probably
/// just based on the way they were extracting locals and constants based on a specific scope.
......@@ -706,12 +707,20 @@ public static bool TryParseVisualBasicImportString(string import, out string ali
return true;
}
// TODO (acasey): looks like we missed some cases (e.g. '$', '#', '&')
// See ProcedureContext::LoadImportsAndDefaultNamespaceNormal.
int pos = 0;
switch (import[pos])
{
case '&':
// Indicates the presence of embedded PIA types from a given assembly. No longer required (as of Roslyn).
case '$':
case '#':
// From ProcedureContext::LoadImportsAndDefaultNamespaceNormal:
// "Module Imports and extension types are no longer needed since we are not doing custom name lookup"
alias = null;
target = import;
kind = ImportTargetKind.Defunct;
scope = ImportScope.Unspecified;
return true;
case '*': // VB default namespace
// see PEBuilder.cpp in vb\language\CodeGen
pos++;
......@@ -890,6 +899,11 @@ internal enum ImportTargetKind
/// VB root namespace (not an import).
/// </summary>
DefaultNamespace,
/// <summary>
/// A kind that is no longer used.
/// </summary>
Defunct,
}
internal enum ImportScope
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册