Exemplo n.º 1
0
        internal static ImmutableArray<LocalSymbol> GetFieldInitializerInfos(
            CSharpCompilation compilation,
            FieldInitializers siblingInitializers,
            ArrayBuilder<FieldInitializerInfo> infos,
            bool generateDebugInfo,
            ref ConsList<Imports> firstDebugImports)
        {
            // All sibling initializers share the same parent node and tree so we can reuse the binder 
            // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
            // individual fields might have their own binders (e.g. because of being declared unsafe).
            BinderFactory binderFactory = null;

            foreach (FieldInitializer initializer in siblingInitializers.Initializers)
            {
                FieldSymbol fieldSymbol = initializer.Field;
                Debug.Assert((object)fieldSymbol != null);

                // A constant field of type decimal needs a field initializer, so
                // check if it is a metadata constant, not just a constant to exclude
                // decimals. Other constants do not need field initializers.
                if (!fieldSymbol.IsMetadataConstant)
                {
                    //Can't assert that this is a regular C# compilation, because we could be in a nested type of a script class.
                    SyntaxReference syntaxRef = initializer.Syntax;
                    var initializerNode = (EqualsValueClauseSyntax)syntaxRef.GetSyntax();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
                    }

                    Binder parentBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type
                            fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios

                    if (generateDebugInfo && firstDebugImports == null)
                    {
                        firstDebugImports = parentBinder.ImportsList;
                    }

                    parentBinder = new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol);

                    if (!fieldSymbol.IsConst && !fieldSymbol.IsStatic)
                    {
                        parentBinder = parentBinder.WithPrimaryConstructorParametersIfNecessary(fieldSymbol.ContainingType);
                    }

                    infos.Add(new FieldInitializerInfo(initializer, parentBinder, initializerNode));
                }
            }

            // See if there are locals that we need to bring into the scope.
            var locals = default(ImmutableArray<LocalSymbol>);
            if (siblingInitializers.TypeDeclarationSyntax != null)
            {
                locals = GetInitializationScopeLocals(infos);

                if (!locals.IsDefaultOrEmpty)
                {
                    for (int i = 0; i < infos.Count; i++)
                    {
                        FieldInitializerInfo info = infos[i];

                        // Constant initializers is not part of the initialization scope.
                        if (!info.Initializer.Field.IsConst)
                        {
                            infos[i] = new FieldInitializerInfo(info.Initializer,
                                                                new SimpleLocalScopeBinder(locals, info.Binder),
                                                                info.EqualsValue);
                        }
                    }
                }
            }

            return locals;
        }
 private FieldInitializersInfo GetFieldInitializersInfo(ConcurrentDictionary<TypeDeclarationSyntax, FieldInitializersInfo> map, FieldInitializers siblingInitializers)
 {
     return map.GetOrAdd((TypeDeclarationSyntax)siblingInitializers.TypeDeclarationSyntax.GetSyntax(),
                                                     (typeDecl) =>
                                                     {
                                                         var infos = ArrayBuilder<FieldInitializerInfo>.GetInstance(); // Exact size is not known up front.
                                                         ConsList<Imports> firstDebugImports = null;
                                                         var locals = Binder.GetFieldInitializerInfos(compilation, siblingInitializers, infos, false, ref firstDebugImports);
                                                         return new FieldInitializersInfo(locals, infos.ToImmutableAndFree());
                                                     });
 }