public void TestMergedNamespaces() { NamespaceSymbol root1 = (NamespaceSymbol)CreateMockSymbol(new NamespaceExtent(new MockAssemblySymbol("Assem1")), XElement.Parse( @"<ns name=''> <ns name='A'> <ns name='D'/> <ns name='E'/> <ns name='F'> <ns name='G'/> </ns> </ns> <ns name='B'/> <ns name='C'/> <ns name='U'/> <class name='X'/> </ns>")); NamespaceSymbol root2 = (NamespaceSymbol)CreateMockSymbol(new NamespaceExtent(new MockAssemblySymbol("Assem2")), XElement.Parse( @"<ns name=''> <ns name='B'> <ns name='K'/> </ns> <ns name='C'/> <class name='X'/> <class name='Y'/> </ns>")); NamespaceSymbol root3 = (NamespaceSymbol)CreateMockSymbol(new NamespaceExtent(new MockAssemblySymbol("Assem3")), XElement.Parse( @"<ns name=''> <ns name='A'> <ns name='D'/> <ns name='E'> <ns name='H'/> </ns> </ns> <ns name='B'> <ns name='K'> <ns name='L'/> <class name='L'/> </ns> </ns> <class name='Z'/> </ns>")); NamespaceSymbol merged = MergedNamespaceSymbol.Create(new NamespaceExtent(new MockAssemblySymbol("Merged")), null, new NamespaceSymbol[] { root1, root2, root3 }.AsImmutable()); string expected = @"namespace [Assembly: Merged] { namespace A [Assembly: Merged] { namespace D [Assembly: Merged] namespace E [Assembly: Merged] { namespace H [Assembly: Assem3] } namespace F [Assembly: Assem1] { namespace G [Assembly: Assem1] } } namespace B [Assembly: Merged] { namespace K [Assembly: Merged] { class L namespace L [Assembly: Assem3] } } namespace C [Assembly: Merged] namespace U [Assembly: Assem1] class X class X class Y class Z }".Replace("Assembly: Merged", "Assembly: Merged, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null") .Replace("Assembly: Assem1", "Assembly: Assem1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null") .Replace("Assembly: Assem3", "Assembly: Assem3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); Assert.Equal(expected, DumpSymbol(merged)); NamespaceSymbol merged2 = MergedNamespaceSymbol.Create(new NamespaceExtent(new MockAssemblySymbol("Merged2")), null, new NamespaceSymbol[] { root1 }.AsImmutable()); Assert.Same(merged2, root1); }
public override void CheckMembers(Dictionary <string, ImmutableArray <Symbol> > result, DiagnosticBag diagnostics) { var memberOfMetadataName = new Dictionary <string, Symbol>(); MergedNamespaceSymbol mergedAssemblyNamespace = null; if (this.ContainingAssembly.Modules.Length > 1) { mergedAssemblyNamespace = this.ContainingAssembly.GetAssemblyNamespace(this) as MergedNamespaceSymbol; } foreach (var name in result.Keys) { memberOfMetadataName.Clear(); foreach (var symbol in result[name]) { var nts = symbol as NamedTypeSymbol; var metadataName = ((object)nts != null) ? nts.MetadataName : string.Empty; if (metadataName == null) { metadataName = string.Empty; } if (memberOfMetadataName.TryGetValue(metadataName, out Symbol other)) { if ((nts as SourceNamedTypeSymbol)?.IsPartial == true && (other as SourceNamedTypeSymbol)?.IsPartial == true) { diagnostics.Add(InternalErrorCode.ERR_PartialTypeKindConflict, symbol.Locations.FirstOrNone(), symbol); } else { diagnostics.Add(InternalErrorCode.ERR_DuplicateNameInNS, symbol.Locations.FirstOrNone(), name, this); } memberOfMetadataName[metadataName] = symbol; } else if ((object)mergedAssemblyNamespace != null) { // Check for collision with declarations from added modules. foreach (NamespaceSymbol constituent in mergedAssemblyNamespace.ConstituentNamespaces) { if ((object)constituent != (object)this) { // For whatever reason native compiler only detects conflicts against types. // It doesn't complain when source declares a type with the same name as // a namespace in added module, but complains when source declares a namespace // with the same name as a type in added module. var types = constituent.GetTypeMembers(symbol.Name, metadataName); if (types.Length > 0) { other = types[0]; // Since the error doesn't specify what added module this type belongs to, we can stop searching // at the first match. break; } } } memberOfMetadataName.Add(metadataName, symbol); } else { memberOfMetadataName.Add(metadataName, symbol); } } } }