Exemple #1
0
            public override Symbol VisitNamedType(NamedTypeSymbol type)
            {
                var originalDef = (NamedTypeSymbol)type.OriginalDefinition;

                if ((object)originalDef != (object)type)
                {
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    var typeArguments = type.GetAllTypeArguments(ref useSiteDiagnostics);

                    var otherDef = (NamedTypeSymbol)this.Visit(originalDef);
                    if ((object)otherDef == null)
                    {
                        return(null);
                    }

                    var otherTypeParameters = otherDef.GetAllTypeParameters();
                    var otherTypeArguments  = typeArguments.SelectAsArray((t, v) => (TypeSymbol)v.Visit(t), this);
                    Debug.Assert(otherTypeArguments.All(t => (object)t != null));

                    var typeMap = new TypeMap(otherTypeParameters, otherTypeArguments);
                    return(typeMap.SubstituteNamedType(otherDef));
                }

                Debug.Assert(type.IsDefinition);

                var otherContainer = this.Visit(type.ContainingSymbol);

                // Containing type will be missing from other assembly
                // if the type was added in the (newer) source assembly.
                if ((object)otherContainer == null)
                {
                    return(null);
                }

                switch (otherContainer.Kind)
                {
                case SymbolKind.Namespace:
                    if (AnonymousTypeManager.IsAnonymousTypeTemplate(type))
                    {
                        Debug.Assert((object)otherContainer == (object)this.otherAssembly.GlobalNamespace);
                        AnonymousTypeValue value;
                        this.TryFindAnonymousType(type, out value);
                        return((NamedTypeSymbol)value.Type);
                    }
                    else if (type.IsAnonymousType)
                    {
                        return(this.Visit(AnonymousTypeManager.TranslateAnonymousTypeSymbol(type)));
                    }
                    else
                    {
                        return(VisitNamespaceMembers((NamespaceSymbol)otherContainer, type, AreNamedTypesEqual));
                    }

                case SymbolKind.NamedType:
                    return(VisitNamedTypeMembers((NamedTypeSymbol)otherContainer, type, AreNamedTypesEqual));

                default:
                    throw ExceptionUtilities.UnexpectedValue(otherContainer.Kind);
                }
            }
            internal bool TryFindAnonymousType(NamedTypeSymbol type, out AnonymousTypeValue otherType)
            {
                Debug.Assert((object)type.ContainingSymbol == (object)this.sourceAssembly.GlobalNamespace);
                Debug.Assert(AnonymousTypeManager.IsAnonymousTypeTemplate(type));

                var key = new AnonymousTypeKey(AnonymousTypeManager.GetTemplatePropertyNames(type));
                return this.anonymousTypeMap.TryGetValue(key, out otherType);
            }
            public override Symbol VisitNamedType(NamedTypeSymbol sourceType)
            {
                var originalDef = sourceType.OriginalDefinition;

                if ((object)originalDef != (object)sourceType)
                {
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    var typeArguments = sourceType.GetAllTypeArguments(ref useSiteDiagnostics);

                    var otherDef = (NamedTypeSymbol)this.Visit(originalDef);
                    if ((object)otherDef == null)
                    {
                        return(null);
                    }

                    var  otherTypeParameters = otherDef.GetAllTypeParameters();
                    bool translationFailed   = false;

                    var otherTypeArguments = typeArguments.SelectAsArray((t, v) =>
                    {
                        var newType = (TypeSymbol)v.Visit(t.Type);

                        if ((object)newType == null)
                        {
                            // For a newly added type, there is no match in the previous generation, so it could be null.
                            translationFailed = true;
                            newType           = t.Type;
                        }

                        return(new TypeWithModifiers(newType, v.VisitCustomModifiers(t.CustomModifiers)));
                    }, this);

                    if (translationFailed)
                    {
                        // For a newly added type, there is no match in the previous generation, so it could be null.
                        return(null);
                    }

                    // TODO: LambdaFrame has alpha renamed type parameters, should we rather fix that?
                    var typeMap = new TypeMap(otherTypeParameters, otherTypeArguments, allowAlpha: true);
                    return(typeMap.SubstituteNamedType(otherDef));
                }
                else if (sourceType.IsTupleType)
                {
                    var otherDef = (NamedTypeSymbol)this.Visit(sourceType.TupleUnderlyingType);
                    if ((object)otherDef == null || !otherDef.IsTupleOrCompatibleWithTupleOfCardinality(sourceType.TupleElementTypes.Length))
                    {
                        return(null);
                    }

                    return(TupleTypeSymbol.Create(otherDef, sourceType.TupleElementNames));
                }

                Debug.Assert(sourceType.IsDefinition);

                var otherContainer = this.Visit(sourceType.ContainingSymbol);

                // Containing type will be missing from other assembly
                // if the type was added in the (newer) source assembly.
                if ((object)otherContainer == null)
                {
                    return(null);
                }

                switch (otherContainer.Kind)
                {
                case SymbolKind.Namespace:
                    if (AnonymousTypeManager.IsAnonymousTypeTemplate(sourceType))
                    {
                        Debug.Assert((object)otherContainer == (object)_otherAssembly.GlobalNamespace);
                        AnonymousTypeValue value;
                        this.TryFindAnonymousType(sourceType, out value);
                        return((NamedTypeSymbol)value.Type);
                    }
                    else if (sourceType.IsAnonymousType)
                    {
                        return(this.Visit(AnonymousTypeManager.TranslateAnonymousTypeSymbol(sourceType)));
                    }
                    else
                    {
                        return(FindMatchingNamespaceMember((NamespaceSymbol)otherContainer, sourceType, AreNamedTypesEqual));
                    }

                case SymbolKind.NamedType:
                    return(FindMatchingNamedTypeMember((NamedTypeSymbol)otherContainer, sourceType, AreNamedTypesEqual));

                default:
                    throw ExceptionUtilities.UnexpectedValue(otherContainer.Kind);
                }
            }
