private static void CheckMembers(SummaryAnalysis analysis)
        {
            var summary = analysis.Summary;

            // No duplicate names
            var targets          = summary.GetBenchmarkTargets();
            var duplicateTargets = GetDuplicates(
                targets,
                t => t.Method.Name,
                t => $"\r\n\t\t  {t.Method.DeclaringType}.{t.Method.Name}()");

            if (duplicateTargets.NotNullNorEmpty())
            {
                analysis.WriteSetupErrorMessage(
                    $"There are multiple methods with same name: {duplicateTargets.Join(",\r\n\t\t")}.",
                    "Rename methods to avoid duplicates.");
            }

            // No conflict on attributes
            var targetMethodsWithAttributes = targets
                                              .SelectMany(GetInvokedMethods)
                                              .Distinct()
                                              .SelectMany(
                m =>
                m.GetCustomAttributes(true)
                .Select(a =>
                        (method: m,
                         attributeType: a.GetType(),
                         baseAttribute: _knownUniqueMemberLevelAttributes.FirstOrDefault(ka => ka.IsInstanceOfType(a)),
                         target: (a as TargetedAttribute)?.Target))
                .Where(t => t.baseAttribute != null))
                                              .ToArray();

            var conflictingAttributes = GetDuplicates(
                targetMethodsWithAttributes,
                t => $"{t.method.DeclaringType}.{t.method.Name}({t.target})",
                t => $"\r\n\t\t  {t.attributeType.FullName}");

            if (conflictingAttributes.NotNullNorEmpty())
            {
                analysis.WriteSetupErrorMessage(
                    $"There are conflicting attributes: {conflictingAttributes.Join(",\r\n\t\t")}.",
                    "There can be only one.");
            }

            // No multiple methods for an attribute
            var conflictingMethods = GetDuplicates(
                targetMethodsWithAttributes.Where(t => _knownUniqueTypeLevelAttributes.Contains(t.baseAttribute)),
                t => $"{t.baseAttribute.FullName}({t.target})",
                t => $"\r\n\t\t  {t.method.DeclaringType}.{t.method.Name}() ({t.attributeType.FullName})");

            if (conflictingMethods.NotNullNorEmpty())
            {
                analysis.WriteSetupErrorMessage(
                    $"There are conflicting methods: {conflictingMethods.Join(",\r\n\t\t")}.",
                    "Leave only one method for each attribute.");
            }
        }
        private static bool CheckSetup(SummaryAnalysis analysis)
        {
            var summary = analysis.Summary;

            // DONTTOUCH: DO NOT add return into if clauses.
            // All conditions should be checked
            if (summary.HasCriticalValidationErrors)
            {
                analysis.WriteExecutionErrorMessage("Summary has validation errors.");
            }

            if (!summary.HasCriticalValidationErrors && summary.Benchmarks.IsNullOrEmpty())
            {
                analysis.WriteSetupErrorMessage(
                    "Nothing to check as there is no methods in benchmark.",
                    $"Apply one of {nameof(CompetitionBenchmarkAttribute)}, {nameof(CompetitionBaselineAttribute)} or {nameof(BenchmarkAttribute)} to the benchmark methods.");
            }

            if (summary.Config.GetJobs().Skip(1).Any())
            {
                analysis.WriteSetupErrorMessage(
                    "Benchmark configuration includes multiple jobs. " +
                    "This is not supported as there's no way to store metric annotations individually per each job.",
                    "Ensure that the config contains only one job.");
            }

            if (summary.Benchmarks.Select(b => b.Parameters).Distinct().Skip(1).Any())
            {
                analysis.WriteInfoMessage(
                    "Benchmark configuration includes multiple parameters. " +
                    "Note that results for each parameter set will be merged.");
            }

            CheckMembers(analysis);

            CheckMetrics(analysis);

            return(analysis.SafeToContinue);
        }
        public IEnumerable <Conclusion> Analyse([NotNull] Summary summary)
        {
            var analysis = new SummaryAnalysis(Id, summary, MessageSource.Validator);

            foreach (var validationError in summary.ValidationErrors)
            {
                var message = validationError.Benchmark == null
                                        ? validationError.Message
                                        : $"Benchmark {validationError.Benchmark.DisplayInfo}:{Environment.NewLine}\t{validationError.Message}";

                if (validationError.IsCritical)
                {
                    analysis.WriteSetupErrorMessage(message);
                }
                else
                {
                    analysis.WriteWarningMessage(message);
                }
            }

            return(analysis.Conclusions);
        }