コード例 #1
0
        /// <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);
            }
        }
コード例 #2
0
ファイル: AssemblyMapper.cs プロジェクト: safern/apicompat
        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);
                        }
                    }
                }
コード例 #3
0
        /// <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);
                    }
                }
コード例 #4
0
        /// <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);
        }