// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;

import static com.android.tools.r8.DiagnosticsChecker.checkDiagnostics;
import static com.android.tools.r8.shaking.ProguardConfigurationSourceStrings.createConfigurationForTesting;
import static com.android.tools.r8.utils.BooleanUtils.intValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextRange;
import com.android.tools.r8.shaking.ProguardClassNameList.SingleClassNameList;
import com.android.tools.r8.shaking.ProguardConfigurationParser.IdentifierPatternWithWildcards;
import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType;
import com.android.tools.r8.shaking.constructor.InitMatchingTest;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.android.tools.r8.utils.KeepingDiagnosticHandler;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class EmptyMainClassForProguardTests {

  public static void main(String[] args) {
  }
}

@RunWith(Parameterized.class)
public class ProguardConfigurationParserTest extends TestBase {

  private static final String VALID_PROGUARD_DIR = "src/test/proguard/valid/";
  private static final String INVALID_PROGUARD_DIR = "src/test/proguard/invalid/";
  private static final String PROGUARD_SPEC_FILE = VALID_PROGUARD_DIR + "proguard.flags";
  private static final String MULTIPLE_NAME_PATTERNS_FILE =
      VALID_PROGUARD_DIR + "multiple-name-patterns.flags";
  private static final String ACCESS_FLAGS_FILE = VALID_PROGUARD_DIR + "access-flags.flags";
  private static final String WHY_ARE_YOU_KEEPING_FILE =
      VALID_PROGUARD_DIR + "why-are-you-keeping.flags";
  private static final String ASSUME_NO_SIDE_EFFECTS =
      VALID_PROGUARD_DIR + "assume-no-side-effects.flags";
  private static final String ASSUME_NO_SIDE_EFFECTS_WITH_RETURN_VALUE =
      VALID_PROGUARD_DIR + "assume-no-side-effects-with-return-value.flags";
  private static final String ASSUME_VALUES_WITH_RETURN_VALUE =
      VALID_PROGUARD_DIR + "assume-values-with-return-value.flags";
  private static final String ADAPT_KOTLIN_METADATA =
      VALID_PROGUARD_DIR + "adapt-kotlin-metadata.flags";
  private static final String INCLUDING =
      VALID_PROGUARD_DIR + "including.flags";
  private static final String INVALID_INCLUDING_1 =
      INVALID_PROGUARD_DIR + "including-1.flags";
  private static final String INVALID_INCLUDING_2 =
      INVALID_PROGUARD_DIR + "including-2.flags";
  private static final String LIBRARY_JARS =
      VALID_PROGUARD_DIR + "library-jars.flags";
  private static final String LIBRARY_JARS_WIN =
      VALID_PROGUARD_DIR + "library-jars-win.flags";
  private static final String SEEDS =
      VALID_PROGUARD_DIR + "seeds.flags";
  private static final String SEEDS_2 =
      VALID_PROGUARD_DIR + "seeds-2.flags";
  private static final String VERBOSE =
      VALID_PROGUARD_DIR + "verbose.flags";
  private static final String KEEPDIRECTORIES =
      VALID_PROGUARD_DIR + "keepdirectories.flags";
  private static final String DONT_OBFUSCATE =
      VALID_PROGUARD_DIR + "dontobfuscate.flags";
  private static final String PACKAGE_OBFUSCATION_1 =
      VALID_PROGUARD_DIR + "package-obfuscation-1.flags";
  private static final String PACKAGE_OBFUSCATION_2 =
      VALID_PROGUARD_DIR + "package-obfuscation-2.flags";
  private static final String PACKAGE_OBFUSCATION_3 =
      VALID_PROGUARD_DIR + "package-obfuscation-3.flags";
  private static final String PACKAGE_OBFUSCATION_4 =
      VALID_PROGUARD_DIR + "package-obfuscation-4.flags";
  private static final String PACKAGE_OBFUSCATION_5 =
      VALID_PROGUARD_DIR + "package-obfuscation-5.flags";
  private static final String PACKAGE_OBFUSCATION_6 =
      VALID_PROGUARD_DIR + "package-obfuscation-6.flags";
  private static final String APPLY_MAPPING =
      VALID_PROGUARD_DIR + "applymapping.flags";
  private static final String APPLY_MAPPING_WITHOUT_FILE =
      INVALID_PROGUARD_DIR + "applymapping-without-file.flags";
  private static final String DONT_SHRINK =
      VALID_PROGUARD_DIR + "dontshrink.flags";
  private static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES =
      VALID_PROGUARD_DIR + "dontskipnonpubliclibraryclasses.flags";
  private static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS =
      VALID_PROGUARD_DIR + "dontskipnonpubliclibraryclassmembers.flags";
  private static final String IDENTIFIER_NAME_STRING =
      VALID_PROGUARD_DIR + "identifiernamestring.flags";
  private static final String OVERLOAD_AGGRESIVELY =
      VALID_PROGUARD_DIR + "overloadaggressively.flags";
  private static final String DONT_OPTIMIZE =
      VALID_PROGUARD_DIR + "dontoptimize.flags";
  private static final String DONT_OPTIMIZE_OVERRIDES_PASSES =
      VALID_PROGUARD_DIR + "dontoptimize-overrides-optimizationpasses.flags";
  private static final String OPTIMIZATION_PASSES =
      VALID_PROGUARD_DIR + "optimizationpasses.flags";
  private static final String OPTIMIZATION_PASSES_WITHOUT_N =
      INVALID_PROGUARD_DIR + "optimizationpasses-without-n.flags";
  private static final String PARSE_AND_SKIP_SINGLE_ARGUMENT =
      VALID_PROGUARD_DIR + "parse-and-skip-single-argument.flags";
  private static final String PRINT_USAGE =
      VALID_PROGUARD_DIR + "printusage.flags";
  private static final String PRINT_USAGE_TO_FILE =
      VALID_PROGUARD_DIR + "printusage-to-file.flags";
  private static final String TARGET =
      VALID_PROGUARD_DIR + "target.flags";

  private Reporter reporter;
  private KeepingDiagnosticHandler handler;
  private ProguardConfigurationParser parser;
  private List<String> whiteSpace =
      ImmutableList.of("", " ", "   ", "\t", " \t", " \t", " \t ", " \t\t \t ");
  private List<String> lineSeparators = ImmutableList.of("\n", "\r\n");
  private List<Character> quotes = ImmutableList.of('"', '\'');

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public ProguardConfigurationParserTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  @Before
  public void reset() {
    handler = new KeepingDiagnosticHandler();
    reporter = new Reporter(handler);
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
  }

