File: Language\SymbolCache.NamedTypeSymbolData.IsViewComponentResult.cs
Web Access
Project: src\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.CodeAnalysis;
 
namespace Microsoft.AspNetCore.Razor.Language;
 
internal partial class SymbolCache
{
    public sealed partial class NamedTypeSymbolData
    {
        private sealed class IsViewComponentResult
        {
            public bool IsViewComponent { get; }
            public INamedTypeSymbol ViewComponentAttribute { get; }
            public INamedTypeSymbol? NonViewComponentAttribute { get; }
 
            public IsViewComponentResult(INamedTypeSymbol symbol, INamedTypeSymbol viewComponentAttribute, INamedTypeSymbol? nonViewComponentAttribute)
            {
                ViewComponentAttribute = viewComponentAttribute;
                NonViewComponentAttribute = nonViewComponentAttribute;
 
                if (symbol.DeclaredAccessibility != Accessibility.Public ||
                    symbol.IsAbstract ||
                    symbol.IsGenericType ||
                    AttributeIsDefined(symbol, nonViewComponentAttribute))
                {
                    IsViewComponent = false;
                }
                else
                {
                    IsViewComponent = symbol.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix, StringComparison.Ordinal) ||
                        AttributeIsDefined(symbol, viewComponentAttribute);
                }
            }
 
            public bool IsMatchingCache(INamedTypeSymbol viewComponentAttribute, INamedTypeSymbol? nonViewComponentAttribute)
            {
                return SymbolEqualityComparer.Default.Equals(ViewComponentAttribute, viewComponentAttribute)
                    && SymbolEqualityComparer.Default.Equals(NonViewComponentAttribute, nonViewComponentAttribute);
            }
 
            private static bool AttributeIsDefined(INamedTypeSymbol type, INamedTypeSymbol? queryAttribute)
            {
                if (queryAttribute == null)
                {
                    return false;
                }
 
                var currentType = type;
                while (currentType != null)
                {
                    foreach (var attribute in currentType.GetAttributes())
                    {
                        if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, queryAttribute))
                        {
                            return true;
                        }
                    }
 
                    currentType = currentType.BaseType;
                }
 
                return false;
            }
        }
    }
}