public void testMergeRequirements_findsDuplicates() {
   Compiler compiler = createCompiler();
   ErrorManager errorManager = new BlackHoleErrorManager();
   compiler.setErrorManager(errorManager);
   ConformanceConfig.Builder builder = ConformanceConfig.newBuilder();
   builder.addRequirementBuilder().addWhitelist("x").addWhitelist("x");
   CheckConformance.mergeRequirements(compiler, ImmutableList.of(builder.build()));
   assertEquals(1, errorManager.getErrorCount());
 }
 @Override
 public CompilerPass getProcessor(final Compiler compiler) {
   ConformanceConfig.Builder builder = ConformanceConfig.newBuilder();
   try {
     TextFormat.merge(configuration, builder);
   } catch (Exception e) {
     Throwables.propagate(e);
   }
   return new CheckConformance(compiler, ImmutableList.of(builder.build()));
 }
 public void testMergeRequirements() {
   Compiler compiler = createCompiler();
   ConformanceConfig.Builder builder = ConformanceConfig.newBuilder();
   builder.addRequirementBuilder().setRuleId("a").addWhitelist("x").addWhitelistRegexp("m");
   builder.addRequirementBuilder().setExtends("a").addWhitelist("y").addWhitelistRegexp("n");
   List<Requirement> requirements =
       CheckConformance.mergeRequirements(compiler, ImmutableList.of(builder.build()));
   assertThat(requirements).hasSize(1);
   Requirement requirement = requirements.get(0);
   assertEquals(2, requirement.getWhitelistCount());
   assertEquals(2, requirement.getWhitelistRegexpCount());
 }
  /**
   * Gets requirements from all configs. Merges whitelists of requirements with 'extends' equal to
   * 'rule_id' of other rule.
   */
  static List<Requirement> mergeRequirements(
      AbstractCompiler compiler, List<ConformanceConfig> configs) {
    List<Requirement.Builder> builders = new ArrayList<>();
    Map<String, Requirement.Builder> extendable = new HashMap<>();
    for (ConformanceConfig config : configs) {
      for (Requirement requirement : config.getRequirementList()) {
        Requirement.Builder builder = requirement.toBuilder();
        if (requirement.hasRuleId()) {
          if (requirement.getRuleId().isEmpty()) {
            reportInvalidRequirement(compiler, requirement, "empty rule_id");
            continue;
          }
          if (extendable.containsKey(requirement.getRuleId())) {
            reportInvalidRequirement(
                compiler,
                requirement,
                "two requirements with the same rule_id: " + requirement.getRuleId());
            continue;
          }
          extendable.put(requirement.getRuleId(), builder);
        }
        if (!requirement.hasExtends()) {
          builders.add(builder);
        }
      }
    }

    for (ConformanceConfig config : configs) {
      for (Requirement requirement : config.getRequirementList()) {
        if (requirement.hasExtends()) {
          Requirement.Builder existing = extendable.get(requirement.getExtends());
          if (existing == null) {
            reportInvalidRequirement(
                compiler, requirement, "no requirement with rule_id: " + requirement.getExtends());
            continue;
          }
          for (Descriptors.FieldDescriptor field : requirement.getAllFields().keySet()) {
            if (!EXTENDABLE_FIELDS.contains(field.getName())) {
              reportInvalidRequirement(
                  compiler, requirement, "extending rules allow only " + EXTENDABLE_FIELDS);
            }
          }
          existing.addAllWhitelist(requirement.getWhitelistList());
          existing.addAllWhitelistRegexp(requirement.getWhitelistRegexpList());
          existing.addAllOnlyApplyTo(requirement.getOnlyApplyToList());
          existing.addAllOnlyApplyToRegexp(requirement.getOnlyApplyToRegexpList());
        }
      }
    }

    List<Requirement> requirements = new ArrayList<>(builders.size());
    for (Requirement.Builder builder : builders) {
      Requirement requirement = builder.build();
      checkRequirementList(compiler, requirement, "whitelist");
      checkRequirementList(compiler, requirement, "whitelist_regexp");
      checkRequirementList(compiler, requirement, "only_apply_to");
      checkRequirementList(compiler, requirement, "only_apply_to_regexp");
      requirements.add(requirement);
    }
    return requirements;
  }