コード例 #1
0
        internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree)
        {
            _compilation = compilation;
            _syntaxTree = syntaxTree;
            if (!this.Compilation.SyntaxTrees.Contains(syntaxTree))
            {
                throw new ArgumentOutOfRangeException("tree", CSharpResources.TreeNotPartOfCompilation);
            }

            _binderFactory = compilation.GetBinderFactory(SyntaxTree);
        }
コード例 #2
0
        internal SyntaxTreeSemanticModel(CSharpCompilation compilation, SyntaxTree syntaxTree, bool ignoreAccessibility = false)
        {
            _compilation = compilation;
            _syntaxTree = syntaxTree;
            _ignoresAccessibility = ignoreAccessibility;

            if (!this.Compilation.SyntaxTrees.Contains(syntaxTree))
            {
                throw new ArgumentOutOfRangeException(nameof(syntaxTree), CSharpResources.TreeNotPartOfCompilation);
            }

            _binderFactory = compilation.GetBinderFactory(SyntaxTree);
        }
コード例 #3
0
            private void BindAndReplaceCref(
                XAttribute attribute,
                CSharpSyntaxNode originatingSyntax
                )
            {
                string     attributeValue = attribute.Value;
                CrefSyntax crefSyntax     = SyntaxFactory.ParseCref(attributeValue);

                if (crefSyntax == null)
                {
                    // This can happen if the cref is verbatim (e.g. "T:C").
                    return;
                }

                // CONSIDER: It would be easy to construct an XmlLocation from the XAttribute, so that
                // we could point the user at the actual problem.
                Location sourceLocation = originatingSyntax.Location;

                RecordSyntaxDiagnostics(crefSyntax, sourceLocation); // Respects DocumentationMode.

                MemberDeclarationSyntax memberDeclSyntax =
                    BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax);

                Debug.Assert(
                    memberDeclSyntax != null,
                    "Why are we processing a documentation comment that is not attached to a member declaration?"
                    );

                Binder binder = BinderFactory.MakeCrefBinder(
                    crefSyntax,
                    memberDeclSyntax,
                    _compilation.GetBinderFactory(memberDeclSyntax.SyntaxTree)
                    );

                var crefDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics);

                attribute.Value = GetDocumentationCommentId(crefSyntax, binder, crefDiagnostics); // NOTE: mutation (element must be a copy)
                RecordBindingDiagnostics(crefDiagnostics, sourceLocation);                        // Respects DocumentationMode.
                crefDiagnostics.Free();
            }
コード例 #4
0
 internal SyntaxTreeSemanticModel(CSharpCompilation parentCompilation, SyntaxTree parentSyntaxTree, SyntaxTree speculatedSyntaxTree)
 {
     _compilation = parentCompilation;
     _syntaxTree = speculatedSyntaxTree;
     _binderFactory = _compilation.GetBinderFactory(parentSyntaxTree);
 }
