<commit_before>namespace AgileObjects.AgileMapper.ObjectPopulation
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Extensions;
#if NET_STANDARD
    using System.Reflection;
#endif
    using Members;
    using NetStandardPolyfills;

    internal abstract class MappingExpressionFactoryBase
    {
        public Expression Create(IObjectMappingData mappingData)
        {
            var mapperData = mappingData.MapperData;

            Expression nullMappingBlock;

            if (TargetCannotBeMapped(mappingData, out nullMappingBlock))
            {
                return nullMappingBlock;
            }

            var returnNull = Expression.Return(
                mapperData.ReturnLabelTarget,
                Expression.Default(mapperData.TargetType));

            var mappingExpressions = new List<Expression>();
            var basicMapperData = mapperData.WithNoTargetMember();

            mappingExpressions.AddRange(GetShortCircuitReturns(returnNull, mapperData));
            mappingExpressions.AddUnlessNullOrEmpty(GetMappingCallbackOrNull(CallbackPosition.Before, basicMapperData, mapperData));
            mappingExpressions.AddUnlessNullOrEmpty(GetDerivedTypeMappings(mappingData));
            mappingExpressions.AddRange(GetObjectPopulation(mappingData).WhereNotNull());
            mappingExpressions.AddUnlessNullOrEmpty(GetMappingCallbackOrNull(CallbackPosition.After, basicMapperData, mapperData));

            var mappingBlock = GetMappingBlock(mappingExpressions.WhereNotNull().ToList(), mapperData);
            var mappingBlockWithTryCatch = WrapInTryCatch(mappingBlock, mapperData);

            return mappingBlockWithTryCatch;
        }

        protected abstract bool TargetCannotBeMapped(IObjectMappingData mappingData, out Expression nullMappingBlock);

        protected abstract IEnumerable<Expression> GetShortCircuitReturns(
            GotoExpression returnNull,
            ObjectMapperData mapperData);

        protected abstract Expression GetDerivedTypeMappings(IObjectMappingData mappingData);
<commit_msg>Short-circuiting mapping expression when mapping always goes to a derived type<commit_after>namespace AgileObjects.AgileMapper.ObjectPopulation
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Extensions;
#if NET_STANDARD
    using System.Reflection;
#endif
    using Members;
    using NetStandardPolyfills;

    internal abstract class MappingExpressionFactoryBase
    {
        public Expression Create(IObjectMappingData mappingData)
        {
            var mapperData = mappingData.MapperData;

            Expression nullMappingBlock;

            if (TargetCannotBeMapped(mappingData, out nullMappingBlock))
            {
                return nullMappingBlock;
            }

            var returnNull = Expression.Return(
                mapperData.ReturnLabelTarget,
                Expression.Default(mapperData.TargetType));

            var mappingExpressions = GetShortCircuitReturns(returnNull, mapperData).ToList();

            Expression derivedTypeMappings;

            if (MappingIsToDerivedType(mappingData, out derivedTypeMappings))
            {
                return mappingExpressions.Any()
                    ? Expression.Block(mappingExpressions.Concat(derivedTypeMappings))
                    : derivedTypeMappings;
            }

            var basicMapperData = mapperData.WithNoTargetMember();

            mappingExpressions.AddUnlessNullOrEmpty(derivedTypeMappings);
            mappingExpressions.AddUnlessNullOrEmpty(GetMappingCallbackOrNull(CallbackPosition.Before, basicMapperData, mapperData));
            mappingExpressions.AddRange(GetObjectPopulation(mappingData).WhereNotNull());
            mappingExpressions.AddUnlessNullOrEmpty(GetMappingCallbackOrNull(CallbackPosition.After, basicMapperData, mapperData));

            var mappingBlock = GetMappingBlock(mappingExpressions.WhereNotNull().ToList(), mapperData);
            var mappingBlockWithTryCatch = WrapInTryCatch(mappingBlock, mapperData);

            return mappingBlockWithTryCatch;
        }

        protected abstract bool TargetCannotBeMapped(IObjectMappingData mappingData, out Expression nullMappingBlock);

        protected abstract IEnumerable<Expression> GetShortCircuitReturns(GotoExpression returnNull, ObjectMapperData mapperData);

        private bool MappingIsToDerivedType(IObjectMappingData mappingData, out Expression derivedTypeMappings)
        {
            derivedTypeMappings = GetDerivedTypeMappings(mappingData);

            if (derivedTypeMappings.NodeType != ExpressionType.Goto)
            {
                return false;
            }

            var returnExpression = (GotoExpression)derivedTypeMappings;
            derivedTypeMappings = returnExpression.Value;
            return true;
        }

        protected abstract Expression GetDerivedTypeMappings(IObjectMappingData mappingData);

{'fraction_non_alphanumeric': 0.05971920110737591, 'fraction_numerical': 0.0, 'mean_word_length': 3.079032258064516, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, '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': '4821700', 'n_tokens_mistral': 1218, 'n_tokens_neox': 1154, 'n_words': 224}