<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AttributeRouting.Helpers;

namespace AttributeRouting.Framework
{
    /// <summary>
    /// Creates <see cref="RouteSpecification"/> objects according to the 
    /// options set in implementations of <see cref="AttributeRoutingConfigurationBase"/>.
    /// </summary>    
    public class RouteReflector
    {
        private readonly AttributeRoutingConfigurationBase _configuration;

        public RouteReflector(AttributeRoutingConfigurationBase configuration)
        {
            if (configuration == null) throw new ArgumentNullException("configuration");

            _configuration = configuration;
        }

        /// <summary>
        /// Yields all the information needed by <see cref="RouteBuilder"/> to build routes.
        /// </summary>
        public IEnumerable<RouteSpecification> BuildRouteSpecifications()
        {
            var controllerRouteSpecs = BuildRouteSpecifications(_configuration.PromotedControllerTypes, _configuration.InheritActionsFromBaseController);
            foreach (var spec in controllerRouteSpecs)
                yield return spec;

            if (!_configuration.Assemblies.Any())
                yield break;

            var scannedControllerTypes = _configuration.Assemblies.SelectMany(a => a.GetControllerTypes(_configuration.FrameworkControllerType)).ToList();
            var unspecdControllerTypes = scannedControllerTypes.Except(_configuration.PromotedControllerTypes);
            var scannedRouteSpecs = BuildRouteSpecifications(unspecdControllerTypes, _configuration.InheritActionsFromBaseController);

            foreach (var spec in scannedRouteSpecs)
                yield return spec;
        }

        private IEnumerable<RouteSpecification> BuildRouteSpecifications(IEnumerable<Type> controllerTypes, bool inheritActionsFromBaseController)
        {
            var controllerCount = 0;

            return (from controllerType in controllerTypes
                    let controllerIndex = controllerCount++
                    let convention = controllerType.GetCustomAttribute<RouteConventionAttributeBase>(false)
                    let routeAreaAttribute = controllerType.GetCustomAttribute<RouteAreaAttribute>(true)
                    let routePrefixAttribute = controllerType.GetCustomAttribute<RoutePrefixAttribute>(true)
                    from actionMethod in controllerType.GetActionMethods(inheritActionsFromBaseController)
                    from routeAttribute in GetRouteAttributes(actionMethod, convention)
                    // precedence is within a controller
                    orderby controllerIndex, routeAttribute.Precedence
                    let routeName = routeAttribute.RouteName
                    let subdomain = GetAreaSubdomain(routeAreaAttribute)
					let isAsyncController = controllerType.IsAsyncController()
                    select new RouteSpecification
                    {
                        AreaName = routeAreaAttribute.SafeGet(a => a.AreaName),
                        AreaUrl = GetAreaUrl(routeAreaAttribute, subdomain),
                        AreaUrlTranslationKey = routeAreaAttribute.SafeGet(a => a.TranslationKey),
                        Subdomain = subdomain,
                        RoutePrefixUrl = GetRoutePrefix(routePrefixAttribute, actionMethod, convention),
                        RoutePrefixUrlTranslationKey = routePrefixAttribute.SafeGet(a => a.TranslationKey),
                        ControllerType = controllerType,
                        ControllerName = controllerType.GetControllerName(),
						ActionName = GetActionName(actionMethod, isAsyncController),
                        RouteUrl = routeAttribute.RouteUrl,
                        RouteUrlTranslationKey = routeAttribute.TranslationKey,
                        HttpMethods = routeAttribute.HttpMethods,
                        DefaultAttributes = GetDefaultAttributes(actionMethod, routeName, convention),
                        ConstraintAttributes = GetConstraintAttributes(actionMethod, routeName, convention),
                        RouteName = routeName,
                        IsAbsoluteUrl = routeAttribute.IsAbsoluteUrl,
                        UseLowercaseRoute = routeAttribute.UseLowercaseRouteFlag,
                        PreserveCaseForUrlParameters = routeAttribute.PreserveCaseForUrlParametersFlag,
                        AppendTrailingSlash = routeAttribute.AppendTrailingSlashFlag
                    }).ToList();
        }

		private static string GetActionName(MethodInfo actionMethod, bool isAsyncController)
		{
			string actionName = actionMethod.Name;
			if (isAsyncController && actionName.EndsWith("Async"))
				actionName = actionName.Substring(0, actionName.Length - 5);
			return actionName;
		}

        private static IEnumerable<IRouteAttribute> GetRouteAttributes(MethodInfo actionMethod, RouteConventionAttributeBase convention)
        {
            var attributes = new List<IRouteAttribute>();

            // Add convention-based attributes
            if (convention != null)
                attributes.AddRange(convention.GetRouteAttributes(actionMethod));

            // Add explicitly-defined attributes
            attributes.AddRange(actionMethod.GetCustomAttributes<IRouteAttribute>(false));

            return attributes.OrderBy(a => a.Order);
        }