コード例 #5
0
        /// <summary>
        /// Bind the (implicit or explicit) constructor initializer of a constructor symbol.
        /// </summary>
        /// <param name="constructor">Constructor method.</param>
        /// <param name="diagnostics">Accumulates errors (e.g. access "this" in constructor initializer).</param>
        /// <param name="compilation">Used to retrieve binder.</param>
        /// <returns>A bound expression for the constructor initializer call.</returns>
        private static BoundExpression BindConstructorInitializer(MethodSymbol constructor, DiagnosticBag diagnostics, CSharpCompilation compilation)
        {
            // Note that the base type can be null if we're compiling System.Object in source.
            NamedTypeSymbol baseType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics;

            SourceMethodSymbol sourceConstructor = constructor as SourceMethodSymbol;
            CSharpSyntaxNode syntax = null;
            ArgumentListSyntax initializerArgumentListOpt = null;
            if ((object)sourceConstructor != null)
            {
                syntax = sourceConstructor.SyntaxNode;

                if (syntax.Kind == SyntaxKind.ConstructorDeclaration)
                {
                    var constructorSyntax = (ConstructorDeclarationSyntax)syntax;
                    if (constructorSyntax.Initializer != null)
                    {
                        initializerArgumentListOpt = constructorSyntax.Initializer.ArgumentList;
                    }

                    ErrorCode reportIfHavePrimaryCtor = ErrorCode.Void;

                    if (initializerArgumentListOpt == null || initializerArgumentListOpt.Parent.Kind != SyntaxKind.ThisConstructorInitializer)
                    {
                        reportIfHavePrimaryCtor = ErrorCode.ERR_InstanceCtorMustHaveThisInitializer;
                    }
                    else if (initializerArgumentListOpt.Arguments.Count == 0 && constructor.ContainingType.TypeKind == TypeKind.Struct)
                    {
                        // Based on C# Design Notes for Oct 21, 2013:
                        reportIfHavePrimaryCtor = ErrorCode.ERR_InstanceCtorCannotHaveDefaultThisInitializer;
                    }

                    if (reportIfHavePrimaryCtor != ErrorCode.Void)
                    {
                        var container = constructor.ContainingType as SourceMemberContainerTypeSymbol;

                        if ((object)container != null && (object)container.PrimaryCtor != null)
                        {
                            diagnostics.Add(reportIfHavePrimaryCtor, constructor.Locations[0]);
                        }
                    }
                }
                else 
                {
                    // Primary constuctor case.
                    Debug.Assert(syntax.Kind == SyntaxKind.ParameterList);
                    if (syntax.Parent.Kind == SyntaxKind.ClassDeclaration)
                    {
                        var classDecl = (ClassDeclarationSyntax)syntax.Parent;

                        if (classDecl.BaseList != null && classDecl.BaseList.Types.Count > 0)
                        {
                            TypeSyntax baseTypeSyntax = classDecl.BaseList.Types[0];
                            if (baseTypeSyntax.Kind == SyntaxKind.BaseClassWithArguments)
                            {
                                initializerArgumentListOpt = ((BaseClassWithArgumentsSyntax)baseTypeSyntax).ArgumentList;
                            }
                        }
                    }
                    else
            {
                        Debug.Assert(syntax.Parent.Kind == SyntaxKind.StructDeclaration);
                    }
                }
            }

            // The common case is that we have no constructor initializer and the type inherits directly from object.
            // Also, we might be trying to generate a constructor for an entirely compiler-generated class such
            // as a closure class; in that case it is vexing to try to find a suitable binder for the non-existing
            // constructor syntax so that we can do unnecessary overload resolution on the non-existing initializer!
            // Simply take the early out: bind directly to the parameterless object ctor rather than attempting
            // overload resolution.
            if (initializerArgumentListOpt == null && (object)baseType != null)
            {
                if (baseType.SpecialType == SpecialType.System_Object)
                {
                    return GenerateObjectConstructorInitializer(constructor, diagnostics);
                }
                else if (baseType.IsErrorType() || baseType.IsStatic)
                {
                    // If the base type is bad and there is no initializer then we can just bail.
                    // We have no expressions we need to analyze to report errors on.
                    return null;
                }
            }

            // Either our base type is not object, or we have an initializer syntax, or both. We're going to
            // need to do overload resolution on the set of constructors of the base type, either on
            // the provided initializer syntax, or on an implicit ": base()" syntax.

            // SPEC ERROR: The specification states that if you have the situation 
            // SPEC ERROR: class B { ... } class D1 : B {} then the default constructor
            // SPEC ERROR: generated for D1 must call an accessible *parameterless* constructor
            // SPEC ERROR: in B. However, it also states that if you have 
            // SPEC ERROR: class B { ... } class D2 : B { D2() {} }  or
            // SPEC ERROR: class B { ... } class D3 : B { D3() : base() {} }  then
            // SPEC ERROR: the compiler performs *overload resolution* to determine
            // SPEC ERROR: which accessible constructor of B is called. Since B might have
            // SPEC ERROR: a ctor with all optional parameters, overload resolution might
            // SPEC ERROR: succeed even if there is no parameterless constructor. This
            // SPEC ERROR: is unintentionally inconsistent, and the native compiler does not
            // SPEC ERROR: implement this behavior. Rather, we should say in the spec that
            // SPEC ERROR: if there is no ctor in D1, then a ctor is created for you exactly
            // SPEC ERROR: as though you'd said "D1() : base() {}". 
            // SPEC ERROR: This is what we now do in Roslyn.

            // Now, in order to do overload resolution, we're going to need a binder. There are
            // three possible situations:
            //
            // class D1 : B { }
            // class D2 : B { D2(int x) { } }
            // class D3 : B { D3(int x) : base(x) { } }
            //
            // In the first case the binder needs to be the binder associated with
            // the *body* of D1 because if the base class ctor is protected, we need
            // to be inside the body of a derived class in order for it to be in the
            // accessibility domain of the protected base class ctor.
            //
            // In the second case the binder could be the binder associated with 
            // the body of D2; since the implicit call to base() will have no arguments
            // there is no need to look up "x".
            // 
            // In the third case the binder must be the binder that knows about "x" 
            // because x is in scope.

            Binder outerBinder;

            if ((object)sourceConstructor == null)
            {
                // The constructor is implicit. We need to get the binder for the body
                // of the enclosing class. 
                CSharpSyntaxNode containerNode = constructor.GetNonNullSyntaxNode();
                SyntaxToken bodyToken;
                if (containerNode.Kind == SyntaxKind.ClassDeclaration)
                {
                    bodyToken = ((ClassDeclarationSyntax)containerNode).OpenBraceToken;
                }
                else if (containerNode.Kind == SyntaxKind.StructDeclaration)
                {
                    bodyToken = ((StructDeclarationSyntax)containerNode).OpenBraceToken;
                }
                else if (containerNode.Kind == SyntaxKind.EnumDeclaration)
                {
                    // We're not going to find any non-default ctors, but we'll look anyway.
                    bodyToken = ((EnumDeclarationSyntax)containerNode).OpenBraceToken;
                }
                else
                {
                    Debug.Assert(false, "How did we get an implicit constructor added to something that is neither a class nor a struct?");
                    bodyToken = containerNode.GetFirstToken();
                }

                outerBinder = compilation.GetBinderFactory(containerNode.SyntaxTree).GetBinder(containerNode, bodyToken.Position);
            }
            else if (initializerArgumentListOpt == null)
            {
                // We have a ctor in source but no explicit constructor initializer.  We can't just use the binder for the
                // type containing the ctor because the ctor might be marked unsafe.  Use the binder for the parameter list
                // as an approximation - the extra symbols won't matter because there are no identifiers to bind.

                outerBinder = compilation.GetBinderFactory(sourceConstructor.SyntaxTree).GetBinder(syntax.Kind == SyntaxKind.ParameterList ? 
                                                                                                        syntax :
                                                                                                        ((ConstructorDeclarationSyntax)syntax).ParameterList);
            }
            else
            {
                outerBinder = compilation.GetBinderFactory(sourceConstructor.SyntaxTree).GetBinder(initializerArgumentListOpt);
            }

            //wrap in ConstructorInitializerBinder for appropriate errors
            Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor);
            return initializerBinder.BindConstructorInitializer(initializerArgumentListOpt, constructor, diagnostics);
        }
