private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag diagnostics)
        {
            //  prepare
            var  initializers = node.Initializers;
            int  fieldCount   = initializers.Count;
            bool hasError     = false;

            //  bind field initializers
            BoundExpression[]    boundExpressions = new BoundExpression[fieldCount];
            AnonymousTypeField[] fields           = new AnonymousTypeField[fieldCount];
            CSharpSyntaxNode[]   fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount];

            // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on
            //          the fact that the order of properties in anonymous type template corresponds
            //          1-to-1 to the appropriate filed initializer syntax nodes; This means such
            //          correspondence must be preserved all the time including erroneous scenarios

            // set of names already used
            HashSet <string> uniqueFieldNames = new HashSet <string>();

            for (int i = 0; i < fieldCount; i++)
            {
                AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i];
                NameEqualsSyntax nameEquals = fieldInitializer.NameEquals;
                ExpressionSyntax expression = fieldInitializer.Expression;

                SyntaxToken nameToken = default(SyntaxToken);
                if (nameEquals != null)
                {
                    nameToken = nameEquals.Name.Identifier;
                }
                else
                {
                    nameToken = expression.ExtractAnonymousTypeMemberName();
                }

                hasError            = hasError || expression.HasErrors;
                boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue);

                //  check the name to be unique
                string fieldName = null;
                if (nameToken.Kind() == SyntaxKind.IdentifierToken)
                {
                    fieldName = nameToken.ValueText;
                    if (uniqueFieldNames.Contains(fieldName))
                    {
                        //  name duplication
                        Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer);
                        hasError  = true;
                        fieldName = null;
                    }
                    else
                    {
                        uniqueFieldNames.Add(fieldName);
                    }
                }
                else
                {
                    // there is something wrong with field's name
                    hasError = true;
                }

                //  calculate the expression's type and report errors if needed
                TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError);

                // build anonymous type field descriptor
                fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer;
                fields[i]           = new AnonymousTypeField(fieldName == null ? "$" + i.ToString() : fieldName, fieldSyntaxNodes[i].Location, fieldType);

                //  NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed
            }

            //  Create anonymous type
            AnonymousTypeManager    manager       = this.Compilation.AnonymousTypeManager;
            AnonymousTypeDescriptor descriptor    = new AnonymousTypeDescriptor(fields.AsImmutableOrNull(), node.NewKeyword.GetLocation());
            NamedTypeSymbol         anonymousType = manager.ConstructAnonymousTypeSymbol(descriptor);

            // declarators - bound nodes created for providing semantic info
            // on anonymous type fields having explicitly specified name
            ArrayBuilder <BoundAnonymousPropertyDeclaration> declarators =
                ArrayBuilder <BoundAnonymousPropertyDeclaration> .GetInstance();

            for (int i = 0; i < fieldCount; i++)
            {
                NameEqualsSyntax explicitName = initializers[i].NameEquals;
                if (explicitName != null)
                {
                    AnonymousTypeField field = fields[i];
                    if (field.Name != null)
                    {
                        //  get property symbol and create a bound property declaration node
                        foreach (var symbol in anonymousType.GetMembers(field.Name))
                        {
                            if (symbol.Kind == SymbolKind.Property)
                            {
                                declarators.Add(new BoundAnonymousPropertyDeclaration(fieldSyntaxNodes[i], (PropertySymbol)symbol, field.Type));
                                break;
                            }
                        }
                    }
                }
            }

            // check if anonymous object creation is allowed in this context
            if (!this.IsAnonymousTypesAllowed())
            {
                Error(diagnostics, ErrorCode.ERR_AnonymousTypeNotAvailable, node.NewKeyword);
                hasError = true;
            }

            //  Finally create a bound node
            return(new BoundAnonymousObjectCreationExpression(
                       node,
                       anonymousType.InstanceConstructors[0],
                       boundExpressions.AsImmutableOrNull(),
                       declarators.ToImmutableAndFree(),
                       anonymousType,
                       hasError));
        }
Beispiel #2
0
            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)Visit(originalDef);
                    if (otherDef is null)
                    {
                        return(null);
                    }

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

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

                        if (newType is 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(t.WithTypeAndModifiers(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));
                }

                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 (otherContainer is null)
                {
                    return(null);
                }

                switch (otherContainer.Kind)
                {
                case SymbolKind.Namespace:
                    if (sourceType is AnonymousTypeManager.AnonymousTypeTemplateSymbol template)
                    {
                        Debug.Assert((object)otherContainer == (object)_otherAssembly.GlobalNamespace);
                        TryFindAnonymousType(template, out var value);
                        return((NamedTypeSymbol)value.Type);
                    }

                    if (sourceType.IsAnonymousType)
                    {
                        return(Visit(AnonymousTypeManager.TranslateAnonymousTypeSymbol(sourceType)));
                    }

                    return(FindMatchingMember(otherContainer, sourceType, AreNamedTypesEqual));

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

                default:
                    throw ExceptionUtilities.UnexpectedValue(otherContainer.Kind);
                }
            }
Beispiel #3
0
            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();
                    var otherTypeArguments  = typeArguments.SelectAsArray((t, v) => (TypeSymbol)v.Visit(t), this);
                    Debug.Assert(otherTypeArguments.All(t => (object)t != 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));
                }

                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)this.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);
                }
            }
