Exemplo n.º 1
0
 public Nested(NamedTypeSymbol containingType, ref MetadataTypeName emittedName)
     : this(containingType, ref emittedName, emittedName.ForcedArity == -1 || emittedName.ForcedArity == emittedName.InferredArity)
 {
 }
Exemplo n.º 2
0
        /// <summary>
        /// Lookup a top level type referenced from metadata, names should be
        /// compared case-sensitively.  Detect cycles during lookup.
        /// </summary>
        /// <param name="emittedName">
        /// Full type name, possibly with generic name mangling.
        /// </param>
        /// <param name="visitedAssemblies">
        /// List of assemblies lookup has already visited (since type forwarding can introduce cycles).
        /// </param>
        /// <param name="digThroughForwardedTypes">
        /// Take forwarded types into account.
        /// </param>
        internal sealed override NamedTypeSymbol LookupTopLevelMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList <AssemblySymbol> visitedAssemblies, bool digThroughForwardedTypes)
        {
            NamedTypeSymbol result = null;

            // This is a cache similar to the one used by MetaImport::GetTypeByName in native
            // compiler. The difference is that native compiler pre-populates the cache when it
            // loads types. Here we are populating the cache only with things we looked for, so that
            // next time we are looking for the same thing, the lookup is fast. This cache also
            // takes care of TypeForwarders. Gives about 8% win on subsequent lookups in some
            // scenarios.
            //
            // CONSIDER !!!
            //
            // However, it is questionable how often subsequent lookup by name  is going to happen.
            // Currently it doesn't happen for TypeDef tokens at all, for TypeRef tokens, the
            // lookup by name is done once and the result is cached. So, multiple lookups by name
            // for the same type are going to happen only in these cases:
            // 1) Resolving GetType() in attribute application, type is encoded by name.
            // 2) TypeRef token isn't reused within the same module, i.e. multiple TypeRefs point to
            //    the same type.
            // 3) Different Module refers to the same type, lookup once per Module (with exception of #2).
            // 4) Multitargeting - retargeting the type to a different version of assembly
            result = LookupTopLevelMetadataTypeInCache(ref emittedName);

            if ((object)result != null)
            {
                // We only cache result equivalent to digging through type forwarders, which
                // might produce an forwarder specific ErrorTypeSymbol. We don't want to
                // return that error symbol, unless digThroughForwardedTypes is true.
                if (digThroughForwardedTypes || (!result.IsErrorType() && (object)result.ContainingAssembly == (object)this))
                {
                    return(result);
                }

                // According to the cache, the type wasn't found, or isn't declared in this assembly (forwarded).
                return(new MissingMetadataTypeSymbol.TopLevel(this.Modules[0], ref emittedName));
            }
            else
            {
                // Now we will look for the type in each module of the assembly and pick the first type
                // we find, this is what native VB compiler does.

                var modules = this.Modules;
                var count   = modules.Length;
                var i       = 0;

                result = modules[i].LookupTopLevelMetadataType(ref emittedName);

                if (result is MissingMetadataTypeSymbol)
                {
                    for (i = 1; i < count; i++)
                    {
                        var newResult = modules[i].LookupTopLevelMetadataType(ref emittedName);

                        // Hold on to the first missing type result, unless we found the type.
                        if (!(newResult is MissingMetadataTypeSymbol))
                        {
                            result = newResult;
                            break;
                        }
                    }
                }

                bool foundMatchInThisAssembly = (i < count);

                Debug.Assert(!foundMatchInThisAssembly || (object)result.ContainingAssembly == (object)this);

                if (!foundMatchInThisAssembly && digThroughForwardedTypes)
                {
                    // We didn't find the type
                    System.Diagnostics.Debug.Assert(result is MissingMetadataTypeSymbol);

                    NamedTypeSymbol forwarded = TryLookupForwardedMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies);
                    if ((object)forwarded != null)
                    {
                        result = forwarded;
                    }
                }

                System.Diagnostics.Debug.Assert((object)result != null);

                // Add result of the lookup into the cache
                if (digThroughForwardedTypes || foundMatchInThisAssembly)
                {
                    CacheTopLevelMetadataType(ref emittedName, result);
                }

                return(result);
            }
        }