        private static string GetAreaUrl(RouteAreaAttribute routeAreaAttribute, string subdomain)
        {<commit_msg>fixed some git line ending junk.<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AttributeRouting.Helpers;

namespace AttributeRouting.Framework
{
    /// <summary>
    /// Creates <see cref="RouteSpecification"/> objects according to the 
    /// options set in implementations of <see cref="AttributeRoutingConfigurationBase"/>.
    /// </summary>    
    public class RouteReflector
    {
        private readonly AttributeRoutingConfigurationBase _configuration;

        public RouteReflector(AttributeRoutingConfigurationBase configuration)
        {
            if (configuration == null) throw new ArgumentNullException("configuration");

            _configuration = configuration;
        }

        /// <summary>
        /// Yields all the information needed by <see cref="RouteBuilder"/> to build routes.
        /// </summary>
        public IEnumerable<RouteSpecification> BuildRouteSpecifications()
        {
            var controllerRouteSpecs = BuildRouteSpecifications(_configuration.PromotedControllerTypes, _configuration.InheritActionsFromBaseController);
            foreach (var spec in controllerRouteSpecs)
                yield return spec;

            if (!_configuration.Assemblies.Any())
                yield break;

            var scannedControllerTypes = _configuration.Assemblies.SelectMany(a => a.GetControllerTypes(_configuration.FrameworkControllerType)).ToList();
            var unspecdControllerTypes = scannedControllerTypes.Except(_configuration.PromotedControllerTypes);
            var scannedRouteSpecs = BuildRouteSpecifications(unspecdControllerTypes, _configuration.InheritActionsFromBaseController);

            foreach (var spec in scannedRouteSpecs)
                yield return spec;
        }

        private IEnumerable<RouteSpecification> BuildRouteSpecifications(IEnumerable<Type> controllerTypes, bool inheritActionsFromBaseController)
        {
            var controllerCount = 0;

            return (from controllerType in controllerTypes
                    let controllerIndex = controllerCount++
                    let convention = controllerType.GetCustomAttribute<RouteConventionAttributeBase>(false)
                    let routeAreaAttribute = controllerType.GetCustomAttribute<RouteAreaAttribute>(true)
                    let routePrefixAttribute = controllerType.GetCustomAttribute<RoutePrefixAttribute>(true)
                    from actionMethod in controllerType.GetActionMethods(inheritActionsFromBaseController)
                    from routeAttribute in GetRouteAttributes(actionMethod, convention)
                    // precedence is within a controller
                    orderby controllerIndex, routeAttribute.Precedence
                    let routeName = routeAttribute.RouteName
                    let subdomain = GetAreaSubdomain(routeAreaAttribute)
                    let isAsyncController = controllerType.IsAsyncController()
                    select new RouteSpecification
                    {
                        AreaName = routeAreaAttribute.SafeGet(a => a.AreaName),
                        AreaUrl = GetAreaUrl(routeAreaAttribute, subdomain),
                        AreaUrlTranslationKey = routeAreaAttribute.SafeGet(a => a.TranslationKey),
                        Subdomain = subdomain,
                        RoutePrefixUrl = GetRoutePrefix(routePrefixAttribute, actionMethod, convention),
                        RoutePrefixUrlTranslationKey = routePrefixAttribute.SafeGet(a => a.TranslationKey),
                        ControllerType = controllerType,
                        ControllerName = controllerType.GetControllerName(),
                        ActionName = GetActionName(actionMethod, isAsyncController),
                        RouteUrl = routeAttribute.RouteUrl,
                        RouteUrlTranslationKey = routeAttribute.TranslationKey,
                        HttpMethods = routeAttribute.HttpMethods,
                        DefaultAttributes = GetDefaultAttributes(actionMethod, routeName, convention),
                        ConstraintAttributes = GetConstraintAttributes(actionMethod, routeName, convention),
                        RouteName = routeName,
                        IsAbsoluteUrl = routeAttribute.IsAbsoluteUrl,
                        UseLowercaseRoute = routeAttribute.UseLowercaseRouteFlag,
                        PreserveCaseForUrlParameters = routeAttribute.PreserveCaseForUrlParametersFlag,
                        AppendTrailingSlash = routeAttribute.AppendTrailingSlashFlag
                    }).ToList();
        }

        private static string GetActionName(MethodInfo actionMethod, bool isAsyncController)
        {
            string actionName = actionMethod.Name;
            if (isAsyncController && actionName.EndsWith("Async"))
                actionName = actionName.Substring(0, actionName.Length - 5);
            return actionName;
        }

        private static IEnumerable<IRouteAttribute> GetRouteAttributes(MethodInfo actionMethod, RouteConventionAttributeBase convention)
        {
            var attributes = new List<IRouteAttribute>();

            // Add convention-based attributes
            if (convention != null)
                attributes.AddRange(convention.GetRouteAttributes(actionMethod));

            // Add explicitly-defined attributes
            attributes.AddRange(actionMethod.GetCustomAttributes<IRouteAttribute>(false));

            return attributes.OrderBy(a => a.Order);
        }

        private static string GetAreaUrl(RouteAreaAttribute routeAreaAttribute, string subdomain)
        {
{'fraction_non_alphanumeric': 0.06351893095768374, 'fraction_numerical': 0.0005345211581291759, 'mean_word_length': 2.436179981634527, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4548086', 'n_tokens_mistral': 2398, 'n_tokens_neox': 2273, 'n_words': 511}