private static void GetMemberClassifications(
            ExpressionMappingComponent expr,
            out ImmutableDictionary <string, string> membersClassificationDict,
            out string[] unmappedCompatibleMembers)
        {
            var membersClasification = GetSameNameFieldsAndProperties(expr.SourceTypeSymbol, expr.TargetTypeSymbol);

            var dict = PrepareMemberClassificationDictForCodeFix(
                membersClasification,
                expr.SourceTypeSymbol,
                expr.TargetTypeSymbol);

            IEnumerable <ISymbol> allSymbolsTouchedOutsideDefault = GetAllSymbolsTouchedOutsideDefault(expr);

            var untouchedAutomappables =
                membersClasification.mappable
                .Where(name => allSymbolsTouchedOutsideDefault.Any(x => x.Name == name) == false)
                .ToArray();

            var untouchedAutomappablesJoined = string.Join(";", untouchedAutomappables);

            dict = dict.Add(AutomappableMembersNotTouchedOutsideDefaulDictKey, untouchedAutomappablesJoined);

            membersClassificationDict = dict;

            var handledMappableSymbols = GetSymbolsMappedOrIgnoredInSource(expr);

            unmappedCompatibleMembers =
                membersClasification.mappable
                .Where(name => handledMappableSymbols.Any(x => x.Name == name) == false)
                .ToArray();
        }
 private static IEnumerable <ISymbol> GetSymbolsMappedOrIgnoredInSource(ExpressionMappingComponent expr)
 {
     return(new[]
     {
         expr.SymbolsMappedInSource,
         expr.SymbolsIgnoredInSource
     }
            .SelectMany(x => x));
 }
 private static IEnumerable <ISymbol> GetAllSymbolsTouchedOutsideDefault(ExpressionMappingComponent expr)
 {
     return(new[]
     {
         expr.SymbolsMappedCustom.source,
         expr.SymbolsIgnoredInSource,
         expr.SymbolsMappedCustom.target,
         expr.SymbolsIgnoredInTarget
     }
            .SelectMany(x => x));
 }
        private static void CheckAndNotifyMissingMembers(SymbolAnalysisContext context, ExpressionMappingComponent expr)
        {
            GetMemberClassifications(expr,
                                     out var membersClassificationDict,
                                     out var unmappedCompatibleMembers);

            if (unmappedCompatibleMembers.Any())
            {
                var unmappedCompatibleMembersJoined = string.Join(";", unmappedCompatibleMembers);

                var diag = Diagnostic.Create(
                    MapperDefinitionMissingMemberRule,
                    expr.DefaultMappings.GetLocation(),
                    membersClassificationDict.Add(CodeFixActionTypeDictKey, CodeFixActionRegenerateDefaultMappings),
                    $"Some membmers with identical names are not mapped. " +
                    $"Please choose '{IKoshelevRoslynMapperCodeFixProvider.TitleRegenerateDefaultMappings}' or " +
                    $"manually handle missing members: {unmappedCompatibleMembersJoined}.");

                context.ReportDiagnostic(diag);
            }

            CheckAndNotifyMissingMembers(
                expr.SourceTypeSymbol,
                expr.SymbolsMappedInSource,
                expr.SymbolsIgnoredInSource,
                getNotifyFn("Source", SourceMembersToIgnoreDictKey, membersClassificationDict, expr.IgnoreInSource));

            CheckAndNotifyMissingMembers(
                expr.TargetTypeSymbol,
                expr.SymbolsMappedInTarget,
                expr.SymbolsIgnoredInTarget,
                getNotifyFn("Target", TargeMembersToIgnoreDictKey, membersClassificationDict, expr.IgnoreInTarget));

            return;

            Action <ISymbol[], ISymbol[]> getNotifyFn(
                string memberType,
                string key,
                ImmutableDictionary <string, string> classificationDict,
                ObjectCreationExpressionSyntax existingIgnore)
            {
                return((missing, alreadyIgnored) =>
                {
                    var missingNames = string.Join(";", missing.Select(x => x.Name).ToArray());

                    var verb = (missing.Length > 1)
                                                ? "are"
                                                : "is";

                    var dict = classificationDict
                               .Add(key, missingNames)
                               .Add(CodeFixActionTypeDictKey, CodeFixActionAddUnmappedMembersToIgnore);

                    var additionalLocations = (new Location[] { existingIgnore?.GetLocation() })
                                              .Where(x => x != null)
                                              .ToArray();

                    var diag = Diagnostic.Create(
                        MapperDefinitionMissingMemberRule,
                        expr.CreationExpressionSyntax.GetLocation(),
                        additionalLocations,
                        dict,
                        $"{memberType} member {missingNames} {verb} not mapped.");

                    context.ReportDiagnostic(diag);
                });
            }
        }