Detach PG attributes from InternalOptions.

-keepattributes should belong to Proguard config, not internal options.

Bug: 66399389
Change-Id: I247987455b80f094987904255ebe72580ef15b36
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 7eff6fa..5b3cfb5 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -477,7 +477,6 @@
     internal.useDiscardedChecker = useDiscardedChecker();
     assert !internal.ignoreMissingClasses;
     internal.ignoreMissingClasses = ignoreMissingClasses;
-    internal.keepAttributes.applyPatterns(proguardConfiguration.getKeepAttributesPatterns());
     internal.ignoreMissingClasses |= proguardConfiguration.isIgnoreWarnings();
     assert !internal.verbose;
     internal.mainDexKeepRules = mainDexKeepRules;
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index c5e62e2..39ca020 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -71,7 +71,7 @@
     this.isAccessModificationAllowed = options.proguardConfiguration.isAccessModificationAllowed();
     this.packageDictionary = options.proguardConfiguration.getPackageObfuscationDictionary();
     this.classDictionary = options.proguardConfiguration.getClassObfuscationDictionary();
-    this.keepInnerClassStructure = options.keepAttributes.signature;
+    this.keepInnerClassStructure = options.proguardConfiguration.getKeepAttributes().signature;
 
     // Initialize top-level naming state.
     topLevelState = new Namespace(
diff --git a/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java b/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
index c10d0d7..3736008 100644
--- a/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/SourceFileRewriter.java
@@ -31,7 +31,7 @@
   public void run() {
     String renameSourceFile = options.proguardConfiguration.getRenameSourceFileAttribute();
     // Return early if a user wants to keep the current source file attribute as-is.
-    if (renameSourceFile == null && options.keepAttributes.sourceFile) {
+    if (renameSourceFile == null && options.proguardConfiguration.getKeepAttributes().sourceFile) {
       return;
     }
     // Now, the user wants either to remove source file attribute or to rename it.
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 824f1bd..1698f7a 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.function.Predicate;
@@ -21,14 +20,13 @@
 public class AnnotationRemover {
 
   private final AppInfoWithLiveness appInfo;
-  private final KeepAttributeOptions keep;
+  private final ProguardKeepAttributes keep;
 
   public AnnotationRemover(AppInfoWithLiveness appInfo, InternalOptions options) {
-    this(appInfo, options.keepAttributes);
+    this(appInfo, options.proguardConfiguration.getKeepAttributes());
   }
 
-  public AnnotationRemover(AppInfoWithLiveness appInfo,
-      KeepAttributeOptions keep) {
+  public AnnotationRemover(AppInfoWithLiveness appInfo, ProguardKeepAttributes keep) {
     this.appInfo = appInfo;
     this.keep = keep;
   }
@@ -91,7 +89,7 @@
         }
         break;
       case DexAnnotation.VISIBILITY_BUILD:
-        if (!keep.runtimeInvisibleParamterAnnotations) {
+        if (!keep.runtimeInvisibleParameterAnnotations) {
           return false;
         }
         break;
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index 3251c04..4a84321 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.DictionaryReader;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
 import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
@@ -256,7 +255,7 @@
   private final Path applyMappingFile;
   private final boolean verbose;
   private final String renameSourceFileAttribute;
-  private final ImmutableList<String> keepAttributesPatterns;
+  private final ProguardKeepAttributes keepAttributes;
   private final ProguardClassFilter dontWarnPatterns;
   protected final ImmutableList<ProguardConfigurationRule> rules;
   private final boolean printSeeds;
@@ -314,7 +313,7 @@
     this.applyMappingFile = applyMappingFile;
     this.verbose = verbose;
     this.renameSourceFileAttribute = renameSourceFileAttribute;
-    this.keepAttributesPatterns = ImmutableList.copyOf(keepAttributesPatterns);
+    this.keepAttributes = ProguardKeepAttributes.fromPatterns(keepAttributesPatterns);
     this.dontWarnPatterns = dontWarnPatterns;
     this.rules = ImmutableList.copyOf(rules);
     this.printSeeds = printSeeds;
@@ -338,7 +337,7 @@
     Builder builder = new Builder(dexItemFactory);
     builder.setObfuscating(false);
     builder.setShrinking(false);
-    builder.addKeepAttributePatterns(KeepAttributeOptions.KEEP_ALL);
+    builder.addKeepAttributePatterns(ProguardKeepAttributes.KEEP_ALL);
     builder.addRule(ProguardKeepRule.defaultKeepAllRule());
     return builder;
   }
@@ -415,8 +414,8 @@
     return renameSourceFileAttribute;
   }
 
-  public ImmutableList<String> getKeepAttributesPatterns() {
-    return keepAttributesPatterns;
+  public ProguardKeepAttributes getKeepAttributes() {
+    return keepAttributes;
   }
 
   public ProguardClassFilter getDontWarnPatterns() {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java
new file mode 100644
index 0000000..487a5b4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepAttributes.java
@@ -0,0 +1,182 @@
+// Copyright (c) 2017, 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 com.android.tools.r8.errors.CompilationError;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class ProguardKeepAttributes {
+
+  public static final String SOURCE_FILE = "SourceFile";
+  public static final String SOURCE_DIR = "SourceDir";
+  public static final String INNER_CLASSES = "InnerClasses";
+  public static final String ENCLOSING_METHOD = "EnclosingMethod";
+  public static final String SIGNATURE = "Signature";
+  public static final String EXCEPTIONS = "Exceptions";
+  public static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
+  public static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
+  public static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
+  public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS =
+      "RuntimeVisibleParameterAnnotations";
+  public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
+      "RuntimeInvisibleParameterAnnotations";
+  public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
+  public static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS =
+      "RuntimeInvisibleTypeAnnotations";
+  public static final String ANNOTATION_DEFAULT = "AnnotationDefault";
+
+  public static final List<String> KEEP_ALL = ImmutableList.of("*");
+
+  public boolean sourceFile = false;
+  public boolean sourceDir = false;
+  public boolean innerClasses = false;
+  public boolean enclosingMethod = false;
+  public boolean signature = false;
+  public boolean exceptions = false;
+  public boolean sourceDebugExtension = false;
+  public boolean runtimeVisibleAnnotations = false;
+  public boolean runtimeInvisibleAnnotations = false;
+  public boolean runtimeVisibleParameterAnnotations = false;
+  public boolean runtimeInvisibleParameterAnnotations = false;
+  public boolean runtimeVisibleTypeAnnotations = false;
+  public boolean runtimeInvisibleTypeAnnotations = false;
+  public boolean annotationDefault = false;
+
+  private ProguardKeepAttributes() {
+  }
+
+  public static ProguardKeepAttributes filterOnlySignatures() {
+    ProguardKeepAttributes result = new ProguardKeepAttributes();
+    result.applyPatterns(KEEP_ALL);
+    result.signature = false;
+    return result;
+  }
+
+  /**
+   * Implements ProGuards attribute matching rules.
+   *
+   * @see <a href="https://www.guardsquare.com/en/proguard/manual/attributes">ProGuard manual</a>.
+   */
+  private boolean update(boolean previous, String text, List<String> patterns) {
+    for (String pattern : patterns) {
+      if (previous) {
+        return true;
+      }
+      if (pattern.charAt(0) == '!') {
+        if (matches(pattern, 1, text, 0)) {
+          break;
+        }
+      } else {
+        previous = matches(pattern, 0, text, 0);
+      }
+    }
+    return previous;
+  }
+
+  private boolean matches(String pattern, int patternPos, String text, int textPos) {
+    while (patternPos < pattern.length()) {
+      char next = pattern.charAt(patternPos++);
+      if (next == '*') {
+        while (textPos < text.length()) {
+          if (matches(pattern, patternPos, text, textPos++)) {
+            return true;
+          }
+        }
+        return patternPos >= pattern.length();
+      } else {
+        if (textPos >= text.length() || text.charAt(textPos) != next) {
+          return false;
+        }
+        textPos++;
+      }
+    }
+    return textPos == text.length();
+  }
+
+  public static ProguardKeepAttributes fromPatterns(List<String> patterns) {
+    ProguardKeepAttributes keepAttributes = new ProguardKeepAttributes();
+    keepAttributes.applyPatterns(patterns);
+    return keepAttributes;
+  }
+
+  public void applyPatterns(List<String> patterns) {
+    sourceFile = update(sourceFile, SOURCE_FILE, patterns);
+    sourceDir = update(sourceDir, SOURCE_DIR, patterns);
+    innerClasses = update(innerClasses, INNER_CLASSES, patterns);
+    enclosingMethod = update(enclosingMethod, ENCLOSING_METHOD, patterns);
+    signature = update(signature, SIGNATURE, patterns);
+    exceptions = update(exceptions, EXCEPTIONS, patterns);
+    sourceDebugExtension = update(sourceDebugExtension, SOURCE_DEBUG_EXTENSION, patterns);
+    runtimeVisibleAnnotations = update(runtimeVisibleAnnotations, RUNTIME_VISIBLE_ANNOTATIONS,
+        patterns);
+    runtimeInvisibleAnnotations = update(runtimeInvisibleAnnotations,
+        RUNTIME_INVISIBLE_ANNOTATIONS, patterns);
+    runtimeVisibleParameterAnnotations = update(runtimeVisibleParameterAnnotations,
+        RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, patterns);
+    runtimeInvisibleParameterAnnotations = update(runtimeInvisibleParameterAnnotations,
+        RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, patterns);
+    runtimeVisibleTypeAnnotations = update(runtimeVisibleTypeAnnotations,
+        RUNTIME_VISIBLE_TYPE_ANNOTATIONS, patterns);
+    runtimeInvisibleTypeAnnotations = update(runtimeInvisibleTypeAnnotations,
+        RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, patterns);
+    annotationDefault = update(annotationDefault, ANNOTATION_DEFAULT, patterns);
+  }
+
+  public void ensureValid() {
+    if (innerClasses && !enclosingMethod) {
+      throw new CompilationError("Attribute InnerClasses requires EnclosingMethod attribute. "
+          + "Check -keepattributes directive.");
+    } else if (!innerClasses && enclosingMethod) {
+      throw new CompilationError("Attribute EnclosingMethod requires InnerClasses attribute. "
+          + "Check -keepattributes directive.");
+    } else if (signature && !innerClasses) {
+      throw new CompilationError("Attribute Signature requires InnerClasses attribute. Check "
+          + "-keepattributes directive.");
+    }
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof ProguardKeepAttributes)) {
+      return false;
+    }
+    ProguardKeepAttributes other = (ProguardKeepAttributes) o;
+    return this.sourceFile == other.sourceFile
+        && this.sourceDir == other.sourceDir
+        && this.innerClasses == other.innerClasses
+        && this.enclosingMethod == other.enclosingMethod
+        && this.signature == other.signature
+        && this.exceptions == other.exceptions
+        && this.sourceDebugExtension == other.sourceDebugExtension
+        && this.runtimeVisibleAnnotations == other.runtimeVisibleAnnotations
+        && this.runtimeInvisibleAnnotations == other.runtimeInvisibleAnnotations
+        && this.runtimeVisibleParameterAnnotations == other.runtimeVisibleParameterAnnotations
+        && this.runtimeInvisibleParameterAnnotations == other.runtimeInvisibleParameterAnnotations
+        && this.runtimeVisibleTypeAnnotations == other.runtimeVisibleTypeAnnotations
+        && this.runtimeInvisibleTypeAnnotations == other.runtimeInvisibleTypeAnnotations
+        && this.annotationDefault == other.annotationDefault;
+  }
+
+  @Override
+  public int hashCode() {
+    return (this.sourceFile ? 1 : 0)
+        + (this.sourceDir ? 1 << 1 : 0)
+        + (this.innerClasses ? 1 << 2 : 0)
+        + (this.enclosingMethod ? 1 << 3 : 0)
+        + (this.signature ? 1 << 4 : 0)
+        + (this.exceptions ? 1 << 5 : 0)
+        + (this.sourceDebugExtension ? 1 << 6 : 0)
+        + (this.runtimeVisibleAnnotations ? 1 << 7 : 0)
+        + (this.runtimeInvisibleAnnotations ? 1 << 8 : 0)
+        + (this.runtimeVisibleParameterAnnotations ? 1 << 9 : 0)
+        + (this.runtimeInvisibleParameterAnnotations ? 1 << 10 : 0)
+        + (this.runtimeVisibleTypeAnnotations ? 1 << 11 : 0)
+        + (this.runtimeInvisibleTypeAnnotations ? 1 << 12 : 0)
+        + (this.annotationDefault ? 1 << 13 : 0);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 8d7171f..75f89be 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.Resource.Origin;
 import com.android.tools.r8.dex.Marker;
-import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.InvalidDebugInfoException;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -114,7 +113,6 @@
   public boolean skipMinification = false;
   public boolean disableAssertions = true;
   public boolean debugKeepRules = false;
-  public final KeepAttributeOptions keepAttributes = new KeepAttributeOptions();
   public boolean allowParameterName = false;
 
   public boolean debug = false;
@@ -282,132 +280,6 @@
     public boolean invertConditionals = false;
   }
 
-  public static class KeepAttributeOptions {
-
-    public static final String SOURCE_FILE = "SourceFile";
-    public static final String SOURCE_DIR = "SourceDir";
-    public static final String INNER_CLASSES = "InnerClasses";
-    public static final String ENCLOSING_METHOD = "EnclosingMethod";
-    public static final String SIGNATURE = "Signature";
-    public static final String EXCEPTIONS = "Exceptions";
-    public static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
-    public static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
-    public static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
-    public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS =
-        "RuntimeVisibleParameterAnnotations";
-    public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
-        "RuntimeInvisibleParameterAnnotations";
-    public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
-    public static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS =
-        "RuntimeInvisibleTypeAnnotations";
-    public static final String ANNOTATION_DEFAULT = "AnnotationDefault";
-
-    public static final List<String> KEEP_ALL = ImmutableList.of("*");
-
-    public boolean sourceFile = false;
-    public boolean sourceDir = false;
-    public boolean innerClasses = false;
-    public boolean enclosingMethod = false;
-    public boolean signature = false;
-    public boolean exceptions = false;
-    public boolean sourceDebugExtension = false;
-    public boolean runtimeVisibleAnnotations = false;
-    public boolean runtimeInvisibleAnnotations = false;
-    public boolean runtimeVisibleParameterAnnotations = false;
-    public boolean runtimeInvisibleParamterAnnotations = false;
-    public boolean runtimeVisibleTypeAnnotations = false;
-    public boolean runtimeInvisibleTypeAnnotations = false;
-    public boolean annotationDefault = false;
-
-    private KeepAttributeOptions() {
-
-    }
-
-    public static KeepAttributeOptions filterOnlySignatures() {
-      KeepAttributeOptions result = new KeepAttributeOptions();
-      result.applyPatterns(KEEP_ALL);
-      result.signature = false;
-      return result;
-    }
-
-    /**
-     * Implements ProGuards attribute matching rules.
-     *
-     * @see <a href="https://www.guardsquare.com/en/proguard/manual/attributes">ProGuard manual</a>.
-     */
-    private boolean update(boolean previous, String text, List<String> patterns) {
-      for (String pattern : patterns) {
-        if (previous) {
-          return true;
-        }
-        if (pattern.charAt(0) == '!') {
-          if (matches(pattern, 1, text, 0)) {
-            break;
-          }
-        } else {
-          previous = matches(pattern, 0, text, 0);
-        }
-      }
-      return previous;
-    }
-
-    private boolean matches(String pattern, int patternPos, String text, int textPos) {
-      while (patternPos < pattern.length()) {
-        char next = pattern.charAt(patternPos++);
-        if (next == '*') {
-          while (textPos < text.length()) {
-            if (matches(pattern, patternPos, text, textPos++)) {
-              return true;
-            }
-          }
-          return patternPos >= pattern.length();
-        } else {
-          if (textPos >= text.length() || text.charAt(textPos) != next) {
-            return false;
-          }
-          textPos++;
-        }
-      }
-      return textPos == text.length();
-    }
-
-    public void applyPatterns(List<String> patterns) {
-      sourceFile = update(sourceFile, SOURCE_FILE, patterns);
-      sourceDir = update(sourceDir, SOURCE_DIR, patterns);
-      innerClasses = update(innerClasses, INNER_CLASSES, patterns);
-      enclosingMethod = update(enclosingMethod, ENCLOSING_METHOD, patterns);
-      signature = update(signature, SIGNATURE, patterns);
-      exceptions = update(exceptions, EXCEPTIONS, patterns);
-      sourceDebugExtension = update(sourceDebugExtension, SOURCE_DEBUG_EXTENSION, patterns);
-      runtimeVisibleAnnotations = update(runtimeVisibleAnnotations, RUNTIME_VISIBLE_ANNOTATIONS,
-          patterns);
-      runtimeInvisibleAnnotations = update(runtimeInvisibleAnnotations,
-          RUNTIME_INVISIBLE_ANNOTATIONS, patterns);
-      runtimeVisibleParameterAnnotations = update(runtimeVisibleParameterAnnotations,
-          RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, patterns);
-      runtimeInvisibleParamterAnnotations = update(runtimeInvisibleParamterAnnotations,
-          RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, patterns);
-      runtimeVisibleTypeAnnotations = update(runtimeVisibleTypeAnnotations,
-          RUNTIME_VISIBLE_TYPE_ANNOTATIONS, patterns);
-      runtimeInvisibleTypeAnnotations = update(runtimeInvisibleTypeAnnotations,
-          RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, patterns);
-      annotationDefault = update(annotationDefault, ANNOTATION_DEFAULT, patterns);
-    }
-
-    public void ensureValid() {
-      if (innerClasses && !enclosingMethod) {
-        throw new CompilationError("Attribute InnerClasses requires EnclosingMethod attribute. "
-            + "Check -keepattributes directive.");
-      } else if (!innerClasses && enclosingMethod) {
-        throw new CompilationError("Attribute EnclosingMethod requires InnerClasses attribute. "
-            + "Check -keepattributes directive.");
-      } else if (signature && !innerClasses) {
-        throw new CompilationError("Attribute Signature requires InnerClasses attribute. Check "
-            + "-keepattributes directive.");
-      }
-    }
-  }
-
   public boolean canUseInvokePolymorphicOnVarHandle() {
     return minApiLevel >= AndroidApiLevel.P.getLevel();
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 7912a9d..6dc19aa 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -18,7 +18,6 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.InternalOptions.KeepAttributeOptions;
 import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -816,8 +815,8 @@
     parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2)));
     ProguardConfiguration config = parser.getConfig();
     assertEquals("PG", config.getRenameSourceFileAttribute());
-    assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_FILE));
-    assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_DIR));
+    assertTrue(config.getKeepAttributes().sourceFile);
+    assertTrue(config.getKeepAttributes().sourceDir);
   }
 
   @Test
