提交 b8798c44 编写于 作者: C Charles Stoner

Order GlobalNamespace declarations to match Compilation.SyntaxTrees

上级 5d9b8222
......@@ -1867,6 +1867,14 @@ internal DeclarationTable Declarations
}
}
internal MergedNamespaceDeclaration MergedRootDeclaration
{
get
{
return Declarations.GetMergedRoot(this);
}
}
/// <summary>
/// Gets the diagnostics produced during the parsing stage of a compilation. There are no diagnostics for declarations or accessor or
/// method bodies, for example.
......@@ -2836,7 +2844,7 @@ public override bool ContainsSymbolsWithName(Func<string, bool> predicate, Symbo
throw new ArgumentException(CSharpResources.NoNoneSearchCriteria, nameof(filter));
}
return this.Declarations.ContainsName(predicate, filter, cancellationToken);
return DeclarationTable.ContainsName(this.MergedRootDeclaration, predicate, filter, cancellationToken);
}
/// <summary>
......@@ -2934,7 +2942,7 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
var result = new HashSet<ISymbol>();
var spine = new List<MergedNamespaceOrTypeDeclaration>();
AppendSymbolsWithName(spine, _compilation.Declarations.MergedRoot, predicate, filter, result, cancellationToken);
AppendSymbolsWithName(spine, _compilation.MergedRootDeclaration, predicate, filter, result, cancellationToken);
return result;
}
......
......@@ -2,7 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Threading;
using Roslyn.Utilities;
......@@ -32,7 +32,7 @@ internal sealed partial class DeclarationTable
private readonly Cache _cache;
// The lazily computed total merged declaration.
private readonly Lazy<MergedNamespaceDeclaration> _mergedRoot;
private MergedNamespaceDeclaration _mergedRoot;
private readonly Lazy<ICollection<string>> _typeNames;
private readonly Lazy<ICollection<string>> _namespaceNames;
......@@ -46,7 +46,6 @@ internal sealed partial class DeclarationTable
_allOlderRootDeclarations = allOlderRootDeclarations;
_latestLazyRootDeclaration = latestLazyRootDeclaration;
_cache = cache ?? new Cache(this);
_mergedRoot = new Lazy<MergedNamespaceDeclaration>(GetMergedRoot);
_typeNames = new Lazy<ICollection<string>>(GetMergedTypeNames);
_namespaceNames = new Lazy<ICollection<string>>(GetMergedNamespaceNames);
_referenceDirectives = new Lazy<ICollection<ReferenceDirective>>(GetMergedReferenceDirectives);
......@@ -88,18 +87,6 @@ public DeclarationTable RemoveRootDeclaration(Lazy<RootSingleNamespaceDeclaratio
}
}
public IEnumerable<RootSingleNamespaceDeclaration> AllRootNamespacesUnordered()
{
if (_latestLazyRootDeclaration == null)
{
return _allOlderRootDeclarations;
}
else
{
return _allOlderRootDeclarations.Concat(SpecializedCollections.SingletonEnumerable(_latestLazyRootDeclaration.Value));
}
}
// The merged-tree-reuse story goes like this. We have a "forest" of old declarations, and
// possibly a lone tree of new declarations. We construct a merged declaration by merging
// together everything in the forest. This we can re-use from edit to edit, provided that
......@@ -114,8 +101,18 @@ public IEnumerable<RootSingleNamespaceDeclaration> AllRootNamespacesUnordered()
// old merged root new merged root
// / | | | \ \
// old singles forest new single tree
public MergedNamespaceDeclaration GetMergedRoot(CSharpCompilation compilation)
{
Debug.Assert(compilation.Declarations == this);
if (_mergedRoot == null)
{
Interlocked.CompareExchange(ref _mergedRoot, CalculateMergedRoot(compilation), null);
}
return _mergedRoot;
}
private MergedNamespaceDeclaration GetMergedRoot()
// Internal for unit tests only.
internal MergedNamespaceDeclaration CalculateMergedRoot(CSharpCompilation compilation)
{
var oldRoot = _cache.MergedRoot.Value;
if (_latestLazyRootDeclaration == null)
......@@ -128,7 +125,31 @@ private MergedNamespaceDeclaration GetMergedRoot()
}
else
{
return MergedNamespaceDeclaration.Create(oldRoot, _latestLazyRootDeclaration.Value);
var oldRootDeclarations = oldRoot.Declarations;
var builder = ArrayBuilder<SingleNamespaceDeclaration>.GetInstance(oldRootDeclarations.Length + 1);
builder.AddRange(oldRootDeclarations);
builder.Add(_latestLazyRootDeclaration.Value);
// Sort the root namespace declarations to match the order of SyntaxTrees.
if (compilation != null)
{
builder.Sort(new RootNamespaceLocationComparer(compilation));
}
return MergedNamespaceDeclaration.Create(builder.ToImmutableAndFree());
}
}
private sealed class RootNamespaceLocationComparer : IComparer<SingleNamespaceDeclaration>
{
private readonly CSharpCompilation _compilation;
internal RootNamespaceLocationComparer(CSharpCompilation compilation)
{
_compilation = compilation;
}
public int Compare(SingleNamespaceDeclaration x, SingleNamespaceDeclaration y)
{
return _compilation.CompareSourceLocations(x.Location, y.Location);
}
}
......@@ -215,14 +236,6 @@ private static ISet<string> GetNames(Declaration declaration, Predicate<Declarat
return SpecializedCollections.ReadOnlySet(set);
}
public MergedNamespaceDeclaration MergedRoot
{
get
{
return _mergedRoot.Value;
}
}
public ICollection<string> TypeNames
{
get
......@@ -247,14 +260,18 @@ public IEnumerable<ReferenceDirective> ReferenceDirectives
}
}
public bool ContainsName(Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
public static bool ContainsName(
MergedNamespaceDeclaration mergedRoot,
Func<string, bool> predicate,
SymbolFilter filter,
CancellationToken cancellationToken)
{
var includeNamespace = (filter & SymbolFilter.Namespace) == SymbolFilter.Namespace;
var includeType = (filter & SymbolFilter.Type) == SymbolFilter.Type;
var includeMember = (filter & SymbolFilter.Member) == SymbolFilter.Member;
var stack = new Stack<MergedNamespaceOrTypeDeclaration>();
stack.Push(this.MergedRoot);
stack.Push(mergedRoot);
while (stack.Count > 0)
{
......
......@@ -221,9 +221,9 @@ public override SingleNamespaceOrTypeDeclaration VisitNamespaceDeclaration(Names
bool hasExterns = node.Externs.Any();
NameSyntax name = node.Name;
CSharpSyntaxNode currentNode = node;
while (name is QualifiedNameSyntax)
QualifiedNameSyntax dotted;
while ((dotted = name as QualifiedNameSyntax) != null)
{
var dotted = name as QualifiedNameSyntax;
var ns = SingleNamespaceDeclaration.Create(
name: dotted.Right.Identifier.ValueText,
hasUsings: hasUsings,
......
......@@ -29,13 +29,6 @@ public static MergedNamespaceDeclaration Create(SingleNamespaceDeclaration decla
return new MergedNamespaceDeclaration(ImmutableArray.Create(declaration));
}
public static MergedNamespaceDeclaration Create(
MergedNamespaceDeclaration mergedDeclaration,
SingleNamespaceDeclaration declaration)
{
return new MergedNamespaceDeclaration(mergedDeclaration._declarations.Add(declaration));
}
public override DeclarationKind Kind
{
get
......
......@@ -1443,13 +1443,18 @@ internal CommonAssemblyWellKnownAttributeData GetNetModuleDecodedWellKnownAttrib
internal ImmutableArray<SyntaxList<AttributeListSyntax>> GetAttributeDeclarations()
{
var attrList =
from rootNs in DeclaringCompilation.Declarations.AllRootNamespacesUnordered()
where rootNs.HasAssemblyAttributes
select rootNs.Location.SourceTree into tree
orderby _compilation.GetSyntaxTreeOrdinal(tree)
select ((CompilationUnitSyntax)tree.GetRoot()).AttributeLists;
return attrList.ToImmutableArray();
var builder = ArrayBuilder<SyntaxList<AttributeListSyntax>>.GetInstance();
var declarations = DeclaringCompilation.MergedRootDeclaration.Declarations;
foreach (RootSingleNamespaceDeclaration rootNs in declarations)
{
if (rootNs.HasAssemblyAttributes)
{
var tree = rootNs.Location.SourceTree;
var root = (CompilationUnitSyntax)tree.GetRoot();
builder.Add(root.AttributeLists);
}
}
return builder.ToImmutableAndFree();
}
private void EnsureAttributesAreBound()
......
......@@ -186,18 +186,14 @@ public override NamespaceSymbol GlobalNamespace
{
if ((object)_globalNamespace == null)
{
Interlocked.CompareExchange(ref _globalNamespace, MakeGlobalNamespace(), null);
var globalNS = new SourceNamespaceSymbol(this, this, DeclaringCompilation.MergedRootDeclaration);
Interlocked.CompareExchange(ref _globalNamespace, globalNS, null);
}
return _globalNamespace;
}
}
private SourceNamespaceSymbol MakeGlobalNamespace()
{
return new SourceNamespaceSymbol(this, this, _sources.MergedRoot);
}
internal sealed override bool RequiresCompletion
{
get { return true; }
......@@ -347,9 +343,9 @@ public override ImmutableArray<Location> Locations
{
if (_locations.IsDefault)
{
ImmutableInterlocked.InterlockedCompareExchange(ref _locations,
_sources.AllRootNamespacesUnordered().Select(n => n.Location).AsImmutable<Location>(),
default(ImmutableArray<Location>));
ImmutableInterlocked.InterlockedInitialize(
ref _locations,
DeclaringCompilation.MergedRootDeclaration.Declarations.SelectAsArray(d => (Location)d.Location));
}
return _locations;
......
......@@ -116,19 +116,17 @@ partial class D
Assert.Equal(0, d2.Children.Length);
var table = DeclarationTable.Empty;
Assert.Empty(table.AllRootNamespacesUnordered());
var mr = table.MergedRoot;
var mr = table.CalculateMergedRoot(null);
Assert.NotNull(mr);
Assert.True(mr.Declarations.IsEmpty);
Assert.True(table.TypeNames.IsEmpty());
table = table.AddRootDeclaration(Lazy(decl1));
mr = table.CalculateMergedRoot(null);
Assert.Equal(decl1, table.AllRootNamespacesUnordered().Single());
Assert.Equal(mr.Declarations, new[] { decl1 });
Assert.True(table.TypeNames.OrderBy(s => s).SequenceEqual(new[] { "C", "D" }));
mr = table.MergedRoot;
Assert.Equal(DeclarationKind.Namespace, mr.Kind);
Assert.Equal(string.Empty, mr.Name);
......@@ -156,12 +154,11 @@ partial class D
Assert.Equal("D", d.Name);
table = table.AddRootDeclaration(Lazy(decl2));
mr = table.CalculateMergedRoot(null);
Assert.True(table.TypeNames.Distinct().OrderBy(s => s).SequenceEqual(new[] { "C", "D" }));
Assert.Equal(2, table.AllRootNamespacesUnordered().Intersect(new[] { decl1, decl2 }).Count());
mr = table.MergedRoot;
Assert.Equal(mr.Declarations, new[] { decl1, decl2 });
Assert.Equal(DeclarationKind.Namespace, mr.Kind);
Assert.Equal(string.Empty, mr.Name);
......
......@@ -718,5 +718,47 @@ void f()
CheckLambdaDeclaringSyntax<SimpleLambdaExpressionSyntax>(comp, tree, "/*2*/");
CheckLambdaDeclaringSyntax<AnonymousMethodExpressionSyntax>(comp, tree, "/*3*/");
}
/// <summary>
/// Symbol location order should be preserved when trees
/// are replaced in the compilation.
/// </summary>
[WorkItem(11015, "https://github.com/dotnet/roslyn/issues/11015")]
[Fact]
public void PreserveLocationOrderOnReplaceSyntaxTree()
{
var source0 = Parse("namespace N { partial class C { } } namespace N0 { } class C0 { }");
var source1 = Parse("namespace N { partial class C { } } namespace N1 { } class C1 { }");
var source2 = Parse("namespace N { struct S { } }");
var source3 = Parse("namespace N { partial class C { } } namespace N3 { } class C3 { }");
var comp0 = CreateCompilationWithMscorlib(new[] { source0, source1, source2, source3 });
comp0.VerifyDiagnostics();
Assert.Equal(new[] { source0, source1, source2, source3 }, comp0.SyntaxTrees);
// Location order of partial class should match SyntaxTrees order.
var locations = comp0.GetMember<NamedTypeSymbol>("N.C").Locations;
Assert.Equal(new[] { source0, source1, source3 }, locations.Select(l => l.SourceTree));
// AddSyntaxTrees will add to the end.
var source4 = Parse("namespace N { partial class C { } } namespace N4 { } class C4 { }");
var comp1 = comp0.AddSyntaxTrees(source4);
locations = comp1.GetMember<NamedTypeSymbol>("N.C").Locations;
Assert.Equal(new[] { source0, source1, source3, source4 }, locations.Select(l => l.SourceTree));
// ReplaceSyntaxTree should preserve location order.
var comp2 = comp0.ReplaceSyntaxTree(source1, source4);
locations = comp2.GetMember<NamedTypeSymbol>("N.C").Locations;
Assert.Equal(new[] { source0, source4, source3 }, locations.Select(l => l.SourceTree));
// NamespaceNames and TypeNames do not match SyntaxTrees order.
// This is expected.
Assert.Equal(new[] { "", "N3", "N0", "N", "", "N4", "N" }, comp2.Declarations.NamespaceNames.ToArray());
Assert.Equal(new[] { "C3", "C0", "S", "C", "C4", "C" }, comp2.Declarations.TypeNames.ToArray());
// RemoveSyntaxTrees should preserve order of remaining trees.
var comp3 = comp2.RemoveSyntaxTrees(source0);
locations = comp3.GetMember<NamedTypeSymbol>("N.C").Locations;
Assert.Equal(new[] { source4, source3 }, locations.Select(l => l.SourceTree));
}
}
}
......@@ -192,6 +192,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
Friend ReadOnly Property MergedRootDeclaration As MergedNamespaceDeclaration
Get
Return Declarations.GetMergedRoot(Me)
End Get
End Property
Public Shadows ReadOnly Property Options As VisualBasicCompilationOptions
Get
Return _options
......@@ -2631,7 +2637,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw New ArgumentException(VBResources.NoNoneSearchCriteria, NameOf(filter))
End If
Return Me.Declarations.ContainsName(predicate, filter, cancellationToken)
Return DeclarationTable.ContainsName(MergedRootDeclaration, predicate, filter, cancellationToken)
End Function
''' <summary>
......@@ -2673,7 +2679,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim result = New HashSet(Of ISymbol)()
Dim spine = New List(Of MergedNamespaceOrTypeDeclaration)()
AppendSymbolsWithName(spine, Me._compilation.Declarations.MergedRoot, predicate, filter, result, cancellationToken)
AppendSymbolsWithName(spine, _compilation.MergedRootDeclaration, predicate, filter, result, cancellationToken)
Return result
End Function
......
......@@ -44,7 +44,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Private ReadOnly _cache As Cache
' The lazily computed total merged declaration.
Private ReadOnly _mergedRoot As Lazy(Of MergedNamespaceDeclaration)
Private _mergedRoot As MergedNamespaceDeclaration
Private ReadOnly _typeNames As Lazy(Of ICollection(Of String))
Private ReadOnly _namespaceNames As Lazy(Of ICollection(Of String))
......@@ -58,7 +58,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Me._allOlderRootDeclarations = allOlderRootDeclarations
Me._latestLazyRootDeclaration = latestLazyRootDeclaration
Me._cache = If(cache, New Cache(Me))
Me._mergedRoot = New Lazy(Of MergedNamespaceDeclaration)(AddressOf GetMergedRoot)
Me._typeNames = New Lazy(Of ICollection(Of String))(AddressOf GetMergedTypeNames)
Me._namespaceNames = New Lazy(Of ICollection(Of String))(AddressOf GetMergedNamespaceNames)
Me._referenceDirectives = New Lazy(Of ICollection(Of ReferenceDirective))(AddressOf GetMergedReferenceDirectives)
......@@ -140,7 +139,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' old merged root new merged root
' / | | | \ \
' old singles forest new single tree
Private Function GetMergedRoot() As MergedNamespaceDeclaration
Public Function GetMergedRoot(compilation As VisualBasicCompilation) As MergedNamespaceDeclaration
Debug.Assert(compilation.Declarations Is Me)
If _mergedRoot Is Nothing Then
Interlocked.CompareExchange(_mergedRoot, CalculateMergedRoot(compilation), Nothing)
End If
Return _mergedRoot
End Function
' Internal for unit tests only.
Friend Function CalculateMergedRoot(compilation As VisualBasicCompilation) As MergedNamespaceDeclaration
Dim oldRoot = Me._cache.MergedRoot.Value
Dim latestRoot = GetLatestRootDeclarationIfAny(includeEmbedded:=True)
If latestRoot Is Nothing Then
......@@ -148,10 +156,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
ElseIf oldRoot Is Nothing Then
Return MergedNamespaceDeclaration.Create(latestRoot)
Else
Return MergedNamespaceDeclaration.Create(oldRoot, latestRoot)
Dim oldRootDeclarations = oldRoot.Declarations
Dim builder = ArrayBuilder(Of SingleNamespaceDeclaration).GetInstance(oldRootDeclarations.Length + 1)
builder.AddRange(oldRootDeclarations)
builder.Add(_latestLazyRootDeclaration.Root.Value)
' Sort the root namespace declarations to match the order of SyntaxTrees.
If compilation IsNot Nothing Then
builder.Sort(New RootNamespaceLocationComparer(compilation))
End If
Return MergedNamespaceDeclaration.Create(builder.ToImmutableAndFree())
End If
End Function
Private NotInheritable Class RootNamespaceLocationComparer
Implements IComparer(Of SingleNamespaceDeclaration)
Private ReadOnly _compilation As VisualBasicCompilation
Friend Sub New(compilation As VisualBasicCompilation)
_compilation = compilation
End Sub
Public Function Compare(x As SingleNamespaceDeclaration, y As SingleNamespaceDeclaration) As Integer Implements IComparer(Of SingleNamespaceDeclaration).Compare
Return _compilation.CompareSourceLocations(x.Location, y.Location)
End Function
End Class
Private Function GetMergedTypeNames() As ICollection(Of String)
Dim cachedTypeNames = Me._cache.TypeNames.Value
Dim latestRoot = GetLatestRootDeclarationIfAny(includeEmbedded:=True)
......@@ -222,12 +252,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return result.AsCaseInsensitiveCollection()
End Function
Public ReadOnly Property MergedRoot As MergedNamespaceDeclaration
Get
Return _mergedRoot.Value
End Get
End Property
Public ReadOnly Property TypeNames As ICollection(Of String)
Get
Return _typeNames.Value
......@@ -246,14 +270,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
Public Function ContainsName(predicate As Func(Of String, Boolean), filter As SymbolFilter, cancellationToken As CancellationToken) As Boolean
Public Shared Function ContainsName(
mergedRoot As MergedNamespaceDeclaration,
predicate As Func(Of String, Boolean),
filter As SymbolFilter,
cancellationToken As CancellationToken) As Boolean
Dim includeNamespace = (filter And SymbolFilter.Namespace) = SymbolFilter.Namespace
Dim includeType = (filter And SymbolFilter.Type) = SymbolFilter.Type
Dim includeMember = (filter And SymbolFilter.Member) = SymbolFilter.Member
Dim stack = New Stack(Of MergedNamespaceOrTypeDeclaration)()
stack.Push(Me.MergedRoot)
stack.Push(mergedRoot)
While stack.Count > 0
cancellationToken.ThrowIfCancellationRequested()
......
......@@ -29,11 +29,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return New MergedNamespaceDeclaration(declarations.AsImmutableOrNull)
End Function
Public Shared Function Create(mergedDeclaration As MergedNamespaceDeclaration,
declaration As SingleNamespaceDeclaration) As MergedNamespaceDeclaration
Return New MergedNamespaceDeclaration(mergedDeclaration._declarations.Add(declaration))
End Function
Public Overrides ReadOnly Property Kind As DeclarationKind
Get
Return DeclarationKind.Namespace
......
......@@ -5,11 +5,6 @@ Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports System.Diagnostics
Imports System.Linq
Imports System.Text
Imports System.Threading
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
......
......@@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Else
Debug.Assert(location.PossiblyEmbeddedOrMySourceSpan.Start >= 0)
Dim tree = DirectCast(location.SourceTree, VisualBasicSyntaxTree)
Dim tree = DirectCast(location.PossiblyEmbeddedOrMySourceTree, VisualBasicSyntaxTree)
Debug.Assert(tree Is Nothing OrElse tree.GetEmbeddedKind = location.EmbeddedKind)
Dim treeKind As SyntaxTreeKind = GetEmbeddedKind(tree)
......
......@@ -461,8 +461,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend Function GetAttributeDeclarations() As ImmutableArray(Of SyntaxList(Of AttributeListSyntax))
Dim attributeBlocks = ArrayBuilder(Of SyntaxList(Of AttributeListSyntax)).GetInstance()
Dim declarations = DeclaringCompilation.MergedRootDeclaration.Declarations
For Each rootNs In DeclaringCompilation.Declarations.AllRootNamespaces
For Each rootNs As RootSingleNamespaceDeclaration In declarations
If rootNs.HasAssemblyAttributes Then
Dim compilationUnitSyntax = DirectCast(rootNs.Location.SourceTree.GetRoot(), CompilationUnitSyntax)
Dim attributeStatements = compilationUnitSyntax.Attributes
......
......@@ -102,9 +102,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Get
Select Case DeclaringCompilation.Options.Platform
Case Platform.Arm
Return System.Reflection.PortableExecutable.Machine.ARMThumb2
Return System.Reflection.PortableExecutable.Machine.ArmThumb2
Case Platform.X64
Return System.Reflection.PortableExecutable.Machine.AMD64
Return System.Reflection.PortableExecutable.Machine.Amd64
Case Platform.Itanium
Return System.Reflection.PortableExecutable.Machine.IA64
Case Else
......@@ -172,7 +172,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides ReadOnly Property GlobalNamespace As NamespaceSymbol
Get
If _lazyGlobalNamespace Is Nothing Then
Dim globalNS = New SourceNamespaceSymbol(_declarationTable.MergedRoot, Nothing, Me)
Dim globalNS = New SourceNamespaceSymbol(DeclaringCompilation.MergedRootDeclaration, Nothing, Me)
Interlocked.CompareExchange(_lazyGlobalNamespace, globalNS, Nothing)
End If
......@@ -193,9 +193,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
Get
If _locations.IsDefault Then
Dim locs = _declarationTable.AllRootNamespaces().SelectAsArray(Function(n) n.Location)
ImmutableInterlocked.InterlockedCompareExchange(_locations, locs, Nothing)
ImmutableInterlocked.InterlockedInitialize(
_locations,
DeclaringCompilation.MergedRootDeclaration.Declarations.SelectAsArray(Function(d) d.Location))
End If
Return _locations
......
......@@ -195,16 +195,6 @@ End Class
compilation.VerifyPdb(
<symbols>
<methods>
<method containingType="C1" name="Method">
<sequencePoints>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="17"/>
<entry offset="0x1" startLine="3" startColumn="9" endLine="3" endColumn="50"/>
<entry offset="0xc" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0xd">
<currentnamespace name=""/>
</scope>
</method>
<method containingType="My.MyComputer" name=".ctor">
<sequencePoints>
<entry offset="0x0" startLine="107" startColumn="9" endLine="107" endColumn="25"/>
......@@ -215,6 +205,17 @@ End Class
<currentnamespace name="My"/>
</scope>
</method>
<method containingType="My.MyProject" name=".cctor">
<sequencePoints>
<entry offset="0x0" startLine="126" startColumn="26" endLine="126" endColumn="97"/>
<entry offset="0xa" startLine="137" startColumn="26" endLine="137" endColumn="95"/>
<entry offset="0x14" startLine="148" startColumn="26" endLine="148" endColumn="136"/>
<entry offset="0x1e" startLine="284" startColumn="26" endLine="284" endColumn="105"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x29">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
</scope>
</method>
<method containingType="My.MyProject" name="get_Computer">
<customDebugInfo>
<encLocalSlotMap>
......@@ -279,15 +280,14 @@ End Class
<local name="WebServices" il_index="0" il_start="0x0" il_end="0x10" attributes="0"/>
</scope>
</method>
<method containingType="My.MyProject" name=".cctor">
<method containingType="C1" name="Method">
<sequencePoints>
<entry offset="0x0" startLine="126" startColumn="26" endLine="126" endColumn="97"/>
<entry offset="0xa" startLine="137" startColumn="26" endLine="137" endColumn="95"/>
<entry offset="0x14" startLine="148" startColumn="26" endLine="148" endColumn="136"/>
<entry offset="0x1e" startLine="284" startColumn="26" endLine="284" endColumn="105"/>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="17"/>
<entry offset="0x1" startLine="3" startColumn="9" endLine="3" endColumn="50"/>
<entry offset="0xc" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x29">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<scope startOffset="0x0" endOffset="0xd">
<currentnamespace name=""/>
</scope>
</method>
<method containingType="My.MyProject+MyWebServices" name="Equals" parameterNames="o">
......@@ -302,7 +302,7 @@ End Class
<entry offset="0x10" startLine="249" startColumn="13" endLine="249" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x12">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<currentnamespace name="My"/>
<local name="Equals" il_index="0" il_start="0x0" il_end="0x12" attributes="0"/>
</scope>
</method>
......@@ -318,7 +318,7 @@ End Class
<entry offset="0xa" startLine="253" startColumn="13" endLine="253" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0xc">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetHashCode" il_index="0" il_start="0x0" il_end="0xc" attributes="0"/>
</scope>
</method>
......@@ -334,7 +334,7 @@ End Class
<entry offset="0xe" startLine="257" startColumn="13" endLine="257" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x10">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetType" il_index="0" il_start="0x0" il_end="0x10" attributes="0"/>
</scope>
</method>
......@@ -350,7 +350,7 @@ End Class
<entry offset="0xa" startLine="261" startColumn="13" endLine="261" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0xc">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="ToString" il_index="0" il_start="0x0" il_end="0xc" attributes="0"/>
</scope>
</method>
......@@ -371,7 +371,7 @@ End Class
<entry offset="0x1b" startLine="270" startColumn="13" endLine="270" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x1d">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="Create__Instance__" il_index="0" il_start="0x0" il_end="0x1d" attributes="0"/>
</scope>
</method>
......@@ -382,7 +382,7 @@ End Class
<entry offset="0x8" startLine="275" startColumn="13" endLine="275" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
<method containingType="My.MyProject+MyWebServices" name=".ctor">
......@@ -392,7 +392,7 @@ End Class
<entry offset="0x8" startLine="281" startColumn="13" endLine="281" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
<method containingType="My.MyProject+ThreadSafeObjectProvider`1" name="get_GetInstance">
......@@ -411,7 +411,7 @@ End Class
<entry offset="0x24" startLine="344" startColumn="17" endLine="344" endColumn="24"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x26">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetInstance" il_index="0" il_start="0x0" il_end="0x26" attributes="0"/>
</scope>
</method>
......@@ -422,7 +422,7 @@ End Class
<entry offset="0x8" startLine="352" startColumn="13" endLine="352" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
</methods>
......@@ -3871,26 +3871,6 @@ End Class
compilation.VerifyPdb(
<symbols>
<methods>
<method containingType="IntervalUpdate" name="Update">
<sequencePoints>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="31"/>
<entry offset="0x1" startLine="3" startColumn="9" endLine="3" endColumn="37"/>
<entry offset="0x11" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x12">
<currentnamespace name=""/>
</scope>
</method>
<method containingType="IntervalUpdate" name="Main">
<sequencePoints>
<entry offset="0x0" startLine="6" startColumn="5" endLine="6" endColumn="22"/>
<entry offset="0x1" startLine="7" startColumn="9" endLine="7" endColumn="17"/>
<entry offset="0x7" startLine="8" startColumn="5" endLine="8" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x8">
<importsforward declaringType="IntervalUpdate" methodName="Update"/>
</scope>
</method>
<method containingType="My.MyComputer" name=".ctor">
<sequencePoints>
<entry offset="0x0" startLine="107" startColumn="9" endLine="107" endColumn="25"/>
......@@ -3901,6 +3881,17 @@ End Class
<currentnamespace name="My"/>
</scope>
</method>
<method containingType="My.MyProject" name=".cctor">
<sequencePoints>
<entry offset="0x0" startLine="126" startColumn="26" endLine="126" endColumn="97"/>
<entry offset="0xa" startLine="137" startColumn="26" endLine="137" endColumn="95"/>
<entry offset="0x14" startLine="148" startColumn="26" endLine="148" endColumn="136"/>
<entry offset="0x1e" startLine="284" startColumn="26" endLine="284" endColumn="105"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x29">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
</scope>
</method>
<method containingType="My.MyProject" name="get_Computer">
<customDebugInfo>
<encLocalSlotMap>
......@@ -3965,15 +3956,24 @@ End Class
<local name="WebServices" il_index="0" il_start="0x0" il_end="0x10" attributes="0"/>
</scope>
</method>
<method containingType="My.MyProject" name=".cctor">
<method containingType="IntervalUpdate" name="Update">
<sequencePoints>
<entry offset="0x0" startLine="126" startColumn="26" endLine="126" endColumn="97"/>
<entry offset="0xa" startLine="137" startColumn="26" endLine="137" endColumn="95"/>
<entry offset="0x14" startLine="148" startColumn="26" endLine="148" endColumn="136"/>
<entry offset="0x1e" startLine="284" startColumn="26" endLine="284" endColumn="105"/>
<entry offset="0x0" startLine="2" startColumn="5" endLine="2" endColumn="31"/>
<entry offset="0x1" startLine="3" startColumn="9" endLine="3" endColumn="37"/>
<entry offset="0x11" startLine="4" startColumn="5" endLine="4" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x29">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<scope startOffset="0x0" endOffset="0x12">
<currentnamespace name=""/>
</scope>
</method>
<method containingType="IntervalUpdate" name="Main">
<sequencePoints>
<entry offset="0x0" startLine="6" startColumn="5" endLine="6" endColumn="22"/>
<entry offset="0x1" startLine="7" startColumn="9" endLine="7" endColumn="17"/>
<entry offset="0x7" startLine="8" startColumn="5" endLine="8" endColumn="12"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x8">
<importsforward declaringType="IntervalUpdate" methodName="Update"/>
</scope>
</method>
<method containingType="My.MyProject+MyWebServices" name="Equals" parameterNames="o">
......@@ -3988,7 +3988,7 @@ End Class
<entry offset="0x10" startLine="249" startColumn="13" endLine="249" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x12">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<currentnamespace name="My"/>
<local name="Equals" il_index="0" il_start="0x0" il_end="0x12" attributes="0"/>
</scope>
</method>
......@@ -4004,7 +4004,7 @@ End Class
<entry offset="0xa" startLine="253" startColumn="13" endLine="253" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0xc">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetHashCode" il_index="0" il_start="0x0" il_end="0xc" attributes="0"/>
</scope>
</method>
......@@ -4020,7 +4020,7 @@ End Class
<entry offset="0xe" startLine="257" startColumn="13" endLine="257" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x10">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetType" il_index="0" il_start="0x0" il_end="0x10" attributes="0"/>
</scope>
</method>
......@@ -4036,7 +4036,7 @@ End Class
<entry offset="0xa" startLine="261" startColumn="13" endLine="261" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0xc">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="ToString" il_index="0" il_start="0x0" il_end="0xc" attributes="0"/>
</scope>
</method>
......@@ -4057,7 +4057,7 @@ End Class
<entry offset="0x1b" startLine="270" startColumn="13" endLine="270" endColumn="25"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x1d">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="Create__Instance__" il_index="0" il_start="0x0" il_end="0x1d" attributes="0"/>
</scope>
</method>
......@@ -4068,7 +4068,7 @@ End Class
<entry offset="0x8" startLine="275" startColumn="13" endLine="275" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
<method containingType="My.MyProject+MyWebServices" name=".ctor">
......@@ -4078,7 +4078,7 @@ End Class
<entry offset="0x8" startLine="281" startColumn="13" endLine="281" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
<method containingType="My.MyProject+ThreadSafeObjectProvider`1" name="get_GetInstance">
......@@ -4097,7 +4097,7 @@ End Class
<entry offset="0x24" startLine="344" startColumn="17" endLine="344" endColumn="24"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x26">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
<local name="GetInstance" il_index="0" il_start="0x0" il_end="0x26" attributes="0"/>
</scope>
</method>
......@@ -4108,7 +4108,7 @@ End Class
<entry offset="0x8" startLine="352" startColumn="13" endLine="352" endColumn="20"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x9">
<importsforward declaringType="My.MyComputer" methodName=".ctor"/>
<importsforward declaringType="My.MyProject+MyWebServices" methodName="Equals" parameterNames="o"/>
</scope>
</method>
</methods>
......
......@@ -606,5 +606,85 @@ BC31060: event 'E' implicitly defines 'add_E', which conflicts with a member of
Assert.Equal("Add_E", members(3).MetadataName)
End Sub
''' <summary>
''' Symbol location order should be preserved when trees
''' are replaced in the compilation.
''' </summary>
<WorkItem(11015, "https://github.com/dotnet/roslyn/issues/11015")>
<Fact>
Public Sub PreserveLocationOrderOnReplaceSyntaxTree()
Dim source0 = Parse(
"Namespace N
Partial Class C
End Class
End Namespace
Namespace N0
Class C0
End Class
End Namespace")
Dim source1 = Parse(
"Namespace N
Partial Class C
End Class
End Namespace
Namespace N1
Class C1
End Class
End Namespace")
Dim source2 = Parse(
"Namespace N
Structure S
End Structure
End Namespace")
Dim source3 = Parse(
"Namespace N
Partial Class C
End Class
End Namespace
Namespace N3
Class C3
End Class
End Namespace")
Dim comp0 = CompilationUtils.CreateCompilationWithMscorlib({source0, source1, source2, source3}, options:=TestOptions.ReleaseDll)
comp0.AssertTheseDiagnostics()
Assert.Equal({source0, source1, source2, source3}, comp0.SyntaxTrees)
Dim locations = comp0.GlobalNamespace.Locations
Assert.Equal({"MyTemplateLocation", "SourceLocation", "SourceLocation", "SourceLocation", "SourceLocation", "MetadataLocation"}, locations.Select(Function(l) l.GetType().Name))
' Location order of partial class should match SyntaxTrees order.
locations = comp0.GetMember(Of NamedTypeSymbol)("N.C").Locations
Assert.Equal({source0, source1, source3}, locations.Select(Function(l) l.SourceTree))
' AddSyntaxTrees will add to the end.
Dim source4 = Parse(
"Namespace N
Partial Class C
End Class
End Namespace
Namespace N4
Class C4
End Class
End Namespace")
Dim comp1 = comp0.AddSyntaxTrees(source4)
locations = comp1.GetMember(Of NamedTypeSymbol)("N.C").Locations
Assert.Equal({source0, source1, source3, source4}, locations.Select(Function(l) l.SourceTree))
' ReplaceSyntaxTree should preserve location order.
Dim comp2 = comp0.ReplaceSyntaxTree(source1, source4)
locations = comp2.GetMember(Of NamedTypeSymbol)("N.C").Locations
Assert.Equal({source0, source4, source3}, locations.Select(Function(l) l.SourceTree))
' NamespaceNames and TypeNames do not match SyntaxTrees order.
' This is expected.
Assert.Equal({"", "N3", "N0", "N", "", "N4", "N"}, comp2.Declarations.NamespaceNames.ToArray())
Assert.Equal({"C3", "C0", "S", "C", "C4", "C"}, comp2.Declarations.TypeNames.ToArray())
' RemoveSyntaxTrees should preserve order of remaining trees.
Dim comp3 = comp2.RemoveSyntaxTrees(source0)
locations = comp3.GetMember(Of NamedTypeSymbol)("N.C").Locations
Assert.Equal({source4, source3}, locations.Select(Function(l) l.SourceTree))
End Sub
End Class
End Namespace
......@@ -106,14 +106,15 @@ end namespace
Dim table As DeclarationTable = DeclarationTable.Empty
Assert.False(table.AllRootNamespaces().Any)
Dim mr = table.MergedRoot
Dim mr = table.CalculateMergedRoot(Nothing)
Assert.NotNull(mr)
Assert.True(mr.Declarations.IsEmpty)
Assert.True(table.TypeNames.IsEmpty())
table = table.AddRootDeclaration(Lazy(decl1))
mr = table.CalculateMergedRoot(Nothing)
Assert.Same(decl1, table.AllRootNamespaces().Single())
mr = table.MergedRoot
Assert.Equal(mr.Declarations, {decl1})
Assert.Equal(DeclarationKind.Namespace, mr.Kind)
Assert.Equal("", mr.Name)
......@@ -142,11 +143,9 @@ end namespace
Assert.Equal("D", d.Name)
table = table.AddRootDeclaration(Lazy(decl2))
Assert.Equal(2, table.AllRootNamespaces().Length)
Assert.True(table.AllRootNamespaces().Contains(decl1))
Assert.True(table.AllRootNamespaces().Contains(decl2))
mr = table.CalculateMergedRoot(Nothing)
mr = table.MergedRoot
Assert.Equal(mr.Declarations, {decl1, decl2})
Assert.Equal(DeclarationKind.Namespace, mr.Kind)
Assert.Equal("", mr.Name)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册