Beispiel #4
0
        private BoundExpression BindCodeblock(SyntaxNode syntax, UnboundLambda unboundLambda, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
        {
            if (!Compilation.Options.HasRuntime)
            {
                return(null);
            }
            var isCodeblock = syntax.XIsCodeBlock;

            if (!isCodeblock)
            {
                isCodeblock = !destination.IsDelegateType() && !destination.IsExpressionTree();
            }
            if (!isCodeblock)
            {
                return(null);
            }

            Conversion conv = Conversion.ImplicitReference;

            if (destination != Compilation.CodeBlockType() && !destination.IsObjectType())
            {
                HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                conv = Conversions.ClassifyConversionFromType(Compilation.CodeBlockType(), destination, ref useSiteDiagnostics);
                diagnostics.Add(syntax, useSiteDiagnostics);
            }
            if (Compilation.Options.HasRuntime)
            {
                Debug.Assert(destination == Compilation.CodeBlockType() || conv.Exists);
            }
            if (!syntax.XIsCodeBlock && !Compilation.Options.MacroScript && !syntax.XNode.IsAliasExpression())
            {
                Error(diagnostics, ErrorCode.ERR_CodeblockWithLambdaSyntax, syntax);
            }

            AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager;
            var delegateSignature        = new TypeSymbol[unboundLambda.ParameterCount + 1];
            var usualType = this.Compilation.UsualType();

            for (int i = 0; i < delegateSignature.Length; i++)
            {
                delegateSignature[i] = usualType;
            }
            NamedTypeSymbol cbType       = manager.ConstructCodeblockTypeSymbol(delegateSignature, syntax.Location);
            var             delType      = manager.GetCodeblockDelegateType(cbType);
            var             _boundLambda = unboundLambda.Bind(delType);

            diagnostics.AddRange(_boundLambda.Diagnostics);
            var cbDel = new BoundConversion(
                syntax,
                _boundLambda,
                conversion,
                @checked: false,
                explicitCastInCode: false,
                constantValueOpt: ConstantValue.NotAvailable,
                type: delType)
            {
                WasCompilerGenerated = unboundLambda.WasCompilerGenerated
            };
            var             cbSrc  = new BoundLiteral(syntax, ConstantValue.Create(syntax.XCodeBlockSource), Compilation.GetSpecialType(SpecialType.System_String));
            BoundExpression cbInst = new BoundAnonymousObjectCreationExpression(syntax,
                                                                                cbType.InstanceConstructors[0],
                                                                                new BoundExpression[] { cbDel, cbSrc }.ToImmutableArrayOrEmpty(),
                                                                                System.Collections.Immutable.ImmutableArray <BoundAnonymousPropertyDeclaration> .Empty, cbType)
            {
                WasCompilerGenerated = unboundLambda.WasCompilerGenerated
            };;

            if (conv != Conversion.ImplicitReference)
            {
                cbInst = new BoundConversion(syntax, cbInst, Conversion.ImplicitReference, false, false, ConstantValue.NotAvailable, Compilation.CodeBlockType())
                {
                    WasCompilerGenerated = unboundLambda.WasCompilerGenerated
                };;
            }
            if (!conv.IsValid || (!isCast && conv.IsExplicit))
            {
                GenerateImplicitConversionError(diagnostics, syntax, conv, cbInst, destination);

                return(new BoundConversion(
                           syntax,
                           cbInst,
                           conv,
                           false,
                           explicitCastInCode: isCast,
                           constantValueOpt: ConstantValue.NotAvailable,
                           type: destination,
                           hasErrors: true)
                {
                    WasCompilerGenerated = unboundLambda.WasCompilerGenerated
                });
            }
            return(new BoundConversion(
                       syntax,
                       cbInst,
                       conv,
                       false,
                       explicitCastInCode: isCast,
                       constantValueOpt: ConstantValue.NotAvailable,
                       type: destination)
            {
                WasCompilerGenerated = unboundLambda.WasCompilerGenerated
            });
        }
Beispiel #5
0
        private PhpCompilation(
            string assemblyName,
            PhpCompilationOptions options,
            ImmutableArray<MetadataReference> references,
            //ReferenceManager referenceManager,
            //SyntaxAndDeclarationManager syntaxAndDeclarations
            AsyncQueue<CompilationEvent> eventQueue = null
            )
            : base(assemblyName, references, SyntaxTreeCommonFeatures(ImmutableArray<SyntaxTree>.Empty), false, eventQueue)
        {
            _wellKnownMemberSignatureComparer = new WellKnownMembersSignatureComparer(this);

            _options = options;
            _referenceManager = new ReferenceManager(options.SdkDirectory);
            _tables = new SourceDeclarations();
            _coreTypes = new CoreTypes(this);
            _coreMethods = new CoreMethods(_coreTypes);

            _anonymousTypeManager = new AnonymousTypeManager(this);
        }
Beispiel #6
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();
        }
Beispiel #7
0
 public void BuildType_EmptyPropertyCollection_ThrowsException()
 {
     Assert.That(() => AnonymousTypeManager.BuildType(Enumerable.Empty <Property>()), Throws.ArgumentException);
 }
Beispiel #8
0
 public void BuildType_NullPropertyCollection_ThrowsException()
 {
     Assert.That(() => AnonymousTypeManager.BuildType(null), Throws.InstanceOf <ArgumentNullException>());
 }