Exemple #4
0
        private void CompileNamedType(NamedTypeSymbol symbol)
        {
            TypeCompilationState compilationState = new TypeCompilationState(symbol, moduleBeingBuilt);

            cancellationToken.ThrowIfCancellationRequested();

            // Find the constructor of a script class.
            MethodSymbol scriptCtor = null;

            if (symbol.IsScriptClass)
            {
                // The field initializers of a script class could be arbitrary statements,
                // including blocks.  Field initializers containing blocks need to
                // use a MethodBodySemanticModel to build up the appropriate tree of binders, and
                // MethodBodySemanticModel requires an "owning" method.  That's why we're digging out
                // the constructor - it will own the field initializers.
                scriptCtor = symbol.InstanceConstructors[0];
                Debug.Assert((object)scriptCtor != null);
            }

            var synthesizedSubmissionFields   = symbol.IsSubmissionClass ? new SynthesizedSubmissionFields(compilation, symbol) : null;
            var processedStaticInitializers   = new ProcessedFieldInitializers();
            var processedInstanceInitializers = new ProcessedFieldInitializers();

            var sourceTypeSymbol = symbol as SourceMemberContainerTypeSymbol;

            if ((object)sourceTypeSymbol != null)
            {
                BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.StaticInitializers, this.generateDebugInfo, ref processedStaticInitializers);
                BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.InstanceInitializers, this.generateDebugInfo, ref processedInstanceInitializers);

                if (compilationState.Emitting)
                {
                    CompileSynthesizedExplicitImplementations(sourceTypeSymbol, compilationState);
                }
            }

            // Indicates if a static constructor is in the member,
            // so we can decide to synthesize a static constructor.
            bool hasStaticConstructor = false;

            foreach (var member in symbol.GetMembers())
            {
                //When a filter is supplied, limit the compilation of members passing the filter.
                if ((this.filter != null) && !this.filter(member))
                {
                    continue;
                }

                switch (member.Kind)
                {
                case SymbolKind.NamedType:
                    member.Accept(this, compilationState);
                    break;

                case SymbolKind.Method:
                {
                    MethodSymbol method = (MethodSymbol)member;
                    if (method.IsSubmissionConstructor || IsFieldLikeEventAccessor(method))
                    {
                        continue;
                    }

                    if (method.IsPartial())
                    {
                        method = method.PartialImplementation();
                        if ((object)method == null)
                        {
                            continue;
                        }
                    }

                    ProcessedFieldInitializers processedInitializers =
                        method.MethodKind == MethodKind.Constructor ? processedInstanceInitializers :
                        method.MethodKind == MethodKind.StaticConstructor ? processedStaticInitializers :
                        default(ProcessedFieldInitializers);

                    CompileMethod(method, ref processedInitializers, synthesizedSubmissionFields, compilationState);

                    // Set a flag to indicate that a static constructor is created.
                    if (method.MethodKind == MethodKind.StaticConstructor)
                    {
                        hasStaticConstructor = true;
                    }

                    break;
                }

                case SymbolKind.Property:
                {
                    SourcePropertySymbol sourceProperty = member as SourcePropertySymbol;
                    if ((object)sourceProperty != null && sourceProperty.IsSealed && compilationState.Emitting)
                    {
                        CompileSynthesizedSealedAccessors(sourceProperty, compilationState);
                    }
                    break;
                }

                case SymbolKind.Event:
                {
                    SourceEventSymbol eventSymbol = member as SourceEventSymbol;
                    if ((object)eventSymbol != null && eventSymbol.HasAssociatedField && !eventSymbol.IsAbstract && compilationState.Emitting)
                    {
                        CompileFieldLikeEventAccessor(eventSymbol, isAddMethod: true, compilationState: compilationState);
                        CompileFieldLikeEventAccessor(eventSymbol, isAddMethod: false, compilationState: compilationState);
                    }
                    break;
                }

                case SymbolKind.Field:
                {
                    SourceMemberFieldSymbol fieldSymbol = member as SourceMemberFieldSymbol;
                    if ((object)fieldSymbol != null)
                    {
                        if (fieldSymbol.IsConst)
                        {
                            // We check specifically for constant fields with bad values because they never result
                            // in bound nodes being inserted into method bodies (in which case, they would be covered
                            // by the method-level check).
                            ConstantValue constantValue = fieldSymbol.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false);
                            SetGlobalErrorIfTrue(constantValue == null || constantValue.IsBad);
                        }

                        if (fieldSymbol.IsFixed && compilationState.Emitting)
                        {
                            // force the generation of implementation types for fixed-size buffers
                            TypeSymbol discarded = fieldSymbol.FixedImplementationType(compilationState.ModuleBuilder);
                        }
                    }
                    break;
                }
                }
            }

            Debug.Assert(symbol.TypeKind != TypeKind.Submission || ((object)scriptCtor != null && scriptCtor.IsSubmissionConstructor));

            //  process additional anonymous type members
            if (AnonymousTypeManager.IsAnonymousTypeTemplate(symbol))
            {
                ProcessedFieldInitializers processedInitializers = default(ProcessedFieldInitializers);
                foreach (var method in AnonymousTypeManager.GetAnonymousTypeHiddenMethods(symbol))
                {
                    CompileMethod(method, ref processedInitializers, synthesizedSubmissionFields, compilationState);
                }
            }

            // In the case there are field initializers but we haven't created an implicit static constructor (.cctor) for it,
            // (since we may not add .cctor implicitly created for decimals into the symbol table)
            // it is necessary for the compiler to generate the static constructor here if we are emitting.
            if (moduleBeingBuilt != null && !hasStaticConstructor && !processedStaticInitializers.BoundInitializers.IsDefaultOrEmpty)
            {
                Debug.Assert(processedStaticInitializers.BoundInitializers.All((init) =>
                                                                               (init.Kind == BoundKind.FieldInitializer) && !((BoundFieldInitializer)init).Field.IsMetadataConstant));

                MethodSymbol method = new SynthesizedStaticConstructor(sourceTypeSymbol);
                if ((this.filter == null) || this.filter(method))
                {
                    CompileMethod(method, ref processedStaticInitializers, synthesizedSubmissionFields, compilationState);
                    // If this method has been successfully built, we emit it.
                    if (moduleBeingBuilt.GetMethodBody(method) != null)
                    {
                        moduleBeingBuilt.AddCompilerGeneratedDefinition(sourceTypeSymbol, method);
                    }
                }
            }

            // compile submission constructor last so that synthesized submission fields are collected from all script methods:
            if (synthesizedSubmissionFields != null && compilationState.Emitting)
            {
                Debug.Assert(scriptCtor.IsSubmissionConstructor);
                CompileMethod(scriptCtor, ref processedInstanceInitializers, synthesizedSubmissionFields, compilationState);
                synthesizedSubmissionFields.AddToType(scriptCtor.ContainingType, compilationState.ModuleBuilder);
            }

            //  Emit synthesized methods produced during lowering if any
            CompileGeneratedMethods(compilationState);
            compilationState.Free();
        }