예제 #1
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,
            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;
                            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     = rootBinderOpt ?? 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);
            }
        }
예제 #2
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;
            }
        }
예제 #3
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");