/// <summary> /// Visits the <see cref="NamespaceMapper"/> and visits each <see cref="TypeMapper"/> in the mapper. /// </summary> /// <param name="mapper">The <see cref="NamespaceMapper"/> to visit.</param> public virtual void Visit(NamespaceMapper mapper) { if (mapper == null) { throw new ArgumentNullException(nameof(mapper)); } foreach (TypeMapper type in mapper.GetTypes()) { Visit(type); } }
public IEnumerable <NamespaceMapper> GetNamespaces() { if (_namespaces == null) { _namespaces = new Dictionary <INamespaceSymbol, NamespaceMapper>(Settings.EqualityComparer); Dictionary <INamespaceSymbol, List <INamedTypeSymbol> > typeForwards; if (Left != null) { typeForwards = ResolveTypeForwards(Left, Settings.EqualityComparer); AddOrCreateMappers(Left.GlobalNamespace, 0); } if (Right != null) { typeForwards = ResolveTypeForwards(Right, Settings.EqualityComparer); AddOrCreateMappers(Right.GlobalNamespace, 1); } void AddOrCreateMappers(INamespaceSymbol ns, int index) { Stack <INamespaceSymbol> stack = new(); stack.Push(ns); while (stack.Count > 0) { INamespaceSymbol symbol = stack.Pop(); if (typeForwards.TryGetValue(symbol, out List <INamedTypeSymbol> forwardedTypes) || symbol.GetTypeMembers().Length > 0) { if (!_namespaces.TryGetValue(symbol, out NamespaceMapper mapper)) { mapper = new NamespaceMapper(Settings); _namespaces.Add(symbol, mapper); } mapper.AddElement(symbol, index); mapper.AddForwardedTypes(forwardedTypes ?? new List <INamedTypeSymbol>(), index); } foreach (INamespaceSymbol child in symbol.GetNamespaceMembers()) { stack.Push(child); } } }
/// <summary> /// Gets the mappers for the namespaces contained in <see cref="ElementMapper{T}.Left"/> and <see cref="ElementMapper{T}.Right"/> /// </summary> /// <returns>The list of <see cref="NamespaceMapper"/>.</returns> public IEnumerable <NamespaceMapper> GetNamespaces() { if (_namespaces == null) { _namespaces = new Dictionary <INamespaceSymbol, NamespaceMapper>(Settings.EqualityComparer); AddOrCreateMappers(Left, ElementSide.Left); if (Right.Length == 1) { AddOrCreateMappers(Right[0], ElementSide.Right); } else { for (int i = 0; i < Right.Length; i++) { AddOrCreateMappers(Right[i], ElementSide.Right, i); } } void AddOrCreateMappers(IAssemblySymbol symbol, ElementSide side, int setIndex = 0) { if (symbol == null) { return; } Stack <INamespaceSymbol> stack = new(); stack.Push(symbol.GlobalNamespace); while (stack.Count > 0) { INamespaceSymbol nsSymbol = stack.Pop(); if (nsSymbol.GetTypeMembers().Length > 0) { AddMapper(nsSymbol); } foreach (INamespaceSymbol child in nsSymbol.GetNamespaceMembers()) { stack.Push(child); } } Dictionary <INamespaceSymbol, List <INamedTypeSymbol> > typeForwards = ResolveTypeForwards(symbol, Settings.EqualityComparer); foreach (KeyValuePair <INamespaceSymbol, List <INamedTypeSymbol> > kvp in typeForwards) { NamespaceMapper mapper = AddMapper(kvp.Key, checkIfExists: true); mapper.AddForwardedTypes(kvp.Value, side, setIndex); } NamespaceMapper AddMapper(INamespaceSymbol ns, bool checkIfExists = false) { if (!_namespaces.TryGetValue(ns, out NamespaceMapper mapper)) { mapper = new NamespaceMapper(Settings, Right.Length); _namespaces.Add(ns, mapper); } if (checkIfExists && mapper.GetElement(side, setIndex) != null) { return(mapper); } mapper.AddElement(ns, side, setIndex); return(mapper); } }
/// <summary> /// Gets the mappers for the namespaces contained in <see cref="ElementMapper{T}.Left"/> and <see cref="ElementMapper{T}.Right"/> /// </summary> /// <returns>The list of <see cref="NamespaceMapper"/>.</returns> public IEnumerable <NamespaceMapper> GetNamespaces() { if (_namespaces == null) { _namespaces = new Dictionary <INamespaceSymbol, NamespaceMapper>(Settings.EqualityComparer); AddOrCreateMappers(Left, ElementSide.Left); if (Right.Length == 1) { AddOrCreateMappers(Right[0], ElementSide.Right); } else { for (int i = 0; i < Right.Length; i++) { AddOrCreateMappers(Right[i], ElementSide.Right, i); } } void AddOrCreateMappers(IAssemblySymbol symbol, ElementSide side, int setIndex = 0) { if (symbol == null) { return; } Dictionary <INamespaceSymbol, List <INamedTypeSymbol> > typeForwards = ResolveTypeForwards(symbol, Settings.EqualityComparer, setIndex); Stack <INamespaceSymbol> stack = new(); stack.Push(symbol.GlobalNamespace); while (stack.Count > 0) { INamespaceSymbol nsSymbol = stack.Pop(); bool hasTypeForwards = typeForwards.TryGetValue(nsSymbol, out List <INamedTypeSymbol> types); if (hasTypeForwards || nsSymbol.GetTypeMembers().Length > 0) { NamespaceMapper mapper = AddMapper(nsSymbol); if (hasTypeForwards) { mapper.AddForwardedTypes(types, side, setIndex); // remove the typeforwards for this namespace as we did // find and instance of the namespace on the current assembly // and we don't want to create a mapper with the namespace in // the assembly where the forwarded type is defined. typeForwards.Remove(nsSymbol); } } foreach (INamespaceSymbol child in nsSymbol.GetNamespaceMembers()) { stack.Push(child); } } // If the current assembly didn't have a namespace symbol for the resolved typeforwards // use the namespace symbol in the assembly where the forwarded type is defined. // But create the mapper with typeForwardsOnly setting to not visit types defined in the target assembly. foreach (KeyValuePair <INamespaceSymbol, List <INamedTypeSymbol> > kvp in typeForwards) { NamespaceMapper mapper = AddMapper(kvp.Key, checkIfExists: true, typeforwardsOnly: true); mapper.AddForwardedTypes(kvp.Value, side, setIndex); } NamespaceMapper AddMapper(INamespaceSymbol ns, bool checkIfExists = false, bool typeforwardsOnly = false) { if (!_namespaces.TryGetValue(ns, out NamespaceMapper mapper)) { mapper = new NamespaceMapper(Settings, Right.Length, typeforwardsOnly: typeforwardsOnly); _namespaces.Add(ns, mapper); } else if (checkIfExists && mapper.GetElement(side, setIndex) != null) { return(mapper); } mapper.AddElement(ns, side, setIndex); return(mapper); } } Dictionary <INamespaceSymbol, List <INamedTypeSymbol> > ResolveTypeForwards(IAssemblySymbol assembly, IEqualityComparer <ISymbol> comparer, int index) { Dictionary <INamespaceSymbol, List <INamedTypeSymbol> > typeForwards = new(comparer); foreach (INamedTypeSymbol symbol in assembly.GetForwardedTypes()) { if (symbol.TypeKind != TypeKind.Error) { if (!typeForwards.TryGetValue(symbol.ContainingNamespace, out List <INamedTypeSymbol> types)) { types = new List <INamedTypeSymbol>(); typeForwards.Add(symbol.ContainingNamespace, types); } types.Add(symbol); } else { // If we should warn on missing references and we are unable to resolve the type forward, then we should log a diagnostic if (Settings.WarnOnMissingReferences) { _assemblyLoadErrors[index].Add(new CompatDifference( DiagnosticIds.AssemblyReferenceNotFound, string.Format(Resources.MatchingAssemblyNotFound, $"{symbol.ContainingAssembly.Name}.dll"), DifferenceType.Changed, string.Empty)); } } } return(typeForwards); } } return(_namespaces.Values); }