コード例 #6
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
            ImmutableArray<ImmutableArray<FieldInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
            bool generateDebugInfo, out ConsList<Imports> firstDebugImports)
        {
            Debug.Assert((object)scriptCtor != null);

            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray<FieldInitializer> siblingInitializers = initializers[i];

                // 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;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.Field;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    Debug.Assert(syntaxRef.SyntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

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

                    Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

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

                    Binder parentBinder = new ExecutableCodeBinder((CSharpSyntaxNode)syntaxRef.SyntaxTree.GetRoot(), scriptCtor, scriptClassBinder);

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);
                    }
                    else if (initializerNode.Kind == SyntaxKind.LabeledStatement)
                    {
                        // TODO: labels in interactive
                        var boundStatement = new BoundBadStatement(initializerNode, ImmutableArray<BoundNode>.Empty, true);
                        boundInitializer = new BoundGlobalStatementInitializer(initializerNode, boundStatement);
                    }
                    else
                    {
                        var collisionDetector = new LocalScopeBinder(parentBinder);
                        boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// In regular C#, all field initializers are assignments to fields and the assigned expressions
        /// may not reference instance members.
        /// </summary>
        private static void BindRegularCSharpFieldInitializers(
            CSharpCompilation compilation,
            ImmutableArray<ImmutableArray<FieldInitializer>> initializers,
            ArrayBuilder<BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            bool generateDebugInfo,
            out ConsList<Imports> firstDebugImports)
        {
            firstDebugImports = null;

            foreach (ImmutableArray<FieldInitializer> siblingInitializers in initializers)
            {
                // 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)
                {
                    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 = (CSharpSyntaxNode)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;
                        }

                        BoundInitializer boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder.WithPrimaryConstructorParametersIfNecessary(fieldSymbol.ContainingType, shadowBackingFields: true)).
                                            WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);

                        boundInitializers.Add(boundInitializer);
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Method to merge attributes from the given attributesSyntaxLists and filter out attributes by attribute target.
        /// This is the first step in attribute binding.
        /// </summary>
        /// <remarks>
        /// This method can generate diagnostics for few cases where we have an invalid target specifier and the parser hasn't generated the necessary diagnostics.
        /// It should not perform any bind operations as it can lead to an attribute binding cycle.
        /// </remarks>
        private ImmutableArray<AttributeSyntax> GetAttributesToBind(
            OneOrMany<SyntaxList<AttributeListSyntax>> attributeDeclarationSyntaxLists,
            AttributeLocation symbolPart,
            DiagnosticBag diagnostics,
            CSharpCompilation compilation,
            out ImmutableArray<Binder> binders)
        {
            var attributeTarget = (IAttributeTargetSymbol)this;

            ArrayBuilder<AttributeSyntax> syntaxBuilder = null;
            ArrayBuilder<Binder> bindersBuilder = null;
            int attributesToBindCount = 0;

            for (int listIndex = 0; listIndex < attributeDeclarationSyntaxLists.Count; listIndex++)
            {
                var attributeDeclarationSyntaxList = attributeDeclarationSyntaxLists[listIndex];
                if (attributeDeclarationSyntaxList.Any())
                {
                    int prevCount = attributesToBindCount;
                    foreach (var attributeDeclarationSyntax in attributeDeclarationSyntaxList)
                    {
                        // We bind the attribute only if it has a matching target for the given ownerSymbol and attributeLocation.
                        if (MatchAttributeTarget(attributeTarget, symbolPart, attributeDeclarationSyntax.Target, diagnostics))
                        {
                            if (syntaxBuilder == null)
                            {
                                syntaxBuilder = new ArrayBuilder<AttributeSyntax>();
                                bindersBuilder = new ArrayBuilder<Binder>();
                            }

                            var attributesToBind = attributeDeclarationSyntax.Attributes;
                            syntaxBuilder.AddRange(attributesToBind);
                            attributesToBindCount += attributesToBind.Count;
                        }
                    }

                    if (attributesToBindCount != prevCount)
                    {
                        Debug.Assert(attributeDeclarationSyntaxList.Node != null);
                        Debug.Assert(bindersBuilder != null);

                        var syntaxTree = attributeDeclarationSyntaxList.Node.SyntaxTree;
                        var binder = compilation.GetBinderFactory(syntaxTree).GetBinder((CSharpSyntaxNode)attributeDeclarationSyntaxList.Node);

                        binder = new ContextualAttributeBinder(binder, this);
                        Debug.Assert(!binder.InAttributeArgument, "Possible cycle in attribute binding");

                        for (int i = 0; i < attributesToBindCount - prevCount; i++)
                        {
                            bindersBuilder.Add(binder);
                        }
                    }
                }
            }

            if (syntaxBuilder != null)
            {
                binders = bindersBuilder.ToImmutableAndFree();
                return syntaxBuilder.ToImmutableAndFree();
            }
            else
            {
                binders = ImmutableArray<Binder>.Empty;
                return ImmutableArray<AttributeSyntax>.Empty;
            }
        }
コード例 #9
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
            ArrayBuilder<BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            out ImportChain firstDebugImports)
        {
            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray<FieldOrPropertyInitializer> siblingInitializers = initializers[i];

                // 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;
                // Label instances must be shared across all global statements.
                ScriptLocalScopeBinder.Labels labels = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.FieldOpt;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    var syntaxTree = syntaxRef.SyntaxTree;
                    Debug.Assert(syntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var syntax = (CSharpSyntaxNode)syntaxRef.GetSyntax();
                    var syntaxRoot = syntaxTree.GetCompilationUnitRoot();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxTree);
                        labels = new ScriptLocalScopeBinder.Labels(scriptInitializer, syntaxRoot);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(syntax);
                    Debug.Assert(((NamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportChain;
                    }

                    Binder parentBinder = new ExecutableCodeBinder(
                        syntaxRoot,
                        scriptInitializer,
                        new ScriptLocalScopeBinder(labels, scriptClassBinder));

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            parentBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)syntax,
                            diagnostics);
                    }
                    else
                    {
                        boundInitializer = BindGlobalStatement(
                            parentBinder,
                            scriptInitializer,
                            (StatementSyntax)syntax,
                            diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
コード例 #10
0
ファイル: Binder_Initializers.cs プロジェクト: EkardNT/Roslyn
        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;
        }
コード例 #11
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);
        }
