< Summary

Information
Class: TeleFlow.Telegram.Internal.Handlers.TelegramHandlerAssemblyScanner
Assembly: TeleFlow.Framework
File(s): /_/src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerAssemblyScanner.cs
Line coverage
98%
Covered lines: 59
Uncovered lines: 1
Coverable lines: 60
Total lines: 113
Line coverage: 98.3%
Branch coverage
95%
Covered branches: 42
Total branches: 44
Branch coverage: 95.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetGeneratedRegistrars(...)100%1180%
GetHandlerTypes(...)100%44100%
GetAssemblyTypes(...)50%22100%
HasTelegramHandlerMethods(...)100%1010100%
IsClassBasedHandlerType(...)100%44100%
HasDeclaredHandleAsync(...)50%22100%
HasRouteAttributes(...)100%2020100%
HasErrorAttributes(...)100%11100%
HasGenericCallbackAttribute(...)100%22100%

File(s)

/_/src/TeleFlow.Framework/Internal/Handlers/TelegramHandlerAssemblyScanner.cs

#LineLine coverage
 1using System.Reflection;
 2using TeleFlow.Annotations;
 3
 4namespace TeleFlow.Telegram.Internal.Handlers;
 5
 6internal static class TelegramHandlerAssemblyScanner
 7{
 8    public static TelegramGeneratedHandlersAttribute[] GetGeneratedRegistrars(Assembly assembly)
 9    {
 3910        ArgumentNullException.ThrowIfNull(assembly);
 11
 3912        return assembly
 3913            .GetCustomAttributes<TelegramGeneratedHandlersAttribute>()
 014            .OrderBy(static attribute => attribute.RegistrarType.FullName, StringComparer.Ordinal)
 3915            .ToArray();
 16    }
 17
 18    public static Type[] GetHandlerTypes(Assembly assembly)
 19    {
 1420        ArgumentNullException.ThrowIfNull(assembly);
 21
 1422        return GetAssemblyTypes(assembly)
 281023            .Where(static type => type is { IsAbstract: false, IsInterface: false })
 1424            .Where(HasTelegramHandlerMethods)
 43425            .OrderBy(static type => type.FullName, StringComparer.Ordinal)
 1426            .ToArray();
 27    }
 28
 29    private static Type[] GetAssemblyTypes(Assembly assembly)
 30    {
 31        try
 32        {
 1433            return assembly.GetTypes();
 34        }
 135        catch (ReflectionTypeLoadException exception)
 36        {
 137            var loaderMessages = exception.LoaderExceptions
 138                .Where(static loaderException => loaderException is not null)
 139                .Select(static loaderException => loaderException!.Message)
 140                .Where(static message => !string.IsNullOrWhiteSpace(message))
 141                .Distinct(StringComparer.Ordinal)
 142                .Take(5)
 143                .ToArray();
 144            var details = loaderMessages.Length == 0
 145                ? string.Empty
 146                : $" Loader exceptions: {string.Join(" | ", loaderMessages)}";
 47
 148            throw new InvalidOperationException(
 149                $"Could not load Telegram handler types from assembly '{assembly.FullName}'.{details}",
 150                exception);
 51        }
 1352    }
 53
 54    private static bool HasTelegramHandlerMethods(Type handlerType)
 55    {
 278356        if (IsClassBasedHandlerType(handlerType) &&
 278357            HasDeclaredHandleAsync(handlerType) &&
 278358            HasRouteAttributes(handlerType))
 59        {
 1460            return true;
 61        }
 62
 276963        return handlerType
 276964            .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
 611765            .Any(static method => !method.IsSpecialName &&
 611766                                  (HasRouteAttributes(method) || HasErrorAttributes(method)));
 67    }
 68
 69    private static bool IsClassBasedHandlerType(Type handlerType)
 70    {
 278371        return typeof(MessageHandler).IsAssignableFrom(handlerType) ||
 278372               typeof(CallbackHandler).IsAssignableFrom(handlerType) ||
 278373               typeof(ChatMemberUpdateHandler).IsAssignableFrom(handlerType);
 74    }
 75
 76    private static bool HasDeclaredHandleAsync(Type handlerType)
 77    {
 1678        return handlerType
 1679            .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
 3080            .Any(static method => !method.IsSpecialName &&
 3081                                  string.Equals(method.Name, "HandleAsync", StringComparison.Ordinal));
 82    }
 83
 84    private static bool HasRouteAttributes(MemberInfo member)
 85    {
 289886        return member.GetCustomAttributes<CommandAttribute>(inherit: true).Any() ||
 289887               member.GetCustomAttributes<MessageAttribute>(inherit: true).Any() ||
 289888               member.GetCustomAttributes<TextAttribute>(inherit: true).Any() ||
 289889               member.GetCustomAttributes<TextTemplateAttribute>(inherit: true).Any() ||
 289890               member.GetCustomAttributes<CommandTemplateAttribute>(inherit: true).Any() ||
 289891               member.GetCustomAttributes<TextRegexAttribute>(inherit: true).Any() ||
 289892               member.GetCustomAttributes<CommandRegexAttribute>(inherit: true).Any() ||
 289893               member.GetCustomAttributes<CallbackAttribute>(inherit: true).Any() ||
 289894               HasGenericCallbackAttribute(member) ||
 289895               member.GetCustomAttributes<ChatMemberUpdatedAttribute>(inherit: true).Any() ||
 289896               member.GetCustomAttributes<MyChatMemberUpdatedAttribute>(inherit: true).Any();
 97    }
 98
 99    private static bool HasErrorAttributes(MemberInfo member)
 100    {
 2496101        return member.GetCustomAttributes<ErrorAttribute>(inherit: true).Any();
 102    }
 103
 104    private static bool HasGenericCallbackAttribute(MemberInfo member)
 105    {
 2537106        return member
 2537107            .GetCustomAttributes(inherit: true)
 3879108            .Select(static attribute => attribute.GetType())
 2537109            .Any(static type =>
 6416110                type.IsGenericType &&
 6416111                type.GetGenericTypeDefinition() == typeof(CallbackAttribute<>));
 112    }
 113}