• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 package com.android.tools.r8.utils;
5 
6 import com.android.tools.r8.dex.Constants;
7 import com.android.tools.r8.errors.CompilationError;
8 import com.android.tools.r8.graph.DexEncodedMethod;
9 import com.android.tools.r8.graph.DexItemFactory;
10 import com.android.tools.r8.ir.conversion.CallGraph;
11 import com.android.tools.r8.shaking.ProguardConfigurationRule;
12 import com.android.tools.r8.shaking.ProguardTypeMatcher;
13 import com.google.common.collect.ImmutableList;
14 import com.google.common.collect.ImmutableSet;
15 import java.nio.file.Path;
16 import java.util.List;
17 import java.util.function.BiFunction;
18 import java.util.function.Function;
19 
20 public class InternalOptions {
21 
22   public final DexItemFactory itemFactory;
23 
InternalOptions()24   public InternalOptions() {
25     itemFactory = new DexItemFactory();
26   }
27 
InternalOptions(DexItemFactory factory)28   public InternalOptions(DexItemFactory factory) {
29     assert factory != null;
30     itemFactory = factory;
31   }
32 
33   public final int NOT_SPECIFIED = -1;
34 
35   public boolean printTimes = false;
36   // Skipping optimizations.
37   public boolean skipDebugInfoOpt = false;
38   public boolean skipDebugLineNumberOpt = false;
39   public boolean skipClassMerging = true;
40 
41   // Number of threads to use while processing the dex files.
42   public int numberOfThreads = NOT_SPECIFIED;
43   // Print smali disassembly.
44   public boolean useSmaliSyntax = false;
45   // Verbose output.
46   public boolean verbose = false;
47   // Silencing output.
48   public boolean quiet = false;
49 
50   public List<String> methodsFilter = ImmutableList.of();
51   public int minApiLevel = Constants.DEFAULT_ANDROID_API;
52   public List<String> logArgumentsFilter = ImmutableList.of();
53 
54   // Defines interface method rewriter behavior.
55   public OffOrAuto interfaceMethodDesugaring = OffOrAuto.Off;
56   // Defines try-with-resources rewriter behavior.
57   public OffOrAuto tryWithResourcesDesugaring = OffOrAuto.Off;
58 
59   // Application writing mode.
60   public OutputMode outputMode = OutputMode.Indexed;
61 
62   public boolean useTreeShaking = true;
63   public boolean printUsage = false;
64   public Path printUsageFile = null;
65 
66   public boolean printCfg = false;
67   public String printCfgFile;
68   public boolean printSeeds;
69   public Path seedsFile;
70   public boolean printMapping;
71   public Path printMappingFile;
72   public boolean printMainDexList;
73   public Path printMainDexListFile;
74   public boolean ignoreMissingClasses = false;
75   public boolean skipMinification = false;
76   public String packagePrefix = "";
77   public boolean allowAccessModification = true;
78   public boolean inlineAccessors = true;
79   public boolean removeSwitchMaps = true;
80   public boolean disableAssertions = true;
81   public final OutlineOptions outline = new OutlineOptions();
82   public boolean debugKeepRules = false;
83   public final AttributeRemovalOptions attributeRemoval = new AttributeRemovalOptions();
84   public boolean allowParameterName = false;
85 
86   public boolean debug = false;
87   public final TestingOptions testing = new TestingOptions();
88 
89   // TODO(zerny): These stateful dictionaries do not belong here.
90   public List<String> classObfuscationDictionary = ImmutableList.of();
91   public List<String> obfuscationDictionary = ImmutableList.of();
92 
93   public ImmutableList<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
94   public boolean minimalMainDex;
95   public ImmutableList<ProguardConfigurationRule> keepRules = ImmutableList.of();
96   public ImmutableSet<ProguardTypeMatcher> dontWarnPatterns = ImmutableSet.of();
97 
98   public String warningInvalidParameterAnnotations = null;
99 
printWarnings()100   public boolean printWarnings() {
101     boolean printed = false;
102     if (warningInvalidParameterAnnotations != null) {
103       System.out.println("Warning: " + warningInvalidParameterAnnotations);
104       printed = true;
105     }
106     return printed;
107   }
108 
hasMethodsFilter()109   public boolean hasMethodsFilter() {
110     return methodsFilter.size() > 0;
111   }
112 
methodMatchesFilter(DexEncodedMethod method)113   public boolean methodMatchesFilter(DexEncodedMethod method) {
114     // Not specifying a filter matches all methods.
115     if (!hasMethodsFilter()) {
116       return true;
117     }
118     // Currently the filter is simple string equality on the qualified name.
119     String qualifiedName = method.qualifiedName();
120     return methodsFilter.indexOf(qualifiedName) >= 0;
121   }
122 
methodMatchesLogArgumentsFilter(DexEncodedMethod method)123   public boolean methodMatchesLogArgumentsFilter(DexEncodedMethod method) {
124     // Not specifying a filter matches no methods.
125     if (logArgumentsFilter.size() == 0) {
126       return false;
127     }
128     // Currently the filter is simple string equality on the qualified name.
129     String qualifiedName = method.qualifiedName();
130     return logArgumentsFilter.indexOf(qualifiedName) >= 0;
131   }
132 
133   public static class OutlineOptions {
134 
135     public boolean enabled = true;
136     public static final String className = "r8.GeneratedOutlineSupport";
137     public String methodPrefix = "outline";
138     public int minSize = 3;
139     public int maxSize = 99;
140     public int threshold = 20;
141   }
142 
143   public static class TestingOptions {
144     public Function<List<DexEncodedMethod>, List<DexEncodedMethod>> irOrdering;
145   }
146 
147   public static class AttributeRemovalOptions {
148 
149     public static final String INNER_CLASSES = "InnerClasses";
150     public static final String ENCLOSING_METHOD = "EnclosingMethod";
151     public static final String SIGNATURE = "Signature";
152     public static final String EXCEPTIONS = "Exceptions";
153     public static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
154     public static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
155     public static final String RUNTIME_INVISBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
156     public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS =
157         "RuntimeVisibleParameterAnnotations";
158     public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
159         "RuntimeInvisibleParameterAnnotations";
160     public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
161     public static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS =
162         "RuntimeInvisibleTypeAnnotations";
163     public static final String ANNOTATION_DEFAULT = "AnnotationDefault";
164 
165     public boolean innerClasses = false;
166     public boolean enclosingMethod = false;
167     public boolean signature = false;
168     public boolean exceptions = false;
169     public boolean sourceDebugExtension = false;
170     public boolean runtimeVisibleAnnotations = false;
171     public boolean runtimeInvisibleAnnotations = false;
172     public boolean runtimeVisibleParameterAnnotations = false;
173     public boolean runtimeInvisibleParamterAnnotations = false;
174     public boolean runtimeVisibleTypeAnnotations = false;
175     public boolean runtimeInvisibleTypeAnnotations = false;
176     public boolean annotationDefault = false;
177 
AttributeRemovalOptions()178     private AttributeRemovalOptions() {
179 
180     }
181 
filterOnlySignatures()182     public static AttributeRemovalOptions filterOnlySignatures() {
183       AttributeRemovalOptions result = new AttributeRemovalOptions();
184       result.applyPattern("*");
185       result.signature = false;
186       return result;
187     }
188 
189     /**
190      * Implements ProGuards attribute matching rules.
191      *
192      * @see <a href="https://www.guardsquare.com/en/proguard/manual/attributes">ProGuard manual</a>.
193      */
update(boolean previous, String text, String[] patterns)194     private boolean update(boolean previous, String text, String[] patterns) {
195       for (String pattern : patterns) {
196         if (previous) {
197           return true;
198         }
199         if (pattern.charAt(0) == '!') {
200           if (matches(pattern, 1, text, 0)) {
201             break;
202           }
203         } else {
204           previous = matches(pattern, 0, text, 0);
205         }
206       }
207       return previous;
208     }
209 
matches(String pattern, int patternPos, String text, int textPos)210     private boolean matches(String pattern, int patternPos, String text, int textPos) {
211       while (patternPos < pattern.length()) {
212         char next = pattern.charAt(patternPos++);
213         if (next == '*') {
214           while (textPos < text.length()) {
215             if (matches(pattern, patternPos, text, textPos++)) {
216               return true;
217             }
218           }
219           return patternPos >= pattern.length();
220         } else {
221           if (textPos >= text.length() || text.charAt(textPos) != next) {
222             return false;
223           }
224           textPos++;
225         }
226       }
227       return textPos == text.length();
228     }
229 
applyPattern(String pattern)230     public void applyPattern(String pattern) {
231       String[] patterns = pattern.split(",");
232       innerClasses = update(innerClasses, INNER_CLASSES, patterns);
233       enclosingMethod = update(enclosingMethod, ENCLOSING_METHOD, patterns);
234       signature = update(signature, SIGNATURE, patterns);
235       exceptions = update(exceptions, EXCEPTIONS, patterns);
236       sourceDebugExtension = update(sourceDebugExtension, SOURCE_DEBUG_EXTENSION, patterns);
237       runtimeVisibleAnnotations = update(runtimeVisibleAnnotations, RUNTIME_VISIBLE_ANNOTATIONS,
238           patterns);
239       runtimeInvisibleAnnotations = update(runtimeInvisibleAnnotations,
240           RUNTIME_INVISBLE_ANNOTATIONS, patterns);
241       runtimeVisibleParameterAnnotations = update(runtimeVisibleParameterAnnotations,
242           RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, patterns);
243       runtimeInvisibleParamterAnnotations = update(runtimeInvisibleParamterAnnotations,
244           RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, patterns);
245       runtimeVisibleTypeAnnotations = update(runtimeVisibleTypeAnnotations,
246           RUNTIME_VISIBLE_TYPE_ANNOTATIONS, patterns);
247       runtimeInvisibleTypeAnnotations = update(runtimeInvisibleTypeAnnotations,
248           RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, patterns);
249       annotationDefault = update(annotationDefault, ANNOTATION_DEFAULT, patterns);
250     }
251 
ensureValid(boolean isMinifying)252     public void ensureValid(boolean isMinifying) {
253       if (innerClasses && !enclosingMethod) {
254         throw new CompilationError("Attribute InnerClasses requires EnclosingMethod attribute. "
255             + "Check -keepattributes directive.");
256       } else if (!innerClasses && enclosingMethod) {
257         throw new CompilationError("Attribute EnclosingMethod requires InnerClasses attribute. "
258             + "Check -keepattributes directive.");
259       } else if (signature && !innerClasses) {
260         throw new CompilationError("Attribute Signature requires InnerClasses attribute. Check "
261             + "-keepattributes directive.");
262       } else if (signature && isMinifying) {
263         // TODO(38188583): Allow this once we can minify signatures.
264         throw new CompilationError("Attribute Signature cannot be kept when minifying. "
265             + "Check -keepattributes directive.");
266       }
267     }
268   }
269 
canUseInvokePolymorphic()270   public boolean canUseInvokePolymorphic() {
271     return minApiLevel >= Constants.ANDROID_O_API;
272   }
273 
canUseInvokeCustom()274   public boolean canUseInvokeCustom() {
275     return minApiLevel >= Constants.ANDROID_O_API;
276   }
277 
canUseDefaultAndStaticInterfaceMethods()278   public boolean canUseDefaultAndStaticInterfaceMethods() {
279     return minApiLevel >= Constants.ANDROID_N_API;
280   }
281 
canUseLongCompareAndObjectsNonNull()282   public boolean canUseLongCompareAndObjectsNonNull() {
283     return minApiLevel >= Constants.ANDROID_K_API;
284   }
285 
canUseSuppressedExceptions()286   public boolean canUseSuppressedExceptions() {
287     return minApiLevel >= Constants.ANDROID_K_API;
288   }
289 
canUsePrivateInterfaceMethods()290   public boolean canUsePrivateInterfaceMethods() {
291     return minApiLevel >= Constants.ANDROID_N_API;
292   }
293 
294   // APIs for accessing parameter names annotations are not available before Android O, thus does
295   // not emit them to avoid wasting space in Dex files because runtimes before Android O will ignore
296   // them.
canUseParameterNameAnnotations()297   public boolean canUseParameterNameAnnotations() {
298     return minApiLevel >= Constants.ANDROID_O_API;
299   }
300 }
301