コード例 #12
0
        private ImmutableArray <AttributeSyntax> GetAttributesToBind(
            OneOrMany <SyntaxList <AttributeListSyntax> > attributeDeclarationSyntaxLists,
            AttributeLocation symbolPart,
            BindingDiagnosticBag diagnostics,
            CSharpCompilation compilation,
            Func <AttributeSyntax, bool> attributeMatchesOpt,
            Binder rootBinderOpt,
            out ImmutableArray <Binder> binders)
        {
            var attributeTarget = (IAttributeTargetSymbol)this;

            ArrayBuilder <AttributeSyntax> syntaxBuilder  = null;
            ArrayBuilder <Binder>          bindersBuilder = null;
            int attributesToBindCount = 0;

            for (int listIndex = 0; listIndex < attributeDeclarationSyntaxLists.Count; listIndex++)
            {
                var attributeDeclarationSyntaxList = attributeDeclarationSyntaxLists[listIndex];
                if (attributeDeclarationSyntaxList.Any())
                {
                    int prevCount = attributesToBindCount;
                    foreach (var attributeDeclarationSyntax in attributeDeclarationSyntaxList)
                    {
                        // We bind the attribute only if it has a matching target for the given ownerSymbol and attributeLocation.
                        if (MatchAttributeTarget(attributeTarget, symbolPart, attributeDeclarationSyntax.Target, diagnostics))
                        {
                            if (syntaxBuilder == null)
                            {
                                syntaxBuilder  = new ArrayBuilder <AttributeSyntax>();
                                bindersBuilder = new ArrayBuilder <Binder>();
                            }

                            var attributesToBind = attributeDeclarationSyntax.Attributes;
                            if (attributeMatchesOpt is null)
                            {
                                syntaxBuilder.AddRange(attributesToBind);
                                attributesToBindCount += attributesToBind.Count;
                            }
                            else
                            {
                                foreach (var attribute in attributesToBind)
                                {
                                    if (attributeMatchesOpt(attribute))
                                    {
                                        syntaxBuilder.Add(attribute);
                                        attributesToBindCount++;
                                    }
                                }
                            }
                        }
                    }

                    if (attributesToBindCount != prevCount)
                    {
                        Debug.Assert(attributeDeclarationSyntaxList.Node != null);
                        Debug.Assert(bindersBuilder != null);

                        var syntaxTree = attributeDeclarationSyntaxList.Node.SyntaxTree;
                        var binder     = rootBinderOpt ?? compilation.GetBinderFactory(syntaxTree).GetBinder(attributeDeclarationSyntaxList.Node);

                        binder = new ContextualAttributeBinder(binder, this);
                        Debug.Assert(!binder.InAttributeArgument || this is MethodSymbol {
                            MethodKind: MethodKind.LambdaMethod
                        }, "Possible cycle in attribute binding");
コード例 #13
0
        /// <summary>
        /// In regular C#, all field initializers are assignments to fields and the assigned expressions
        /// may not reference instance members.
        /// </summary>
        private static void BindRegularCSharpFieldInitializers(
            CSharpCompilation compilation,
            ImmutableArray <FieldInitializers> initializers,
            ArrayBuilder <BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            bool generateDebugInfo,
            out ConsList <Imports> firstDebugImports)
        {
            firstDebugImports = null;

            foreach (FieldInitializers siblingInitializers in initializers)
            {
                // 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;

                var infos = ArrayBuilder <FieldInitializerInfo> .GetInstance(); // Exact size is not known up front.

                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);
                }

                ArrayBuilder <BoundInitializer> initializersBuilder = locals.IsDefaultOrEmpty ? boundInitializers : ArrayBuilder <BoundInitializer> .GetInstance(infos.Count);

                foreach (var info in infos)
                {
                    Binder binder = info.Binder;
                    ScopedExpressionBinder scopedExpressionBinder = null;

                    // Constant initializers is not part of the initialization scope.
                    if (info.Initializer.Field.IsConst || locals.IsDefault)
                    {
                        binder = scopedExpressionBinder = new ScopedExpressionBinder(binder, info.EqualsValue.Value);
                    }
                    else if (!locals.IsEmpty)
                    {
                        binder = new SimpleLocalScopeBinder(locals, binder);
                    }

                    BoundFieldInitializer boundInitializer = BindFieldInitializer(binder, info.Initializer.Field, info.EqualsValue, diagnostics);

                    if (scopedExpressionBinder != null && !scopedExpressionBinder.Locals.IsDefaultOrEmpty)
                    {
                        boundInitializer = boundInitializer.Update(boundInitializer.Field, scopedExpressionBinder.AddLocalScopeToExpression(boundInitializer.InitialValue));
                    }

                    initializersBuilder.Add(boundInitializer);
                }

                Debug.Assert(locals.IsDefaultOrEmpty == (initializersBuilder == boundInitializers));
                if (!locals.IsDefaultOrEmpty)
                {
                    boundInitializers.Add(new BoundInitializationScope((CSharpSyntaxNode)siblingInitializers.TypeDeclarationSyntax.GetSyntax(),
                                                                       locals, initializersBuilder.ToImmutableAndFree()));
                }
            }
        }