@@ -829,14 +828,16 @@
     parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2)));
     ProguardConfiguration config = parser.getConfig();
     assertEquals("", config.getRenameSourceFileAttribute());
-    assertTrue(config.getKeepAttributesPatterns().contains(KeepAttributeOptions.SOURCE_FILE));
+    assertTrue(config.getKeepAttributes().sourceFile);
   }
 
   private void testKeepattributes(List<String> expected, String config) throws Exception {
     ProguardConfigurationParser parser =
         new ProguardConfigurationParser(new DexItemFactory(), diagnosticsHandler);
     parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
-    assertEquals(expected, parser.getConfig().getKeepAttributesPatterns());
+    assertEquals(
+        ProguardKeepAttributes.fromPatterns(expected),
+        parser.getConfig().getKeepAttributes());
   }
 
   @Test
@@ -848,9 +849,11 @@
     testKeepattributes(xxxYYY, "-keepattributes xxx   ,   yyy");
     testKeepattributes(xxxYYY, "-keepattributes       xxx   ,   yyy     ");
     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",
+    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);
   }
@@ -889,7 +892,6 @@
       parser.getConfig();
       fail();
     } catch (ProguardRuleParserException e) {
-      System.out.println(e);
       assertTrue(e.getMessage().contains("-keepparameternames is not supported"));
     }
   }