  @Before
  public void resetAllowTestOptions() {
    handler = new KeepingDiagnosticHandler();
    reporter = new Reporter(handler);
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter, true);
  }

  @Test
  public void parse() throws Exception {
    ProguardConfigurationParser parser;

    // Parse from file.
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PROGUARD_SPEC_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(24, rules.size());
    assertEquals(1, rules.get(0).getMemberRules().size());

    // Parse from strings.
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    List<String> lines = FileUtils.readAllLines(Paths.get(PROGUARD_SPEC_FILE));
    parser.parse(createConfigurationForTesting(lines));
    rules = parser.getConfig().getRules();
    assertEquals(24, rules.size());
    assertEquals(1, rules.get(0).getMemberRules().size());
  }

  @Test
  public void parseMultipleNamePatterns() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(MULTIPLE_NAME_PATTERNS_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(1, rule.getMemberRules().size());
    assertEquals("com.company.hello.**,com.company.world.**", rule.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, ((ProguardKeepRule) rule).getType());
    assertTrue(rule.getInheritanceIsExtends());
    assertEquals("some.library.Class", rule.getInheritanceClassName().toString());
    ProguardMemberRule memberRule = rule.getMemberRules().iterator().next();
    assertTrue(memberRule.getAccessFlags().isProtected());
    assertEquals(ProguardNameMatcher.create(
        IdentifierPatternWithWildcards.withoutWildcards("getContents")), memberRule.getName());
    assertEquals("java.lang.Object[][]", memberRule.getType().toString());
    assertEquals(ProguardMemberType.METHOD, memberRule.getRuleType());
    assertEquals(0, memberRule.getArguments().size());
  }

  @Test
  public void parseNonJavaIdentifiers() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, new Reporter());
    String nonJavaIdentifiers =
        String.join("\n", ImmutableList.of(
            "-keep class -package-.-ClassNameWithDash-{",
            "  -NameWithDash- -field-;",
            "  p-.-OtherNameWithDash- -method-(-p.-WithDash-, -package-.-ClassNameWithDash-[]); ",
            "}"));
    parser.parse(createConfigurationForTesting(ImmutableList.of(nonJavaIdentifiers)));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    assertEquals(ProguardClassType.CLASS, rules.get(0).getClassType());
    assertEquals(1, rules.get(0).getClassNames().size());
    List<DexType> classTypes = rules.get(0).getClassNames().asSpecificDexTypes();
    assertEquals(1, classTypes.size());
    assertSame(dexItemFactory.createType("L-package-/-ClassNameWithDash-;"), classTypes.get(0));
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(2, rule.getMemberRules().size());
    int matches = 0;
    for (ProguardMemberRule memberRule : rule.getMemberRules()) {
      if (memberRule.getRuleType() == ProguardMemberType.FIELD) {
        assertTrue(memberRule.getName().matches("-field-"));
        matches |= 0x01;
      } else {
        assertEquals(ProguardMemberType.METHOD, memberRule.getRuleType());
        assertTrue(memberRule.getName().matches("-method-"));
        assertFalse(memberRule.getArguments().get(0).getSpecificType().isArrayType());
        assertSame(dexItemFactory.createType("L-p/-WithDash-;"),
            memberRule.getArguments().get(0).getSpecificType());
        assertSame(dexItemFactory.createType("[L-package-/-ClassNameWithDash-;"),
            memberRule.getArguments().get(1).getSpecificType());
        matches |= 0x02;
      }
    }
    assertEquals(0x03, matches);
  }

  private void testDontXXX(
      String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String configuration = "-dont" + xxx + " !foobar,*bar";
    parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    Predicate<DexType> matcher = matcherFactory.apply(config);
    assertFalse(matcher.test(dexItemFactory.createType("Lboobaz;")));
    assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
    assertFalse(matcher.test(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontXXX() {
    testDontXXX("warn", config -> DontWarnConfiguration.create(config)::matches);
    testDontXXX("note", config -> config.getDontNotePatterns()::matches);
  }

  private void testDontXXXMultiple(
      String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    List<String> configuration1 = ImmutableList.of("-dont" + xxx + " foo.**, bar.**");
    List<String> configuration2 = ImmutableList.of("-dont" + xxx + " foo.**", "-dontwarn bar.**");
    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
      parser.parse(createConfigurationForTesting(configuration));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      Predicate<DexType> matcher = matcherFactory.apply(config);
      assertTrue(matcher.test(dexItemFactory.createType("Lfoo/Bar;")));
      assertTrue(matcher.test(dexItemFactory.createType("Lfoo/bar7Bar;")));
      assertTrue(matcher.test(dexItemFactory.createType("Lbar/Foo;")));
    }
  }

  @Test
  public void testDontWarnMultiple() {
    testDontXXXMultiple("warn", config -> DontWarnConfiguration.create(config)::matches);
    testDontXXXMultiple("note", config -> config.getDontNotePatterns()::matches);
  }

  private void testDontXXXAllExplicitly(
      String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String dontwarnAll = "-dont" + xxx + " *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    Predicate<DexType> matcher = matcherFactory.apply(config);
    assertTrue(matcher.test(dexItemFactory.createType("Lboobaz;")));
    assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
    assertTrue(matcher.test(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontWarnAllExplicitly() {
    testDontXXXAllExplicitly("warn", config -> DontWarnConfiguration.create(config)::matches);
    testDontXXXAllExplicitly("note", config -> config.getDontNotePatterns()::matches);
  }

  private void testDontXXXAllImplicitly(
      String xxx, Function<ProguardConfiguration, Predicate<DexType>> matcherFactory) {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String dontwarnAll = "-dont" + xxx;
    String otherOption = "-keep class *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll, otherOption)));
    ProguardConfiguration config = parser.getConfig();
    Predicate<DexType> matcher = matcherFactory.apply(config);
    assertTrue(matcher.test(dexItemFactory.createType("Lboobaz;")));
    assertTrue(matcher.test(dexItemFactory.createType("Lboobar;")));
    assertTrue(matcher.test(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontWarnAllImplicitly() {
    testDontXXXAllImplicitly("warn", config -> DontWarnConfiguration.create(config)::matches);
    testDontXXXAllImplicitly("note", config -> config.getDontNotePatterns()::matches);
  }

  @Test
  public void parseAccessFlags() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ACCESS_FLAGS_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    ClassAccessFlags publicAndFinalFlags = ClassAccessFlags.fromSharedAccessFlags(0);
    publicAndFinalFlags.setPublic();
    publicAndFinalFlags.setFinal();
    assertTrue(rule.getClassAccessFlags().containsNone(publicAndFinalFlags));
    assertTrue(rule.getNegatedClassAccessFlags().containsAll(publicAndFinalFlags));
    ClassAccessFlags abstractFlags = ClassAccessFlags.fromSharedAccessFlags(0);
    abstractFlags.setAbstract();
    assertTrue(rule.getClassAccessFlags().containsAll(abstractFlags));
    assertTrue(rule.getNegatedClassAccessFlags().containsNone(abstractFlags));
    for (ProguardMemberRule member : rule.getMemberRules()) {
      if (member.getRuleType() == ProguardMemberType.ALL_FIELDS) {
        FieldAccessFlags publicFlags = FieldAccessFlags.fromSharedAccessFlags(0);
        publicFlags.setPublic();
        assertTrue(member.getAccessFlags().containsAll(publicFlags));
        assertTrue(member.getNegatedAccessFlags().containsNone(publicFlags));
        FieldAccessFlags staticFlags = FieldAccessFlags.fromSharedAccessFlags(0);
        staticFlags.setStatic();
        assertTrue(member.getAccessFlags().containsNone(staticFlags));
        assertTrue(member.getNegatedAccessFlags().containsAll(staticFlags));
      } else {
        assertTrue(member.getRuleType() == ProguardMemberType.ALL_METHODS);

        MethodAccessFlags publicNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
        publicNativeFlags.setPublic();
        publicNativeFlags.setNative();
        assertTrue(member.getAccessFlags().containsAll(publicNativeFlags));
        assertFalse(member.getNegatedAccessFlags().containsNone(publicNativeFlags));

        MethodAccessFlags protectedNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
        protectedNativeFlags.setProtected();
        protectedNativeFlags.setNative();
        assertTrue(member.getAccessFlags().containsAll(protectedNativeFlags));
        assertFalse(member.getNegatedAccessFlags().containsNone(protectedNativeFlags));
      }
    }
  }

  @Test
  public void parseWhyAreYouKeeping() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(WHY_ARE_YOU_KEEPING_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(1, rule.getClassNames().size());
    assertEquals("*", rule.getClassNames().toString());
    assertTrue(rule.getInheritanceIsExtends());
    assertEquals("foo.bar", rule.getInheritanceClassName().toString());
  }

  @Test
  public void parseAssumeNoSideEffects() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
    assertEquals(1, assumeNoSideEffects.size());
    assumeNoSideEffects.get(0).getMemberRules().forEach(rule -> {
      assertFalse(rule.hasReturnValue());
    });
  }

  @Test
  public void parseAssumeNoSideEffectsWithReturnValue() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS_WITH_RETURN_VALUE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
    assertEquals(1, assumeNoSideEffects.size());
    int matches = 0;
    for (ProguardMemberRule rule : assumeNoSideEffects.get(0).getMemberRules()) {
      assertTrue(rule.hasReturnValue());
      if (rule.getName().matches("returnsTrue") || rule.getName().matches("returnsFalse")) {
        assertTrue(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals(rule.getName().matches("returnsTrue"), rule.getReturnValue().getBoolean());
        matches |= 1 << 0;
      } else if (rule.getName().matches("returns1")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        assertEquals(1, rule.getReturnValue().getValueRange().getMin());
        assertEquals(1, rule.getReturnValue().getValueRange().getMax());
        assertEquals(1, rule.getReturnValue().getSingleValue());
        matches |= 1 << 1;
      } else if (rule.getName().matches("returns2To4")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(2, rule.getReturnValue().getValueRange().getMin());
        assertEquals(4, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 2;
      } else if (rule.getName().matches("returns234To567")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(234, rule.getReturnValue().getValueRange().getMin());
        assertEquals(567, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 3;
      } else if (rule.getName().matches("returnsField")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertTrue(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals("com.google.C", rule.getReturnValue().getField().holder.toString());
        assertEquals("int", rule.getReturnValue().getField().type.toString());
        assertEquals("X", rule.getReturnValue().getField().name.toString());
        matches |= 1 << 4;
      } else if (rule.getName().matches("returnsNull")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertTrue(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        matches |= 1 << 5;
      } else {
        fail("Unexpected");
      }
    }
    assertEquals((1 << 6) - 1, matches);
  }

  @Test
  public void parseAssumeValuesWithReturnValue() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_VALUES_WITH_RETURN_VALUE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeValues = parser.getConfig().getRules();
    assertEquals(1, assumeValues.size());
    int matches = 0;
    for (ProguardMemberRule rule : assumeValues.get(0).getMemberRules()) {
      assertTrue(rule.hasReturnValue());
      if (rule.getName().matches("isTrue") || rule.getName().matches("isFalse")) {
        assertTrue(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals(rule.getName().matches("isTrue"), rule.getReturnValue().getBoolean());
        matches |= 1 << 0;
      } else if (rule.getName().matches("is1")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        assertEquals(1, rule.getReturnValue().getValueRange().getMin());
        assertEquals(1, rule.getReturnValue().getValueRange().getMax());
        assertEquals(1, rule.getReturnValue().getSingleValue());
        matches |= 1 << 1;
      } else if (rule.getName().matches("is2To4")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(2, rule.getReturnValue().getValueRange().getMin());
        assertEquals(4, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 2;
      } else if (rule.getName().matches("is234To567")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(234, rule.getReturnValue().getValueRange().getMin());
        assertEquals(567, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 3;
      } else if (rule.getName().matches("isField")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertTrue(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals("com.google.C", rule.getReturnValue().getField().holder.toString());
        assertEquals("int", rule.getReturnValue().getField().type.toString());
        assertEquals("X", rule.getReturnValue().getField().name.toString());
        matches |= 1 << 4;
      } else if (rule.getName().matches("isNull")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertTrue(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        matches |= 1 << 5;
      } else {
        fail("Unexpected");
      }
    }
    assertEquals((1 << 6) - 1, matches);
  }

  @Test
  public void testAdaptClassStrings() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptClassStrings = "-adaptclassstrings !foobar,*bar";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptClassStrings)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertFalse(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testAdaptClassStringsMultiple() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    List<String> configuration1 = ImmutableList.of("-adaptclassstrings foo.**, bar.**");
    List<String> configuration2 =
        ImmutableList.of("-adaptclassstrings foo.**", "-adaptclassstrings bar.**");
    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
      parser.parse(createConfigurationForTesting(configuration));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/Bar;")));
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/bar7Bar;")));
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lbar/Foo;")));
    }
  }

  @Test
  public void testAdaptClassStringsAllExplicitly() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptAll = "-adaptclassstrings *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testAdaptClassStringsAllImplicitly() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptAll = "-adaptclassstrings";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testIdentifierNameString() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    String config1 =
        "-identifiernamestring class a.b.c.*GeneratedClass {\n"
            + "  static java.lang.String CONTAINING_TYPE_*;\n"
            + "}";
    String config2 =
        "-identifiernamestring class x.y.z.ReflectionBasedFactory {\n"
            + "  private static java.lang.reflect.Field field(java.lang.Class,java.lang.String);\n"
            + "}";
    String config3 =
        "-identifiernamestring class * {\n"
            + "  @my.annotations.IdentifierNameString *;\n"
            + "}";
    parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2, config3)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    List<ProguardConfigurationRule> identifierNameStrings = config.getRules();
    assertEquals(3, identifierNameStrings.size());
    assertEquals(1, identifierNameStrings.get(0).getClassNames().size());
    assertEquals(
        "a.b.c.*GeneratedClass",
        identifierNameStrings.get(0).getClassNames().toString());
    identifierNameStrings.get(0).getMemberRules().forEach(memberRule -> {
      assertTrue(memberRule.getRuleType().includesFields());
      assertTrue(memberRule.getName().matches("CONTAINING_TYPE_ABC"));
    });
    assertEquals(1, identifierNameStrings.get(1).getClassNames().size());
    assertEquals(
        "x.y.z.ReflectionBasedFactory",
        identifierNameStrings.get(1).getClassNames().toString());
    identifierNameStrings.get(1).getMemberRules().forEach(memberRule -> {
      assertTrue(memberRule.getRuleType().includesMethods());
      assertTrue(memberRule.getName().matches("field"));
    });
    assertEquals(1, identifierNameStrings.get(2).getClassNames().size());
    assertEquals("*", identifierNameStrings.get(2).getClassNames().toString());
    identifierNameStrings
        .get(2)
        .getMemberRules()
        .forEach(
            memberRule -> {
              assertEquals(ProguardMemberType.ALL, memberRule.getRuleType());
              assertEquals(1, memberRule.getAnnotations().size());
              assertTrue(
                  ListUtils.first(memberRule.getAnnotations())
                      .toString()
                      .endsWith("IdentifierNameString"));
            });
  }

  @Test
  public void parseDontobfuscate() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_OBFUSCATE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isObfuscating());
  }

  @Test
  public void parseRepackageClassesEmpty() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_1));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("", config.getPackagePrefix());
  }

  @Test
  public void parseRepackageClassesNonEmpty() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_2));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("p.q.r", config.getPackagePrefix());
  }

  @Test
  public void parseFlattenPackageHierarchyEmpty() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_3));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("", config.getPackagePrefix());
  }

  @Test
  public void parseFlattenPackageHierarchyNonEmpty() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_4));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("p.q.r", config.getPackagePrefix());
  }

  @Test
  public void flattenPackageHierarchyCannotOverrideRepackageClasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(PACKAGE_OBFUSCATION_5);
    parser.parse(path);
    checkDiagnostics(handler.warnings, path, 6, 1,
        "repackageclasses", "overrides", "flattenpackagehierarchy");
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("top", config.getPackagePrefix());
  }

  @Test
  public void repackageClassesOverridesFlattenPackageHierarchy() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(PACKAGE_OBFUSCATION_6);
    parser.parse(path);
    checkDiagnostics(handler.warnings, path, 6, 1,
        "repackageclasses", "overrides", "flattenpackagehierarchy");
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("top", config.getPackagePrefix());
  }

  @Test
  public void parseApplyMapping() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(APPLY_MAPPING));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.hasApplyMappingFile());
  }

  @Test
  public void parseApplyMappingWithoutFile() {
    Path path = Paths.get(APPLY_MAPPING_WITHOUT_FILE);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(path);
      fail("Expect to fail due to the lack of file name.");
    } catch (RuntimeException e) {
      checkDiagnostics(handler.errors, path, 6, 14, "File name expected");
    }
  }

  @Test
  public void parseAdaptKotlinMetadata() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(ADAPT_KOTLIN_METADATA);
    parser.parse(path);
    checkDiagnostics(handler.infos, path, 1, 1, "Ignoring", "-adaptkotlinmetadata");
  }

  @Test
  public void parseIncluding() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(INCLUDING));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseInvalidIncluding1() {
    Path path = Paths.get(INVALID_INCLUDING_1);
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(path);
      fail();
    } catch (RuntimeException e) {
      checkDiagnostics(handler.errors, path, 6, 10,"does-not-exist.flags");
    }
  }

  @Test
  public void parseInvalidIncluding2() {
    Path path = Paths.get(INVALID_INCLUDING_2);
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(path);
      fail();
    } catch (RuntimeException e) {
      checkDiagnostics(handler.errors, path, 6,2, "does-not-exist.flags");
    }
  }

  @Test
  public void parseLibraryJars() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    if (!ToolHelper.isLinux() && !ToolHelper.isMac()) {
      parser.parse(Paths.get(LIBRARY_JARS_WIN));
    } else {
      parser.parse(Paths.get(LIBRARY_JARS));
    }
    assertEquals(4, parser.getConfig().getLibraryjars().size());
  }

  @Test
  public void parseInvalidFilePattern() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(
          Collections.singletonList("-injars abc.jar(*.zip;*.class)")));
      fail();
    } catch (RuntimeException e) {
      assertEquals(1, handler.errors.size());
    }
  }

  @Test
  public void parseKeepModifiers() {
    for (String before : whiteSpace) {
      for (String after : whiteSpace) {
        reset();
        parseAndVerifyParserEndsCleanly(
            ImmutableList.of(
                "-keep"
                    + before
                    + ","
                    + after
                    + "includedescriptorclasses"
                    + before
                    + ","
                    + after
                    + "allowaccessmodification"
                    + before
                    + ","
                    + after
                    + "allowshrinking"
                    + before
                    + ","
                    + after
                    + "allowobfuscation"
                    + before
                    + ","
                    + after
                    + "allowoptimization "
                    + "class A { *; }"));
      }
    }
  }

  @Test
  public void parseKeepAnnotation() {
    for (String space : whiteSpace) {
      reset();
      parseAndVerifyParserEndsCleanly(ImmutableList.of(
          "-keep @" + space + "interface A"
      ));
    }
  }

  @Test
  public void regress78442725() {
    parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-keep, includedescriptorclasses class in.uncod.android.bypass.Document { *; }",
        "-keep, includedescriptorclasses class in.uncod.android.bypass.Element { *; }"
    ));
  }

  @Test
  public void parseSeeds() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(SEEDS));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintSeeds());
    assertNull(config.getSeedFile());
  }

  @Test
  public void parseSeeds2() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(SEEDS_2));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintSeeds());
    assertNotNull(config.getSeedFile());
  }

  @Test
  public void parseVerbose() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(VERBOSE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isVerbose());
  }

  @Test
  public void parseKeepdirectories() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter, false);
    parser.parse(Paths.get(KEEPDIRECTORIES));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontshrink() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SHRINK));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isShrinking());
  }

  @Test
  public void parseDontSkipNonPublicLibraryClasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontskipnonpubliclibraryclassmembers() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseIdentifiernamestring() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path source = Paths.get(IDENTIFIER_NAME_STRING);
    parser.parse(source);
    verifyParserEndsCleanly();
  }

  @Test
  public void parseOverloadAggressively() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(OVERLOAD_AGGRESIVELY));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontOptimize() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_OPTIMIZE));
    ProguardConfiguration config = parser.getConfig();
    verifyParserEndsCleanly();
    assertFalse(config.isOptimizing());
  }

  @Test
  public void parseDontOptimizeOverridesPasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(DONT_OPTIMIZE_OVERRIDES_PASSES);
    parser.parse(path);
    checkDiagnostics(handler.infos, path, 7, 1, "Ignoring", "-optimizationpasses");
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isOptimizing());
  }

  @Test
  public void parseOptimizationPasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(OPTIMIZATION_PASSES);
    parser.parse(path);
    checkDiagnostics(handler.infos, path, 5, 1, "Ignoring", "-optimizationpasses");
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isOptimizing());
  }

  @Test
  public void parseOptimizationPassesError() {
    Path path = Paths.get(OPTIMIZATION_PASSES_WITHOUT_N);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(path);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, path, 6, 1, "Missing n");
    }
  }

  @Test
  public void parseSkipNonPublicLibraryClasses() {
    testUnsupportedOption("-skipnonpubliclibraryclasses");
  }

  private void testUnsupportedOption(String option) {
    try {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(option)));
      fail("Expect to fail due to unsupported option.");
    } catch (RuntimeException e) {
      checkDiagnostics(handler.errors, null, 1, 1, "Unsupported option", option);
    }
  }

  @Test
  public void parseAndskipSingleArgument() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PARSE_AND_SKIP_SINGLE_ARGUMENT));
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_printconfiguration_noArguments() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-printconfiguration"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertNull(config.getPrintConfigurationFile());
  }

  @Test
  public void parse_printconfiguration_argument() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-printconfiguration file_name"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertEquals("file_name", config.getPrintConfigurationFile().toString());
  }

  @Test
  public void parse_optimizations() throws Exception {
    for (String option :
        ImmutableList.of(
            "-optimizations",
            "-optimizations xxx",
            "-optimizations \"xxx\"",
            "-optimizations 'xxx'",
            "-optimizations     xxx",
            "-optimizations \"    xxx\"",
            "-optimizations '    xxx'",
            "-optimizations xxx/yyy",
            "-optimizations \"xxx/yyy\"",
            "-optimizations 'xxx/yyy'",
            "-optimizations     xxx/yyy",
            "-optimizations \"    xxx/yyy\"",
            "-optimizations '    xxx/yyy'",
            "-optimizations xxx/yyy,zzz*",
            "-optimizations \"xxx/yyy\",\"zzz*\"",
            "-optimizations 'xxx/yyy','zzz*'",
            "-optimizations xxx/yyy  ,  zzz*",
            "-optimizations \"xxx/yyy  \",\"  zzz*\"",
            "-optimizations 'xxx/yyy  ','  zzz*'",
            "-optimizations !xxx",
            "-optimizations \"!xxx\"",
            "-optimizations '!xxx'",
            "-optimizations   !  xxx",
            "-optimizations \"  !  xxx\"",
            "-optimizations '  !  xxx'",
            "-optimizations !xxx,!yyy",
            "-optimizations \"!xxx\",\"!yyy\"",
            "-optimizations '!xxx','!yyy'",
            "-optimizations   !  xxx,  !  yyy",
            "-optimizations \"  !  xxx\", \" !  yyy\"",
            "-optimizations '  !  xxx', ' !  yyy'",
            "-optimizations !code/simplification/advanced,code/simplification/*",
            "-optimizations \"!code/simplification/advanced\",\"code/simplification/*\"",
            "-optimizations '!code/simplification/advanced','code/simplification/*'")) {
      reset();
      Path proguardConfig = writeTextToTempFile(option);
      parser.parse(proguardConfig);
      assertEquals(1, handler.infos.size());
      checkDiagnostics(handler.infos, proguardConfig, 1, 1, "Ignoring", "-optimizations");
    }
  }

  @Test
  public void parse_optimizationpasses() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-optimizations xxx",
              "-optimizationpasses 5",
              "-optimizations yyy"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      assertEquals(3, handler.infos.size());

      checkDiagnostics(handler.infos, 0, proguardConfig, 1, 1, "Ignoring", "-optimizations");
      Position p1 = handler.infos.get(0).getPosition();
      assertTrue(p1 instanceof TextRange);
      TextRange r1 = (TextRange) p1;
      assertEquals(1, r1.getStart().getLine());
      assertEquals(1, r1.getStart().getColumn());
      assertEquals(1, r1.getEnd().getLine());
      assertEquals(15, r1.getEnd().getColumn());

      checkDiagnostics(
          handler.infos, 1, proguardConfig, 2, 1, "Ignoring", "-optimizationpasses");
      Position p2 = handler.infos.get(1).getPosition();
      assertTrue(p2 instanceof TextRange);
      TextRange r2 = (TextRange) p2;
      assertEquals(2, r2.getStart().getLine());
      assertEquals(1, r2.getStart().getColumn());
      assertEquals(2, r2.getEnd().getLine());
      assertEquals(22, r2.getEnd().getColumn());

      checkDiagnostics(handler.infos, 2, proguardConfig, 3, 1, "Ignoring", "-optimizations");
      Position p3 = handler.infos.get(2).getPosition();
      assertTrue(p3 instanceof TextRange);
      TextRange r3 = (TextRange) p3;
      assertEquals(3, r3.getStart().getLine());
      assertEquals(1, r3.getStart().getColumn());
      assertEquals(3, r3.getEnd().getLine());
      assertEquals(15, r3.getEnd().getColumn());
    }
  }

  @Test
  public void parsePrintUsage() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PRINT_USAGE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintUsage());
    assertNull(config.getPrintUsageFile());
  }

  @Test
  public void parsePrintUsageToFile() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PRINT_USAGE_TO_FILE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintUsage());
    assertNotNull(config.getPrintUsageFile());
  }

  @Test
  public void parseTarget() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(TARGET));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseInvalidKeepOption() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keepx public class * {       ",
        "  native <methods>;           ",
        "}                             "
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Unknown option", "-keepx");
    }
  }

  @Test
  public void parseKeepOptionEOF() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        System.lineSeparator(), ImmutableList.of("-keep"), false);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 6,
          "Expected [!]interface|@interface|class|enum");
    }
  }

  @Test
  public void parseInvalidKeepClassOption() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keepclassx public class * {  ",
        "  native <methods>;           ",
        "}                             "
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Unknown option", "-keepclassx");
    }
  }

  @Test
  public void parseCustomFlags() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    // Custom Proguard flags -runtype and -laststageoutput are ignored.
    Path proguardConfig = writeTextToTempFile(
        "-runtype FINAL                    ",
        "-laststageoutput /some/file/name  "
    );
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void testRenameSourceFileAttribute() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-renamesourcefileattribute PG",
              "-keepattributes SourceFile,SourceDir"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfigRawForTesting();
      assertEquals("PG", config.getRenameSourceFileAttribute());
      assertTrue(config.getKeepAttributes().sourceFile);
      assertTrue(config.getKeepAttributes().sourceDir);
    }
  }

  @Test
  public void testRenameSourceFileAttribute_empty() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-renamesourcefileattribute",
              "-keepattributes SourceFile"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfigRawForTesting();
      assertEquals("", config.getRenameSourceFileAttribute());
      assertTrue(config.getKeepAttributes().sourceFile);
      assertFalse(config.getKeepAttributes().sourceDir);
    }
  }

  @Test
  public void testRenameSourceFileAttribute_qouted() throws Exception {
    for (String lineSeparator : lineSeparators) {
      for (Character quote : quotes) {
        reset();
        Path proguardConfig = writeTextToTempFile(lineSeparator,
            ImmutableList.of(
                "-renamesourcefileattribute " + quote + "PG" + quote,
                "-keepattributes SourceFile"));
        ProguardConfigurationParser parser =
            new ProguardConfigurationParser(new DexItemFactory(), reporter);
        parser.parse(proguardConfig);
        verifyParserEndsCleanly();
        ProguardConfiguration config = parser.getConfigRawForTesting();
        assertEquals("PG", config.getRenameSourceFileAttribute());
        assertTrue(config.getKeepAttributes().sourceFile);
        assertFalse(config.getKeepAttributes().sourceDir);
      }
    }
  }

  @Test
  public void testRenameSourceFileAttribute_qouted_empty() throws Exception {
    for (String lineSeparator : lineSeparators) {
      for (Character quote : quotes) {
        reset();
        Path proguardConfig = writeTextToTempFile(lineSeparator,
            ImmutableList.of(
                "-renamesourcefileattribute " + quote + quote,
                "-keepattributes SourceFile"));
        ProguardConfigurationParser parser =
            new ProguardConfigurationParser(new DexItemFactory(), reporter);
        parser.parse(proguardConfig);
        verifyParserEndsCleanly();
        ProguardConfiguration config = parser.getConfigRawForTesting();
        assertEquals("", config.getRenameSourceFileAttribute());
        assertTrue(config.getKeepAttributes().sourceFile);
        assertFalse(config.getKeepAttributes().sourceDir);
      }
    }
  }

  private void testKeepattributes(List<String> expected, String config) {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
    verifyParserEndsCleanly();
    assertEquals(
        ProguardKeepAttributes.fromPatterns(expected),
        parser.getConfigRawForTesting().getKeepAttributes());
  }

  @Test
  public void parseKeepattributes() {
    List<String> xxxYYY = ImmutableList.of("xxx", "yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx,yyy");
    testKeepattributes(xxxYYY, "-keepattributes \"xxx\",\"yyy\"");
    testKeepattributes(xxxYYY, "-keepattributes 'xxx','yyy'");
    testKeepattributes(xxxYYY, "-keepattributes xxx, yyy");
    testKeepattributes(xxxYYY, "-keepattributes \"xxx\", \"yyy\"");
    testKeepattributes(xxxYYY, "-keepattributes 'xxx', 'yyy'");
    testKeepattributes(xxxYYY, "-keepattributes xxx ,yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx   ,   yyy");
    testKeepattributes(xxxYYY, "-keepattributes \"xxx\"   ,   \"yyy\"");
    testKeepattributes(xxxYYY, "-keepattributes 'xxx'   ,   'yyy'");
    testKeepattributes(xxxYYY, "-keepattributes       xxx   ,   yyy     ");
    testKeepattributes(xxxYYY, "-keepattributes       \"xxx\"   ,   \"yyy\"     ");
    testKeepattributes(xxxYYY, "-keepattributes       'xxx'   ,   'yyy'     ");
    testKeepattributes(xxxYYY, "-keepattributes       xxx   ,   yyy     \n");
    testKeepattributes(xxxYYY, "-keepattributes       \"xxx\"   ,   \"yyy\"     \n");
    testKeepattributes(xxxYYY, "-keepattributes       'xxx'   ,   'yyy'     \n");
    String config =
        "-keepattributes Exceptions,InnerClasses,Signature,Deprecated,\n"
            + "          SourceFile,LineNumberTable,*Annotation*,EnclosingMethod\n";
    List<String> expected = ImmutableList.of(
        "Exceptions", "InnerClasses", "Signature", "Deprecated",
        "SourceFile", "LineNumberTable", "*Annotation*", "EnclosingMethod");
    testKeepattributes(expected, config);
    config =
        "-keepattributes \"Exceptions\",\"InnerClasses\",\"Signature\",\"Deprecated\",\n"
            + "          \"SourceFile\",\"LineNumberTable\",\"*Annotation*\",\"EnclosingMethod\"\n";
    testKeepattributes(expected, config);
    config =
        "-keepattributes 'Exceptions','InnerClasses','Signature','Deprecated',\n"
            + "          'SourceFile','LineNumberTable','*Annotation*','EnclosingMethod'\n";
    testKeepattributes(expected, config);
  }

  private void testKeeppackagenames(ProguardPackageNameList expected, String config) {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
    verifyParserEndsCleanly();
    assertEquals(expected, parser.getConfigRawForTesting().getKeepPackageNamesPatterns());
  }

  @Test
  public void parseKeeppackagenames() {
    ProguardPackageNameList xxxYYY =
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("xxx"))
            .addPackageName(false, new ProguardPackageMatcher("yyy"))
            .build();
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx,yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx, yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx ,yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx   ,   yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames       xxx   ,   yyy     ");
    testKeeppackagenames(xxxYYY, "-keeppackagenames       xxx   ,   yyy     \n");
    testKeeppackagenames(xxxYYY, "-keeppackagenames \"xxx\",\"yyy\"");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("com.**"))
            .addPackageName(false, new ProguardPackageMatcher("org.*"))
            .build(),
        "-keeppackagenames com.**, org.*");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("c?m.**"))
            .addPackageName(false, new ProguardPackageMatcher("?r?.*"))
            .build(),
        "-keeppackagenames c?m.**, ?r?.*");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(true, new ProguardPackageMatcher("c?m.**"))
            .addPackageName(true, new ProguardPackageMatcher("?r?.*"))
            .build(),
        "-keeppackagenames !c?m.**, !?r?.*");
  }

  @Test
  public void parseInvalidKeepattributes_brokenList() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of("-keepattributes xxx,")));
      fail();
    } catch (RuntimeException e) {
      assertTrue(
          handler.errors.get(0).getDiagnosticMessage().contains("Expected list element at "));
    }
  }

  @Test
  public void parseUseUniqueClassMemberNames() throws IOException {
    Path proguardConfig = writeTextToTempFile("-useuniqueclassmembernames");
    new ProguardConfigurationParser(new DexItemFactory(), reporter).parse(proguardConfig);
    checkDiagnostics(
        handler.warnings, proguardConfig, 1, 1, "Ignoring", "-useuniqueclassmembernames");
  }

  @Test
  public void parseKeepParameterNames() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of(
          "-keepparameternames"
      )));
      parser.getConfig();
      fail();
    } catch (AbortException e) {
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains(
          "-keepparameternames is not supported"));
    }
  }

  @Test
  public void parseKeepParameterNamesWithoutMinification() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-keepparameternames",
        "-dontobfuscate"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isKeepParameterNames());

    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-keepparameternames"
    )));
    verifyParserEndsCleanly();
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-dontobfuscate"
    )));
    verifyParserEndsCleanly();
    config = parser.getConfig();
    assertTrue(config.isKeepParameterNames());
  }

  @Test
  public void parseShortLine() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(Collections.singletonList("-")));
      fail();
    } catch (AbortException e) {
      assertEquals(1, handler.errors.size());
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains("-"));
    }
  }

  @Test
  public void parseNoLocals() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(Collections.singletonList("--no-locals")));
      fail();
    } catch (AbortException e) {

      assertEquals(1, handler.errors.size());
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains("--no-locals"));
    }
  }

  private void checkFileFilterMatchAnything(ProguardPathFilter filter) {
    assertTrue(filter.matches("x"));
    assertTrue(filter.matches("x/y"));
    assertTrue(filter.matches("x/y/x"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments1() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames",
        "-adaptresourcefilecontents",
        "-keepdirectories"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments2() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-keepdirectories",
        "-adaptresourcefilenames",
        "-adaptresourcefilecontents"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments3() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilecontents",
        "-keepdirectories",
        "-adaptresourcefilenames"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  private String FILE_FILTER_SINGLE = "xxx/*";

  private void checkFileFilterSingle(ProguardPathFilter filter) {
    assertTrue(filter.matches("xxx/x"));
    assertTrue(filter.matches("xxx/"));
    assertFalse(filter.matches("xxx/yyy/z"));
    assertFalse(filter.matches("xxx"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_singleArgument() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames " + FILE_FILTER_SINGLE,
        "-adaptresourcefilecontents " + FILE_FILTER_SINGLE,
        "-keepdirectories " + FILE_FILTER_SINGLE
    ));
    checkFileFilterSingle(config.getAdaptResourceFilenames());
    checkFileFilterSingle(config.getAdaptResourceFileContents());
    checkFileFilterSingle(config.getKeepDirectories());
  }

  private String FILE_FILTER_MULTIPLE =
      "xxx/*, !**.gif  ,images/**  ,  com/myapp/**/*.xml,com/mylib/*/*.xml";

  private void checkFileFilterMultiple(ProguardPathFilter filter) {
    assertTrue(filter.matches("xxx/x"));
    assertTrue(filter.matches("xxx/x.gif"));
    assertTrue(filter.matches("images/x.jpg"));
    assertTrue(filter.matches("images/xxx/x.jpg"));
    assertTrue(filter.matches("com/myapp/package1/x.xml"));
    assertTrue(filter.matches("com/myapp/package1/package2/x.xml"));
    assertTrue(filter.matches("com/mylib/package1/x.xml"));
    assertFalse(filter.matches("x.gif"));
    assertFalse(filter.matches("images/x.gif"));
    assertFalse(filter.matches("images/xxx/y.gif"));
    assertFalse(filter.matches("images/xxx/yyy/z.gif"));
    assertFalse(filter.matches("com/myapp/package1/x.jpg"));
    assertFalse(filter.matches("com/myapp/package1/package2/x.jpg"));
    assertFalse(filter.matches("com/mylib/package1/package2/x.xml"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_multipleArgument() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames " + FILE_FILTER_MULTIPLE,
        "-adaptresourcefilecontents " + FILE_FILTER_MULTIPLE,
        "-keepdirectories " + FILE_FILTER_MULTIPLE
    ));
    checkFileFilterMultiple(config.getAdaptResourceFilenames());
    checkFileFilterMultiple(config.getAdaptResourceFileContents());
    checkFileFilterMultiple(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_leadingComma() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " ,")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (RuntimeException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 2, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_emptyListElement() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,,yyy")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (RuntimeException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 6, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_trailingComma() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (RuntimeException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 6, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_testInlineOptions() {
    List<String> options = ImmutableList.of(
        "-neverinline", "-forceinline");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " class A { *; }")));
        fail("Expect to fail due to testing option being turned off.");
      } catch (AbortException e) {
        assertEquals(1, handler.errors.size());
        checkDiagnostics(handler.errors, 0, null, 1, 1, "Unknown option \"" + option + "\"");
      }
    }
  }

  @Test
  public void parse_if() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter",
        "-keep class A",
        "-if   class **$$InjectAdapter",
        "-keep class B",
        "-if   class **$$StaticInjection",
        "-keep class C",
        "-keepnames class dagger.Lazy"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    // Three -if rules and one independent -keepnames
    assertEquals(4, config.getRules().size());
    long ifCount =
        config.getRules().stream().filter(rule -> rule instanceof ProguardIfRule).count();
    assertEquals(3, ifCount);
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**$$ModuleAdapter", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("A", if0.subsequentRule.getClassNames().toString());
    ProguardIfRule if1 = (ProguardIfRule) config.getRules().get(1);
    assertEquals("**$$InjectAdapter", if1.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if1.subsequentRule.getType());
    assertEquals("B", if1.subsequentRule.getClassNames().toString());
    ProguardIfRule if2 = (ProguardIfRule) config.getRules().get(2);
    assertEquals("**$$StaticInjection", if2.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if2.subsequentRule.getType());
    assertEquals("C", if2.subsequentRule.getClassNames().toString());
  }

  @Test
  public void parse_if_nthWildcard() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **$D<2>"  // <2> corresponds to the 2nd ** in -if rule.
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**$R**", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**$D<2>", if0.subsequentRule.getClassNames().toString());

    // Test <2> literally refers to the second wildcard in the rule.
    Iterator<ProguardWildcard> it1 = if0.getClassNames().getWildcards().iterator();
    it1.next();
    ProguardWildcard secondWildcardInIf = it1.next();
    assertTrue(secondWildcardInIf.isPattern());
    Iterator<ProguardWildcard> it2 = if0.subsequentRule.getWildcards().iterator();
    it2.next();
    ProguardWildcard backReference = it2.next();
    assertTrue(backReference.isBackReference());
    assertSame(secondWildcardInIf.asPattern(), backReference.asBackReference().reference);

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_fieldType() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R*",
        "-keep class **.D<2> {",
        "  <1>.F<2> fld;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**.R*", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**.D<2>", if0.subsequentRule.getClassNames().toString());
    assertEquals(1, if0.subsequentRule.getMemberRules().size());
    ProguardMemberRule fieldRule = if0.subsequentRule.getMemberRules().get(0);
    assertEquals("<1>.F<2>", fieldRule.getType().toString());

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_fieldName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R*",
        "-keep class **.D<2> {",
        "  java.lang.String fld<2>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**.R*", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**.D<2>", if0.subsequentRule.getClassNames().toString());
    assertEquals(1, if0.subsequentRule.getMemberRules().size());
    ProguardMemberRule fieldRule = if0.subsequentRule.getMemberRules().get(0);
    assertEquals("fld<2>", fieldRule.getName().toString());

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_returnType() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R*",
        "-keep class **.D<2> {",
        "  <1>.M<2> mtd(...);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**.R*", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**.D<2>", if0.subsequentRule.getClassNames().toString());
    assertEquals(1, if0.subsequentRule.getMemberRules().size());
    ProguardMemberRule methodRule = if0.subsequentRule.getMemberRules().get(0);
    assertEquals("<1>.M<2>", methodRule.getType().toString());

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_init() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R* {",
        "  void *(...);",
        "}",
        "-keep class **.D<2> {",
        "  <3>(...);",
        "}"
    );
    try {
      parser.parse(proguardConfig);
      fail("Expect to fail due to unsupported constructor name pattern.");
    } catch (RuntimeException e) {
      checkDiagnostics(
          handler.errors, proguardConfig, 5, 3, "Unexpected character", "method name");
    }

    verifyFailWithProguard6(proguardConfig, "Expecting type and name instead of just '<3>'");
  }

  @Test
  public void parse_if_methodName_void() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R* {",
        "  void *(...);",
        "}",
        "-keep class **.D<2> {",
        "  void <3>_delegate(...);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**.R*", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**.D<2>", if0.subsequentRule.getClassNames().toString());
    assertEquals(1, if0.subsequentRule.getMemberRules().size());
    ProguardMemberRule methodRule = if0.subsequentRule.getMemberRules().get(0);
    assertEquals("<3>_delegate", methodRule.getName().toString());

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_methodName_class() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R* {",
        "  ** *(...);",
        "}",
        "-keep class **.D<2> {",
        "  <3> <4>(...);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**.R*", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**.D<2>", if0.subsequentRule.getClassNames().toString());
    assertEquals(1, if0.subsequentRule.getMemberRules().size());
    ProguardMemberRule methodRule = if0.subsequentRule.getMemberRules().get(0);
    assertEquals("<3>", methodRule.getType().toString());
    assertEquals("<4>", methodRule.getName().toString());

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nthWildcard_notNumber_literalN() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<n>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Use of generics not allowed for java type");
    }
    verifyFailWithProguard6(proguardConfig, "Use of generics not allowed for java type");
  }

  @Test
  public void parse_if_nthWildcard_notNumber_asterisk_inClassName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<*>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Use of generics not allowed for java type");
    }
    verifyFailWithProguard6(proguardConfig, "Use of generics not allowed for java type");
  }

  @Test
  public void parse_if_nthWildcard_notNumber_asterisk_inMemberName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<*>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nestedAngularBrackets_inMemberName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<<*>>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 3, 7, "The field name \"id<<*>>\" is");

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nestedAngularBrackets_outOfRange() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<<4>>;",  // There are 3 previous referable wildcards in this rule.
        "}"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 4, 2,
          "Wildcard", "<4>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (4,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_tooSmall() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<0>"  // nth wildcard starts from 1, not 0.
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Wildcard", "<0>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (0,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_tooBig() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<4>"  // There are 3 previous wildcards in this rule.
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 3, 1,
          "Wildcard", "<4>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (4,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_inIf() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R<2>", // There is only one wildcard prior to <2>.
        "-keep class **D<2>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 3, 1,
          "Wildcard", "<2>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (2,");
  }

  @Test
  public void parse_if_nthWildcard_not_referable() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R {",
        "  int id?;",
        "}",
        "-keep class <1>.D<2> {",
        "  int id<3>;",  // Only ** and ? are referable wildcards.
        "}"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 6, 2,
          "Wildcard", "<3>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (3,");
  }

  @Test
  public void parse_if_nthWildcard_not_referable_after_backreference() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.*User {",
        "  @<1>.*<2> <methods>;", // As back reference starts, * in the middle is not referable.
        "}",
        "-keep @interface <1>.<3><2>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 5, 1,
          "Wildcard", "<3>", "invalid");
    }
    verifyFailWithProguard6(
        proguardConfig, "Use of generics not allowed for java type at '<1>.<3><2>'");
  }

  @Test
  public void parse_if_if() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter",
        "-if   class **$$InjectAdapter"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Expecting", "'-keep'", "after", "'-if'");
    }
    verifyFailWithProguard6(proguardConfig, "Expecting '-keep' option after '-if' option");
  }

  @Test
  public void parse_if_end() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Expecting", "'-keep'", "after", "'-if'");
    }
    verifyFailWithProguard6(proguardConfig, "Expecting '-keep' option after '-if' option");
  }

  @Test
  public void parse_assumenoexternalsideeffects() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoexternalsideeffects class java.lang.StringBuilder {",
        "  public java.lang.StringBuilder();",
        "  public java.lang.StringBuilder(int);",
        "  public java.lang.StringBuilder(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.Object);",
        "  public java.lang.StringBuilder append(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.StringBuffer);",
        "  public java.lang.StringBuilder append(char[]);",
        "  public java.lang.StringBuilder append(char[], int, int);",
        "  public java.lang.StringBuilder append(boolean);",
        "  public java.lang.StringBuilder append(char);",
        "  public java.lang.StringBuilder append(int);",
        "  public java.lang.StringBuilder append(long);",
        "  public java.lang.StringBuilder append(float);",
        "  public java.lang.StringBuilder append(double);",
        "  public java.lang.String toString();",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoexternalsideeffects");
  }

  @Test
  public void parse_assumenoescapingparameters() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoescapingparameters class java.lang.System {",
        "  public static void arraycopy(java.lang.Object, int, java.lang.Object, int, int);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoescapingparameters");
  }

  @Test
  public void parse_assumenoexternalreturnvalues() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoexternalreturnvalues class java.lang.StringBuilder {",
        "  public java.lang.StringBuilder append(java.lang.Object);",
        "  public java.lang.StringBuilder append(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.StringBuffer);",
        "  public java.lang.StringBuilder append(char[]);",
        "  public java.lang.StringBuilder append(char[], int, int);",
        "  public java.lang.StringBuilder append(boolean);",
        "  public java.lang.StringBuilder append(char);",
        "  public java.lang.StringBuilder append(int);",
        "  public java.lang.StringBuilder append(long);",
        "  public java.lang.StringBuilder append(float);",
        "  public java.lang.StringBuilder append(double);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoexternalreturnvalues");
  }

  @Test
  public void parse_dump_withoutFile() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-dump"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-dump");
  }

  @Test
  public void parse_dump_withFile() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-dump class_files.txt"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-dump");
  }

  @Test
  public void parse_android() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-android"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_mergeinterfaceaggressively() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-mergeinterfacesaggressively"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_addconfigurationdebugging() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-addconfigurationdebugging"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    assertTrue(parser.getConfig().isConfigurationDebugging());
  }

  @Test
  public void parse_regress74508478() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keep class A {",
        "  A <fields>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 2, 5, "The field name \"<fields>\" is");
    verifyWithProguard(proguardConfig);
  }

  @Test
  public void parse_regress79925760() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keep public @ interface test.MyAnnotation"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();

    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardKeepRule rule = (ProguardKeepRule) config.getRules().get(0);
    assertEquals(ProguardClassType.ANNOTATION_INTERFACE, rule.getClassType());

    verifyWithProguard(proguardConfig);
  }

  @Test
  public void parse_regress110021323() throws Exception {
    Path proguardConfig = writeTextToTempFile(
      "-keepclassmembernames class A {",
      "  <public methods>;",
      "  <public fields>;",
      "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    assertEquals(4, handler.warnings.size());
    checkDiagnostics(handler.warnings, 0, proguardConfig, 2, 3, "The type \"<public\" is");
    checkDiagnostics(handler.warnings, 1, proguardConfig, 2, 11, "The field name \"methods>\" is");
    checkDiagnostics(handler.warnings, 2, proguardConfig, 3, 3, "The type \"<public\" is");
    checkDiagnostics(handler.warnings, 3, proguardConfig, 3, 11, "The field name \"fields>\" is");

    verifyWithProguard(proguardConfig);
  }

  private void checkRulesSourceSnippet(List<String> sourceRules) {
    checkRulesSourceSnippet(sourceRules, sourceRules, false);
  }

  private void checkRulesSourceSnippet(
      List<String> sourceRules, List<String> expected, boolean trim) {
    reset();
    parser.parse(createConfigurationForTesting(sourceRules));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(expected.size(), rules.size());
    for (int i = 0; i < expected.size(); i++) {
      assertEquals(trim ? expected.get(i).trim() : expected.get(i), rules.get(i).getSource());
    }
  }

  @Test
  public void accurateSourceSnippet() {
    String rule1 = String.join(System.lineSeparator(), ImmutableList.of("-keep class A  {  *;  }"));
    String rule2 =
        String.join(System.lineSeparator(), ImmutableList.of("-keep class A  ", "{  *;  ", "}"));
    String rule3 =
        String.join(
            System.lineSeparator(), ImmutableList.of("-checkdiscard class A  ", "{  *;  ", "}"));

    checkRulesSourceSnippet(ImmutableList.of(rule1));
    checkRulesSourceSnippet(ImmutableList.of(rule2));
    checkRulesSourceSnippet(ImmutableList.of(rule3));
    checkRulesSourceSnippet(
        ImmutableList.of(rule1, rule2, rule3), ImmutableList.of(rule1, rule3), false);
  }

  @Test
  public void accurateSourceSnippet_withWhitespace() {
    Iterable<String> nonEmptyWhiteSpace =
        whiteSpace.stream().filter(space -> !space.equals("")).collect(Collectors.toList());
    for (String space : nonEmptyWhiteSpace) {
      String rule1 =
          String.join(System.lineSeparator(), ImmutableList.of("  -keep class A  {  *;  }  "))
              .replaceAll(" {2}", space);
      String rule2 =
          String.join(
                  System.lineSeparator(), ImmutableList.of("-keep class A  ", "{  *;  ", "}", ""))
              .replaceAll(" {2}", space);

      checkRulesSourceSnippet(ImmutableList.of(rule1), ImmutableList.of(rule1), true);
      checkRulesSourceSnippet(
          ImmutableList.of("#Test comment ", "", rule1), ImmutableList.of(rule1), true);
      checkRulesSourceSnippet(
          ImmutableList.of("#Test comment ", "", rule1, "", "#Test comment ", ""),
          ImmutableList.of(rule1),
          true);
      checkRulesSourceSnippet(ImmutableList.of(rule2), ImmutableList.of(rule2), true);
      checkRulesSourceSnippet(ImmutableList.of(rule1, rule2), ImmutableList.of(rule1), true);
      checkRulesSourceSnippet(
          ImmutableList.of(
              "#Test comment ", "", rule1, " ", "#Test comment ", "", rule2, "#Test comment ", ""),
          ImmutableList.of(rule1),
          true);
    }
  }

  @Test
  public void parseOptionalArgumentsFollowedByArobaseInclude() throws Exception {
    Path includeFile = writeTextToTempFile(
        "-renamesourcefileattribute SRC"
    );
    Path proguardConfig = writeTextToTempFile(
        "-printconfiguration",
        "@" + includeFile.toAbsolutePath()
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertNull(config.getPrintConfigurationFile());
    assertEquals("SRC", config.getRenameSourceFileAttribute());
  }

  private void testFlagWithFilenames(
      String flag,
      List<String> values,
      Function<ProguardConfiguration, Path> extractPath,
      BiConsumer<String, String> check) {
    for (String value : values) {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      check.accept(value, extractPath.apply(config).toString());
    }
  }

  @Test
  public void parseSingleFileNameOptions() {
    List<String> fileNames = ImmutableList.of(
        "xxx",
        "xxx" + File.pathSeparatorChar + "xxx");
    testFlagWithFilenames("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, Assert::assertEquals);
    testFlagWithFilenames("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, Assert::assertEquals);
    testFlagWithFilenames("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, Assert::assertEquals);
    testFlagWithFilenames("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, Assert::assertEquals);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenames("-basedirectory", fileNames, (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenames("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, Assert::assertEquals);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  private void checkQuotedFileName(String quoted, String parsed) {
    assertTrue(quoted.charAt(0) == '\'' || quoted.charAt(0) == '\"');
    assertTrue(quoted.charAt(0) == quoted.charAt(quoted.length() - 1));
    assertEquals(quoted.substring(1, quoted.length() - 1), parsed);
  }

  @Test
  public void parseSingleFleNameOptionsQuoted() {
    List<String> fileNames = new ArrayList<>();
    fileNames.add("'xxx'");
    fileNames.add("\"xxx\"");
    fileNames.add("'xxx xxx\'");
    fileNames.add("\"xxx xxx\"");
    fileNames.add("\"'xxx'\"");
    fileNames.add("\" xxx xxx (\"");
    fileNames.add("' xxx xxx ('");
    // Java Path implementation on Windows does not allow " or trailing
    // spaces in file names.
    if (!ToolHelper.isWindows()) {
      fileNames.add("'\"xxx\"'");
      fileNames.add("\" xxx xxx \"");
      fileNames.add("' xxx xxx '");
    }
    testFlagWithFilenames("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, this::checkQuotedFileName);
    testFlagWithFilenames("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, this::checkQuotedFileName);
    testFlagWithFilenames("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, this::checkQuotedFileName);
    testFlagWithFilenames("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, this::checkQuotedFileName);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenames("-basedirectory", fileNames, (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenames("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, this::checkQuotedFileName);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  private void testFlagWithFilenamesWithSystemProperty(
      String flag,
      List<String> values,
      Function<ProguardConfiguration, Path> extractPath,
      BiConsumer<String, String> check) {
    for (String value : values) {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      Path path = extractPath.apply(config);
      check.accept(
          value
              .replaceAll("<java.home>", Matcher.quoteReplacement(System.getProperty("java.home")))
              .replaceAll("<user.home>", Matcher.quoteReplacement(System.getProperty("user.home"))),
          path.toString());
    }
  }

  @Test
  public void parseFlagWithFilenamesWithSystemProperty() {
    List<String> fileNames = new ArrayList<>();
    fileNames.add("<java.home>");
    fileNames.add("<user.home>");
    if (!ToolHelper.isWindows()) {
      // If the system property has e.g. C:\ prefix, then these file names
      // will not work on Windows.
      fileNames.add("xxx<java.home>");
      fileNames.add("xxx<user.home>");
    }
    fileNames.add("<java.home>" +  File.separatorChar + "xxx");
    fileNames.add("<user.home>" +  File.separatorChar + "xxx");
    if (!ToolHelper.isWindows()) {
      fileNames.add("xxx<java.home>/xxx");
      fileNames.add("xxx<user.home>/xxx");
      fileNames.add("<java.home><java.home>");
      fileNames.add("<user.home><user.home>");
      fileNames.add("<java.home><user.home>");
      fileNames.add("<user.home><java.home>");
      // The characters < and > are not allowed in paths on Windows.
      fileNames.add(">");
      fileNames.add("<");
      fileNames.add("<<<<");
      fileNames.add("><");
      fileNames.add(">><<");
    }
    testFlagWithFilenamesWithSystemProperty("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, Assert::assertEquals);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenamesWithSystemProperty("-basedirectory", fileNames,
        (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenamesWithSystemProperty("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, Assert::assertEquals);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  @Test
  public void pasteFlagWithFilenamesWithSystemProperty_empty() {
    try {
      parser.parse(createConfigurationForTesting(ImmutableList.of("-printusage <>")));
      fail("Expect to fail due to the lack of file name.");
    } catch (RuntimeException e) {
      checkDiagnostics(handler.errors, null, 1, 15, "Value of system property '' not found");
    }
  }

  @Test
  public void pasteFlagWithFilenamesWithSystemProperty_notFound() {
    // Find a non-existent system property.
    String property = "x";
    while (System.getProperty(property) != null) {
      property = property + "x";
    }

    try {
      parser.parse(
          createConfigurationForTesting(ImmutableList.of("-printusage <" + property + ">")));
      fail("Expect to fail due to the lack of file name.");
    } catch (RuntimeException e) {
      checkDiagnostics(
          handler.errors, null, 1, 16, "Value of system property '" + property + "' not found");
    }
  }

  private void testFlagWithQuotedValue(
      String flag, String value, BiConsumer<PackageObfuscationMode, String> checker) {
    reset();
    parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    checker.accept(config.getPackageObfuscationMode(), config.getPackagePrefix());
  }

  private void testFlagWithQuotedValueFailure(
      String flag, String value, Supplier<Void> checker) {
    try {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      fail("Expect to fail due to un-closed quote.");
    } catch (RuntimeException e) {
      checker.get();
    }
  }

  @Test
  public void parseRepackageclassesQuotes() {
    testFlagWithQuotedValue("-repackageclasses", "'xxx'", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.REPACKAGE, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValue("-repackageclasses", "\"xxx\"", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.REPACKAGE, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "'xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "'xxx\"", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "\"xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "\"xxx'", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
  }

  @Test
  public void parseFlattenpackagehierarchyQuotes() {
    testFlagWithQuotedValue("-flattenpackagehierarchy", "'xxx'", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.FLATTEN, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValue("-flattenpackagehierarchy", "\"xxx\"", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.FLATTEN, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "'xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "'xxx\"", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "\"xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "\"xxx'", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
  }

  private ProguardConfiguration parseAndVerifyParserEndsCleanly(List<String> config) {
    parser.parse(createConfigurationForTesting(config));
    verifyParserEndsCleanly();
    return parser.getConfig();
  }

  private ProguardConfiguration parseAndVerifyParserEndsCleanly(Path config) {
    parser.parse(config);
    verifyParserEndsCleanly();
    return parser.getConfig();
  }

  private void verifyParserEndsCleanly() {
    assertEquals(0, handler.infos.size());
    assertEquals(0, handler.warnings.size());
    assertEquals(0, handler.errors.size());
  }

  private void verifyWithProguard(Path proguardConfig) throws Exception {
    if (isRunProguard()) {
      // Add a keep rule for the test class as Proguard will fail if the resulting output jar is
      // empty
      Class classToKeepForTest = EmptyMainClassForProguardTests.class;
      Path additionalProguardConfig = writeTextToTempFile(
          "-keep class " + classToKeepForTest.getCanonicalName() + " {",
          "  public static void main(java.lang.String[]);",
          "}"
      );
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguardRaw(
          jarTestClasses(ImmutableList.of(classToKeepForTest)),
          proguardedJar,
          ImmutableList.of(proguardConfig, additionalProguardConfig),
          null);
      assertEquals(0, result.exitCode);
      CodeInspector proguardInspector = new CodeInspector(readJar(proguardedJar));
      assertEquals(1, proguardInspector.allClasses().size());
    }
  }

  private void verifyWithProguard6(Path proguardConfig) throws Exception {
    if (isRunProguard()) {
      // Add a keep rule for the test class as Proguard will fail if the resulting output jar is
      // empty
      Class classToKeepForTest = EmptyMainClassForProguardTests.class;
      Path additionalProguardConfig = writeTextToTempFile(
          "-keep class " + classToKeepForTest.getCanonicalName() + " {",
          "  public static void main(java.lang.String[]);",
          "}"
      );
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguard6Raw(
          jarTestClasses(ImmutableList.of(classToKeepForTest)),
          proguardedJar,
          ImmutableList.of(proguardConfig, additionalProguardConfig),
          null);
      assertEquals(0, result.exitCode);
      CodeInspector proguardInspector = new CodeInspector(readJar(proguardedJar));
      assertEquals(1, proguardInspector.allClasses().size());
    }
  }

  private void verifyFailWithProguard6(Path proguardConfig, String expectedMessage)
      throws Exception{
    if (isRunProguard()) {
      // No need for a keep rule for this class, as we are expecting Proguard to fail with the
      // specified message.
      Class classForTest = EmptyMainClassForProguardTests.class;
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguard6Raw(
          jarTestClasses(ImmutableList.of(classForTest)), proguardedJar, proguardConfig, null);
      assertNotEquals(0, result.exitCode);
      assertThat(result.stderr, containsString(expectedMessage));
    }
  }

  @Test
  public void b124181032() {
    // Test spaces and quotes in class name list.
    ProguardConfigurationParser parser;
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(
        createConfigurationForTesting(
            ImmutableList.of(
                "-keepclassmembers class \"a.b.c.**\" ,"
                    + " !**d , '!**e' , \"!**f\" , g , 'h' , \"i\" { ",
                "<fields>;",
                "<init>();",
                "}")));
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(ProguardKeepRuleType.KEEP_CLASS_MEMBERS.toString(), rule.typeString());
    assertEquals("a.b.c.**,!**d,!**e,!**f,g,h,i", rule.getClassNames().toString());
  }

  @Test
  public void directiveAfterRepackagingRuleTest() {
    List<PackageObfuscationMode> packageObfuscationModes =
        ImmutableList.of(PackageObfuscationMode.FLATTEN, PackageObfuscationMode.REPACKAGE);
    for (PackageObfuscationMode packageObfuscationMode : packageObfuscationModes) {
      String directive =
          packageObfuscationMode == PackageObfuscationMode.FLATTEN
              ? "-flattenpackagehierarchy"
              : "-repackageclasses";
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of(directive + " -keep class *")));
      ProguardConfiguration configuration = parser.getConfig();
      assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
      assertEquals("", configuration.getPackagePrefix());

      List<ProguardConfigurationRule> rules = configuration.getRules();
      assertEquals(1, rules.size());

      ProguardConfigurationRule rule = rules.get(0);
      assertEquals(ProguardKeepRuleType.KEEP.toString(), rule.typeString());
      assertEquals("*", rule.getClassNames().toString());
    }
  }

  @Test
  public void arobaseAfterRepackagingRuleTest() throws IOException {
    Path includeFile = writeTextToTempFile("-keep class *");
    List<PackageObfuscationMode> packageObfuscationModes =
        ImmutableList.of(PackageObfuscationMode.FLATTEN, PackageObfuscationMode.REPACKAGE);
    for (PackageObfuscationMode packageObfuscationMode : packageObfuscationModes) {
      String directive =
          packageObfuscationMode == PackageObfuscationMode.FLATTEN
              ? "-flattenpackagehierarchy"
              : "-repackageclasses";
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(
          createConfigurationForTesting(
              ImmutableList.of(directive + " @" + includeFile.toAbsolutePath())));
      ProguardConfiguration configuration = parser.getConfig();
      assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
      assertEquals("", configuration.getPackagePrefix());

      List<ProguardConfigurationRule> rules = configuration.getRules();
      assertEquals(1, rules.size());

      ProguardConfigurationRule rule = rules.get(0);
      assertEquals(ProguardKeepRuleType.KEEP.toString(), rule.typeString());
      assertEquals("*", rule.getClassNames().toString());
    }
  }

  @Test
  public void negatedMemberTypeTest() throws IOException {
    Path proguardConfigurationFile = writeTextToTempFile("-keepclassmembers class ** { !int x; }");
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(proguardConfigurationFile);
      fail("Expected to fail since the type name cannot be negated.");
    } catch (RuntimeException e) {
      checkDiagnostics(
          handler.errors,
          proguardConfigurationFile,
          1,
          30,
          "Unexpected character '!': "
              + "The negation character can only be used to negate access flags");
    }
  }

  @Test
  public void parseInits() throws Exception {
    for (String initName : InitMatchingTest.ALLOWED_INIT_NAMES) {
      reset();
      Path initConfig = writeTextToTempFile(
          "-keep class **.MyClass {",
          "  " + initName + "(...);",
          "}");
      parseAndVerifyParserEndsCleanly(initConfig);
    }

    for (String initName : InitMatchingTest.INIT_NAMES) {
      // Tested above.
      if (InitMatchingTest.ALLOWED_INIT_NAMES.contains(initName)) {
        continue;
      }
      reset();
      Path proguardConfig = writeTextToTempFile(
          "-keep class **.MyClass {",
          "  " + initName + "(...);",
          "}");
      try {
        parser.parse(proguardConfig);
        fail("Expect to fail due to unsupported constructor name pattern.");
      } catch (RuntimeException e) {
        int column = initName.contains("void") ? initName.indexOf("void") + 8
            : (initName.contains("XYZ") ? initName.indexOf(">") + 4 : 3);
        if (initName.contains("XYZ")) {
          checkDiagnostics(
              handler.errors, proguardConfig, 2, column, "Expected [access-flag]* void ");
        } else {
          checkDiagnostics(
              handler.errors, proguardConfig, 2, column, "Unexpected character", "method name");
        }
      }
      // For some exceptional cases, Proguard accepts the rules but fails with an empty jar message.
      if (initName.contains("<init>")
          || initName.contains("<clinit>")
          || initName.contains("void")) {
        continue;
      }
      verifyFailWithProguard6(
          proguardConfig, "Expecting type and name instead of just '" + initName + "'");
    }
  }

  @Test
  public void parseIncludeCode() throws Exception {
    ProguardConfigurationParser parser;
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path proguardConfig = writeTextToTempFile("-keep,includecode class A { method(); }");
    parser.parse(proguardConfig);
    assertEquals(1, parser.getConfig().getRules().size());
    assertEquals(1, handler.infos.size());
    checkDiagnostics(handler.infos, proguardConfig, 1, 7, "Ignoring modifier", "includecode");
  }

  @Test
  public void parseFileStartingWithBOM() throws Exception {
    // Copied from test 'parseIncludeCode()' and added a BOM.
    ProguardConfigurationParser parser;
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path proguardConfig =
        writeTextToTempFile(StringUtils.BOM + "-keep,includecode class A { method(); }");
    byte[] bytes = Files.readAllBytes(proguardConfig);
    assertEquals(0xef, Byte.toUnsignedLong(bytes[0]));
    assertEquals(0xbb, Byte.toUnsignedLong(bytes[1]));
    assertEquals(0xbf, Byte.toUnsignedLong(bytes[2]));
    parser.parse(proguardConfig);
    assertEquals(1, parser.getConfig().getRules().size());
    assertEquals(1, handler.infos.size());
    checkDiagnostics(handler.infos, proguardConfig, 1, 7, "Ignoring modifier", "includecode");
  }

  @Test
  public void parseFileWithLotsOfWhitespace() throws Exception {
    List<String> ws =
        ImmutableList.of(
            "",
            " ",
            "  ",
            "\t ",
            " \t",
            "" + StringUtils.BOM,
            StringUtils.BOM + " " + StringUtils.BOM);
    // Copied from test 'parseIncludeCode()' and added whitespace.
    for (String whitespace1 : ws) {
      for (String whitespace2 : ws) {
        reset();
        Path proguardConfig =
            writeTextToTempFile(
                whitespace1
                    + "-keep,includecode "
                    + whitespace2
                    + "class A { method(); }"
                    + whitespace1);
        parser.parse(proguardConfig);
        assertEquals(1, parser.getConfig().getRules().size());
        assertEquals(1, handler.infos.size());
        // All BOSs except the leading are counted as input characters.
        checkDiagnostics(handler.infos, proguardConfig, 1, 0, "Ignoring modifier", "includecode");
      }
    }
  }

  @Test
  public void backReferenceElimination() {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser = new ProguardConfigurationParser(dexItemFactory, reporter);
    String configuration = StringUtils.lines("-if class *.*.*", "-keep class <1>.<2>$<3>");
    parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
    verifyParserEndsCleanly();

    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());

    ProguardIfRule ifRule = (ProguardIfRule) config.getRules().iterator().next();

    // Evaluate the class name matcher against foo.bar.Baz.
    DexType type = dexItemFactory.createType("Lfoo/bar/Baz;");
    ifRule.getClassNames().matches(type);

    // Materialize the subsequent rule.
    ProguardKeepRule materializedSubsequentRule = ifRule.subsequentRule.materialize(dexItemFactory);

    // Verify that the class name matcher of the materialized rule has a specific type.
    ProguardClassNameList classNameList = materializedSubsequentRule.getClassNames();
    assertTrue(classNameList instanceof SingleClassNameList);

    SingleClassNameList singleClassNameList = (SingleClassNameList) classNameList;
    assertTrue(singleClassNameList.className instanceof MatchSpecificType);

    MatchSpecificType specificTypeMatcher = (MatchSpecificType) singleClassNameList.className;
    assertEquals("foo.bar$Baz", specificTypeMatcher.type.toSourceString());
  }

  @Test
  public void parseCheckenumstringsdiscarded() throws Exception {
    Path proguardConfig =
        writeTextToTempFile("-checkenumstringsdiscarded @com.example.SomeAnnotation enum *");
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void parseClassAnnotationsAndFlags() {
    List<String> configurationContents =
        ImmutableList.of(
            // 1 annotation without flags.
            "-keep @Foo class *",
            // 1 annotation with public flag.
            "-keep public @Foo class *",
            "-keep @Foo public class *",
            // 1 annotation with public final flags.
            "-keep public final @Foo class *",
            "-keep public @Foo final class *",
            "-keep @Foo public final class *",
            // 2 annotations without flags.
            "-keep @Foo @Bar class *",
            // 2 annotations with public flag.
            "-keep public @Foo @Bar class *",
            "-keep @Foo public @Bar class *",
            "-keep @Foo @Bar public class *",
            // 2 annotations with public final flags.
            "-keep public final @Foo @Bar class *",
            "-keep public @Foo final @Bar class *",
            "-keep public @Foo @Bar final class *",
            "-keep @Foo public final @Bar class *",
            "-keep @Foo public @Bar final class *",
            "-keep @Foo @Bar public final class *");
    for (String configurationContent : configurationContents) {
      DexItemFactory dexItemFactory = new DexItemFactory();
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(dexItemFactory, reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
      verifyParserEndsCleanly();

      ProguardConfiguration configuration = parser.getConfig();
      assertEquals(1, configuration.getRules().size());

      ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
      assertEquals(configurationContent.contains("final"), rule.getClassAccessFlags().isFinal());
      assertEquals(configurationContent.contains("public"), rule.getClassAccessFlags().isPublic());
      assertEquals(
          1 + intValue(configurationContent.contains("@Bar")), rule.getClassAnnotations().size());

      ProguardTypeMatcher.MatchSpecificType fooAnnotation =
          rule.getClassAnnotations().get(0).asSpecificTypeMatcher();
      assertEquals("Foo", fooAnnotation.getSpecificType().toSourceString());

      if (configurationContent.contains("@Bar")) {
        ProguardTypeMatcher.MatchSpecificType barAnnotation =
            rule.getClassAnnotations().get(1).asSpecificTypeMatcher();
        assertEquals("Bar", barAnnotation.getSpecificType().toSourceString());
      }
    }
  }

  @Test
  public void parseFieldAnnotationsAndFlags() {
    Map<String, Optional<Class<? extends Exception>>> configurationContents =
        ImmutableMap.<String, Optional<Class<? extends Exception>>>builder()
            // 1 annotation without flags.
            .put("-keep class * { @Foo Type FIELD; }", Optional.empty())
            // 1 annotation with public flag.
            .put("-keep class * { public @Foo Type FIELD; }", Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo public Type FIELD; }", Optional.empty())
            // 1 annotation with public final flags.
            .put(
                "-keep class * { public final @Foo Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo final Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo public final Type FIELD; }", Optional.empty())
            //// 2 annotations without flags.
            .put("-keep class * { @Foo @Bar Type FIELD; }", Optional.empty())
            //// 2 annotations with public flag.
            .put(
                "-keep class * { public @Foo @Bar Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public @Bar Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo @Bar public Type FIELD; }", Optional.empty())
            //// 2 annotations with public final flags.
            .put(
                "-keep class * { public final @Foo @Bar Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo final @Bar Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo @Bar final Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public final @Bar Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public @Bar final Type FIELD; }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo @Bar public final Type FIELD; }", Optional.empty())
            .build();
    configurationContents.forEach(
        (configurationContent, expectedExceptionClass) -> {
          DexItemFactory dexItemFactory = new DexItemFactory();
          ProguardConfigurationParser parser =
              new ProguardConfigurationParser(dexItemFactory, reporter);
          try {
            parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
            assertFalse(expectedExceptionClass.isPresent());
          } catch (Throwable e) {
            assertTrue(expectedExceptionClass.isPresent());
            assertEquals(expectedExceptionClass.get(), e.getClass());
            reset();
            return;
          }

          verifyParserEndsCleanly();

          ProguardConfiguration configuration = parser.getConfig();
          assertEquals(1, configuration.getRules().size());

          ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
          assertEquals(1, rule.getMemberRules().size());

          ProguardMemberRule memberRule = ListUtils.first(rule.getMemberRules());

          assertEquals(
              configurationContent.contains("final"), memberRule.getAccessFlags().isFinal());
          assertEquals(
              configurationContent.contains("public"), memberRule.getAccessFlags().isPublic());
          assertEquals(
              1 + intValue(configurationContent.contains("@Bar")),
              memberRule.getAnnotations().size());

          ProguardTypeMatcher.MatchSpecificType fooAnnotation =
              memberRule.getAnnotations().get(0).asSpecificTypeMatcher();
          assertEquals("Foo", fooAnnotation.getSpecificType().toSourceString());

          if (configurationContent.contains("@Bar")) {
            ProguardTypeMatcher.MatchSpecificType barAnnotation =
                memberRule.getAnnotations().get(1).asSpecificTypeMatcher();
            assertEquals("Bar", barAnnotation.getSpecificType().toSourceString());
          }
        });
  }

  @Test
  public void parseMethodAnnotationsAndFlags() {
    Map<String, Optional<Class<? extends Exception>>> configurationContents =
        ImmutableMap.<String, Optional<Class<? extends Exception>>>builder()
            // 1 annotation without flags.
            .put("-keep class * { @Foo Type method(); }", Optional.empty())
            // 1 annotation with public flag.
            .put(
                "-keep class * { public @Foo Type method(); }", Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo public Type method(); }", Optional.empty())
            // 1 annotation with public final flags.
            .put(
                "-keep class * { public final @Foo Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo final Type method(); }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo public final Type method(); }", Optional.empty())
            //// 2 annotations without flags.
            .put("-keep class * { @Foo @Bar Type method(); }", Optional.empty())
            //// 2 annotations with public flag.
            .put(
                "-keep class * { public @Foo @Bar Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public @Bar Type method(); }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo @Bar public Type method(); }", Optional.empty())
            //// 2 annotations with public final flags.
            .put(
                "-keep class * { public final @Foo @Bar Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo final @Bar Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { public @Foo @Bar final Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public final @Bar Type method(); }",
                Optional.of(RuntimeException.class))
            .put(
                "-keep class * { @Foo public @Bar final Type method(); }",
                Optional.of(RuntimeException.class))
            .put("-keep class * { @Foo @Bar public final Type method(); }", Optional.empty())
            .build();
    configurationContents.forEach(
        (configurationContent, expectedExceptionClass) -> {
          DexItemFactory dexItemFactory = new DexItemFactory();
          ProguardConfigurationParser parser =
              new ProguardConfigurationParser(dexItemFactory, reporter);
          try {
            parser.parse(createConfigurationForTesting(ImmutableList.of(configurationContent)));
            assertFalse(expectedExceptionClass.isPresent());
          } catch (Throwable e) {
            assertTrue(expectedExceptionClass.isPresent());
            assertEquals(expectedExceptionClass.get(), e.getClass());
            reset();
            return;
          }

          verifyParserEndsCleanly();

          ProguardConfiguration configuration = parser.getConfig();
          assertEquals(1, configuration.getRules().size());

          ProguardKeepRule rule = ListUtils.first(configuration.getRules()).asProguardKeepRule();
          assertEquals(1, rule.getMemberRules().size());

          ProguardMemberRule memberRule = ListUtils.first(rule.getMemberRules());

          assertEquals(
              configurationContent.contains("final"), memberRule.getAccessFlags().isFinal());
          assertEquals(
              configurationContent.contains("public"), memberRule.getAccessFlags().isPublic());
          assertEquals(
              1 + intValue(configurationContent.contains("@Bar")),
              memberRule.getAnnotations().size());

          ProguardTypeMatcher.MatchSpecificType fooAnnotation =
              memberRule.getAnnotations().get(0).asSpecificTypeMatcher();
          assertEquals("Foo", fooAnnotation.getSpecificType().toSourceString());

          if (configurationContent.contains("@Bar")) {
            ProguardTypeMatcher.MatchSpecificType barAnnotation =
                memberRule.getAnnotations().get(1).asSpecificTypeMatcher();
            assertEquals("Bar", barAnnotation.getSpecificType().toSourceString());
          }
        });
  }

  @Test
  public void parseKeepXNamesIsAllowShrinking() {
    for (String rule : ImmutableList.of("-keep", "-keepclassmembers", "-keepclasseswithmembers")) {
      for (String modifier :
          ImmutableList.of("", "names", ",allowshrinking", "names,allowshrinking")) {
        DexItemFactory dexItemFactory = new DexItemFactory();
        ProguardConfigurationParser parser =
            new ProguardConfigurationParser(dexItemFactory, reporter);
        String ruleWithModifier =
            (rule.endsWith("s") && (!modifier.startsWith(",") && !modifier.isEmpty())
                    ? rule.substring(0, rule.length() - 1)
                    : rule)
                + modifier;
        parser.parse(
            createConfigurationForTesting(ImmutableList.of(ruleWithModifier + " class A")));
        verifyParserEndsCleanly();

        ProguardConfiguration configuration = parser.getConfig();
        assertEquals(1, configuration.getRules().size());
        assertEquals(
            !modifier.isEmpty(),
            ListUtils.first(configuration.getRules())
                .asProguardKeepRule()
                .getModifiers()
                .allowsShrinking);
      }
    }
  }
}