1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tools.metalava
18 
19 const val COMPAT_MODE_BY_DEFAULT = true
20 
21 /**
22  * The old API generator code had a number of quirks. Initially we want to simulate these
23  * quirks to produce compatible signature files and APIs, but we want to track what these quirks
24  * are and be able to turn them off eventually. This class offers more fine grained control
25  * of these compatibility behaviors such that we can enable/disable them selectively
26  */
27 var compatibility: Compatibility = Compatibility()
28 
29 class Compatibility(
30     /** Whether compatibility is generally on */
31     val compat: Boolean = COMPAT_MODE_BY_DEFAULT
32 ) {
33 
34     /** In signature files, use "implements" instead of "extends" for the super class of
35      * an interface */
36     var extendsForInterfaceSuperClass: Boolean = compat
37 
38     /** In signature files, refer to annotations as an "abstract class" instead of an "@interface"
39      * and implementing this interface: java.lang.annotation.Annotation */
40     var classForAnnotations: Boolean = compat
41 
42     /** Add in explicit `valueOf` and `values` methods into enum classes */
43     var defaultEnumMethods: Boolean = compat
44 
45     /** Whether signature files should contain annotation default values (as is already
46      * done for field default values) */
47     var includeAnnotationDefaults: Boolean = !compat
48 
49     /** In signature files, refer to enums as "class" instead of "enum" */
50     var classForEnums: Boolean = compat
51 
52     /** Whether to use a nonstandard, compatibility modifier order instead of the Java canonical order.
53      * ("deprecated" isn't a real modifier, so in "standard" mode it's listed first, as if it was the
54      * `@Deprecated` annotation before the modifier list */
55     var nonstandardModifierOrder: Boolean = compat
56 
57     /** Whether to include instance methods in annotation classes for the annotation properties */
58     var skipAnnotationInstanceMethods: Boolean = compat
59 
60     /**
61      * In signature files, whether interfaces should also be described as "abstract"
62      */
63     var abstractInInterfaces: Boolean = compat
64 
65     /**
66      * In signature files, whether annotation types should also be described as "abstract"
67      */
68     var abstractInAnnotations: Boolean = compat
69 
70     /**
71      * In signature files, whether interfaces can be listed as final
72      */
73     var finalInInterfaces: Boolean = compat
74 
75     /**
76      * In this signature
77      *        public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
78      *  doclava1 would treat this as "throws Throwable" instead of "throws X". This variable turns on
79      *  this compat behavior.
80      * */
81     var useErasureInThrows: Boolean = compat
82 
83     /**
84      * Whether throws classes in methods should be filtered. This should definitely
85      * be the case, but doclava1 doesn't. Note that this only applies to signature
86      * files, not stub files.
87      */
88     var filterThrowsClasses: Boolean = !compat
89 
90     /** Format `Map<K,V>` as `Map<K, V>` */
91     var spaceAfterCommaInTypes: Boolean = compat
92 
93     /**
94      * Doclava1 omits type parameters in interfaces (in signature files, not in stubs)
95      */
96     var omitTypeParametersInInterfaces: Boolean = compat
97 
98     /** Force methods named "values" in enums to be marked final. This was done by
99      * doclava1 with this comment:
100      *
101      *     Explicitly coerce 'final' state of Java6-compiled enum values() method,
102      *     to match the Java5-emitted base API description.
103      *
104      **/
105     var forceFinalInEnumValueMethods: Boolean = compat
106 
107     /** Whether signature files and stubs should contain annotations */
108     var annotationsInSignatures: Boolean = !compat
109 
110     /** Emit errors in the old API diff format */
111     var oldErrorOutputFormat: Boolean = false
112 
113     /** Whether to include the exit <b>code</b> in the error output next to the id */
114     var includeExitCode = oldErrorOutputFormat
115 
116     /**
117      * When a public class implementing a public interface inherits the implementation
118      * of a method in that interface from a hidden super class, the method must be
119      * included in the stubs etc (since otherwise subclasses would believe they need
120      * to implement that method and can't just inherit it). However, doclava1 does not
121      * list these methods. This flag controls this compatibility behavior.
122      * Not that this refers only to the signature files, not the stub file generation.
123      *
124      * An example is StringBuilder#setLength.
125      */
126     var skipInheritedMethods: Boolean = compat
127 
128     /**
129      * Similar to [skipInheritedMethods], but for field constants.
130      */
131     var skipInheritedConstants: Boolean = compat
132 
133     /**
134      * Whether to include parameter names in the signature file
135      */
136     var parameterNames: Boolean = !compat
137 
138     /**
139      * *Some* signatures for doclava1 wrote "<?>" as "<? extends java.lang.Object>",
140      * which is equivalent. Metalava does not do that. This flags ensures that the
141      * signature files look like the old ones for the specific methods which did this.
142      */
143     var includeExtendsObjectInWildcard = compat
144 
145     /**
146      * Whether deprecation should be shown in signature files as an annotation
147      * instead of a pseudo-modifier
148      */
149     var deprecatedAsAnnotation = !compat
150 
151     /** Whether synchronized should be part of the output */
152     var includeSynchronized = compat
153 
154     /** Whether we should omit common packages such as java.lang.* and kotlin.* from signature output */
155     var omitCommonPackages = !compat
156 
157     /** Whether we should explicitly include retention when class even if not explicitly defined */
158     var explicitlyListClassRetention = !compat
159 
160     /**
161      * If true, a @Deprecated class will automatically deprecate all its inner classes
162      * as well.
163      */
164     var propagateDeprecatedInnerClasses = !compat
165 
166     /**
167      * If true, a @Deprecated class will automatically deprecate all members (not
168      * including inner classes; for that see [propagateDeprecatedInnerClasses]) as well.
169      */
170     var propagateDeprecatedMembers = !compat
171 
172     /**
173      * If an overriding method differs from its super method only by final or deprecated
174      * and the containing class is final or deprecated, skip it in the signature file
175      */
176     var hideDifferenceImplicit = !compat
177 
178     /** Whether inner enums should be listed as static in the signature file. */
179     var staticEnums = compat
180 
181     /**
182      * The -new_api flag in API check (which generates an XML diff of the differences
183      * between two APIs) in doclava was ignoring fields. This flag controls whether
184      * we do the same.
185      */
186     var includeFieldsInApiDiff = !compat
187 
188     /**
189      * Whether to escape the > character in JDiff XML files. The XML spec does not require
190      * this but doclava does it.
191      */
192     var xmlEscapeGreaterThan = compat
193 
194     /**
195      * When producing JDiff output for field arrays but where we
196      * do not have the value, emit "null" into the JDiff report. This isn't right but matches
197      * what doclava did.
198      */
199     var xmlShowArrayFieldsAsNull = compat
200 
201     /**
202      * Doclava was missing enum fields in JDiff reports
203      */
204     var xmlSkipEnumFields = compat
205 
206     /**
207      * Doclava was missing annotation instance methods in JDiff reports
208      */
209     var xmlSkipAnnotationMethods = compat
210 
211     /** Doclava lists character field values as integers instead of chars */
212     var xmlCharAsInt = compat
213 
214     /**
215      * Doclava listed the superclass of annotations as
216      * java.lang.Object.
217      */
218     var xmlAnnotationAsObject = compat
219 
220     // Other examples: sometimes we sort by qualified name, sometimes by full name
221 }