/// <summary>
        ///   Returns all attributes implementing the <typeparamref name="T"/> interface.
        /// </summary>
        public static IEnumerable <T> FindAttributesOfInterface <T>(this ImmutableArray <AttributeData> attributes)
        {
            Type interfType = typeof(T);

            if (!interfType.GetTypeInfo().IsInterface)
            {
                throw new ArgumentException("Expected an interface.");
            }

            string metadataName = interfType.IsConstructedGenericType
                ? interfType.GetGenericTypeDefinition().FullName
                : interfType.FullName;

            for (int i = 0; i < attributes.Length; i++)
            {
                AttributeData data = attributes[i];
                ImmutableArray <INamedTypeSymbol> interfaces = data.AttributeClass.AllInterfaces;

                for (int o = 0; o < interfaces.Length; o++)
                {
                    INamedTypeSymbol interf = interfaces[o];

                    if (interf.MetadataName != metadataName)
                    {
                        continue;
                    }

                    // We got this far, so we have a valid attribute; construct it.
                    yield return(data.Construct <T>());

                    break;
                }
            }
        }
        /// <summary>
        ///   Returns all attributes of type <typeparamref name="T"/>.
        /// </summary>
        public static IEnumerable <T> FindAttributesOfType <T>(this ImmutableArray <AttributeData> attributes, bool allowInherited = true)
        {
            Type type = typeof(T);

            if (type.GetTypeInfo().IsInterface)
            {
                throw new ArgumentException("Expected a type.");
            }

            string metadataName = type.IsConstructedGenericType
                ? type.GetGenericTypeDefinition().Name
                : type.Name;

            for (int i = 0; i < attributes.Length; i++)
            {
                AttributeData data       = attributes[i];
                ITypeSymbol   typeSymbol = data.AttributeClass;

                if (!allowInherited && typeSymbol.MetadataName == metadataName)
                {
                    yield return(data.Construct <T>());
                }
                else if (allowInherited)
                {
                    while (typeSymbol != null)
                    {
                        if (typeSymbol.MetadataName == metadataName)
                        {
                            yield return(data.Construct <T>());

                            break;
                        }

                        typeSymbol = typeSymbol.BaseType;
                    }
                }
            }
        }
Esempio n. 3
0
            /// <inheritdoc />
            public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
            {
                CancellationToken token  = cancellationToken;
                INamedTypeSymbol  symbol = semanticModel.GetDeclaredSymbol(node, token);

                if (symbol == null)
                {
                    return(node);
                }

                int totalAttributes = 0;
                ImmutableArray <AttributeData> attrs = symbol.GetAttributes();

                if (attrs.IsDefaultOrEmpty)
                {
                    return(node);
                }

                SyntaxList <AttributeListSyntax> attributeLists = node.AttributeLists;

                for (int i = 0; i < attributeLists.Count; i++)
                {
                    AttributeListSyntax attributeList = attributeLists[i];
                    SeparatedSyntaxList <AttributeSyntax> attributes = attributeList.Attributes;

                    for (int j = 0; j < attributes.Count; j++, totalAttributes++)
                    {
                        AttributeSyntax attr     = attributes[j];
                        string          attrName = attr.Name.ToString();

                        if (attrName == "Component" || attrName == nameof(ComponentAttribute))
                        {
                            // There is a 'Component' attribute: Specify its content.
                            string contentStr = node.ToString();

                            // TODO: Use b64 and serialization
                            // It works, except Roslyn <= 2.0.0 has a bug with serialization
                            //using (MemoryStream ms = new MemoryStream())
                            //{
                            //    node.SerializeTo(ms, cancellationToken);

                            //    contentStr = ms.TryGetBuffer(out ArraySegment<byte> buffer)
                            //        ? Convert.ToBase64String(buffer.Array, buffer.Offset, buffer.Count)
                            //        : Convert.ToBase64String(ms.ToArray());
                            //}

                            AttributeArgumentSyntax contentArg = SyntaxFactory.AttributeArgument(
                                SyntaxFactory.LiteralExpression(
                                    SyntaxKind.StringLiteralExpression,
                                    SyntaxFactory.Literal(contentStr)
                                    )
                                );

                            node = node.WithAttributeLists(
                                attributeLists.Replace(
                                    attributeList,
                                    attributeList.WithAttributes(
                                        attributes.Replace(attr, attr.WithArgumentList(
                                                               SyntaxFactory.AttributeArgumentList().AddArguments(contentArg)
                                                               ))
                                        )
                                    )
                                );
                        }

                        // Maybe a component?
                        AttributeData attrData = attrs[totalAttributes];

                        if (attrData.AttributeClass.MetadataName == nameof(CopyFromAttribute))
                        {
                            // CopyFrom component: copy members
                            node = CopyMembers(node, attrData, token);
                        }
                        else if (InheritsCompositionAttribute(attrData.AttributeClass))
                        {
                            // Component: apply it
                            CompositionAttribute builtAttr = attrData.Construct <CompositionAttribute>();

                            try
                            {
                                node = builtAttr.Component.Apply(node, symbol, token);

                                if (node == null)
                                {
                                    throw new NullReferenceException("A component cannot return null.");
                                }
                            }
                            catch (Exception e)
                            {
                                throw new DiagnosticException($"Error applying the {builtAttr.Component} component.", e, attr.GetLocation());
                            }
                        }
                    }
                }

                return(node);
            }