示例#1
0
        /// <summary>
        /// Find canonical type for NoPia embedded type.
        /// </summary>
        /// <returns>
        /// Symbol for the canonical type or an ErrorTypeSymbol. Never returns null.
        /// </returns>
        internal static NamedTypeSymbol SubstituteNoPiaLocalType(
            ref MetadataTypeName name,
            bool isInterface,
            TypeSymbol baseType,
            string interfaceGuid,
            string scope,
            string identifier,
            AssemblySymbol referringAssembly)
        {
            NamedTypeSymbol result = null;

            Guid interfaceGuidValue     = new Guid();
            bool haveInterfaceGuidValue = false;
            Guid scopeGuidValue         = new Guid();
            bool haveScopeGuidValue     = false;

            if (isInterface && interfaceGuid != null)
            {
                haveInterfaceGuidValue = Guid.TryParse(interfaceGuid, out interfaceGuidValue);

                if (haveInterfaceGuidValue)
                {
                    // To have consistent errors.
                    scope      = null;
                    identifier = null;
                }
            }

            if (scope != null)
            {
                haveScopeGuidValue = Guid.TryParse(scope, out scopeGuidValue);
            }

            foreach (AssemblySymbol assembly in referringAssembly.GetNoPiaResolutionAssemblies())
            {
                Debug.Assert((object)assembly != null);
                if (ReferenceEquals(assembly, referringAssembly))
                {
                    continue;
                }

                NamedTypeSymbol candidate = assembly.LookupTopLevelMetadataType(ref name, digThroughForwardedTypes: false);
                Debug.Assert(!candidate.IsGenericType);

                // Ignore type forwarders, error symbols and non-public types
                if (candidate.Kind == SymbolKind.ErrorType ||
                    !ReferenceEquals(candidate.ContainingAssembly, assembly) ||
                    candidate.DeclaredAccessibility != Accessibility.Public)
                {
                    continue;
                }

                // Ignore NoPia local types.
                // If candidate is coming from metadata, we don't need to do any special check,
                // because we do not create symbols for local types. However, local types defined in source
                // is another story. However, if compilation explicitly defines a local type, it should be
                // represented by a retargeting assembly, which is supposed to hide the local type.
                Debug.Assert(!(assembly is SourceAssemblySymbol) || !((SourceAssemblySymbol)assembly).SourceModule.MightContainNoPiaLocalTypes());

                string candidateGuid;
                bool   haveCandidateGuidValue = false;
                Guid   candidateGuidValue     = new Guid();

                // The type must be of the same kind (interface, struct, delegate or enum).
                switch (candidate.TypeKind)
                {
                case TypeKind.Interface:
                    if (!isInterface)
                    {
                        continue;
                    }

                    // Get candidate's Guid
                    if (candidate.GetGuidString(out candidateGuid) && candidateGuid != null)
                    {
                        haveCandidateGuidValue = Guid.TryParse(candidateGuid, out candidateGuidValue);
                    }

                    break;

                case TypeKind.Delegate:
                case TypeKind.Enum:
                case TypeKind.Struct:

                    if (isInterface)
                    {
                        continue;
                    }

                    // Let's use a trick. To make sure the kind is the same, make sure
                    // base type is the same.
                    if (!ReferenceEquals(baseType, candidate.BaseTypeNoUseSiteDiagnostics))
                    {
                        continue;
                    }

                    break;

                default:
                    continue;
                }

                if (haveInterfaceGuidValue || haveCandidateGuidValue)
                {
                    if (!haveInterfaceGuidValue || !haveCandidateGuidValue ||
                        candidateGuidValue != interfaceGuidValue)
                    {
                        continue;
                    }
                }
                else
                {
                    if (!haveScopeGuidValue || identifier == null || !identifier.Equals(name.FullName))
                    {
                        continue;
                    }

                    // Scope guid must match candidate's assembly guid.
                    haveCandidateGuidValue = false;
                    if (assembly.GetGuidString(out candidateGuid) && candidateGuid != null)
                    {
                        haveCandidateGuidValue = Guid.TryParse(candidateGuid, out candidateGuidValue);
                    }

                    if (!haveCandidateGuidValue || scopeGuidValue != candidateGuidValue)
                    {
                        continue;
                    }
                }

                // OK. It looks like we found canonical type definition.
                if ((object)result != null)
                {
                    // Ambiguity
                    result = new NoPiaAmbiguousCanonicalTypeSymbol(referringAssembly, result, candidate);
                    break;
                }

                result = candidate;
            }

            if ((object)result == null)
            {
                result = new NoPiaMissingCanonicalTypeSymbol(
                    referringAssembly,
                    name.FullName,
                    interfaceGuid,
                    scope,
                    identifier);
            }

            return(result);
        }
示例#2
0
 internal override bool GetGuidString(out string guidString)
 {
     return(_underlyingType.GetGuidString(out guidString));
 }