• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Bazel Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 package com.google.devtools.build.android.desugar;
15 
16 import javax.annotation.Nullable;
17 
18 /**
19  * Interface for collecting desugaring metadata that we can use to double-check correct desugaring
20  * at the binary level by looking at the metadata written for all Jars on the runtime classpath
21  * (b/65645388). Use {@link NoWriteCollectors} for "no-op" collectors and {@link
22  * com.google.devtools.build.android.desugar.dependencies.MetadataCollector} for writing out
23  * metadata files.
24  */
25 // TODO(kmb): There could conceivably be a "self-contained" version where we check at the end that
26 // we actually saw all the companion classes (in recordDefaultMethods) that we "assumed"; useful
27 // for one-shot runs over an entire binary.
28 @SuppressWarnings("unused") // default implementations consist of empty method stubs
29 public interface DependencyCollector {
30 
31   /** Class name suffix used for interface companion classes. */
32   public String INTERFACE_COMPANION_SUFFIX = "$$CC";
33 
34   /**
35    * Records that {@code origin} depends on companion class {@code target}.  For the resulting
36    * binary to be valid, {@code target} needs to exist, which isn't the case if the corresponding
37    * interface is only available as a compile-time ("neverlink") dependency.
38    */
assumeCompanionClass(String origin, String target)39   default void assumeCompanionClass(String origin, String target) {}
40 
41   /**
42    * Records that {@code origin} transitively implements {@code target} but {@code target} isn't
43    * in the classpath.  This can lead to wrong desugarings if {@code target} or an interface it
44    * extends defines default methods.
45    */
missingImplementedInterface(String origin, String target)46   default void missingImplementedInterface(String origin, String target) {}
47 
48   /**
49    * Records that the given interface extends the given interfaces.
50    *
51    * <p>This information is useful reference to double-check {@link #missingImplementedInterface}s
52    * without reading and parsing .class files, specifically if default methods are defined in
53    * interfaces that a missing interface transitively extends.
54    */
recordExtendedInterfaces(String origin, String... targets)55   default void recordExtendedInterfaces(String origin, String... targets) {}
56 
57   /**
58    * Records that the given interface has a companion class that includes the given number of
59    * default methods (0 if there were only static methods).  This method should not be called for
60    * purely abstract interfaces, to allow verifying available companion classes against this.
61    *
62    * <p>This information is useful reference to double-check {@link #missingImplementedInterface}s
63    * without reading and parsing .class files with better precision than just looking for
64    * companion classes on the runtime classpath (which may only contain static methods).
65    */
recordDefaultMethods(String origin, int count)66   default void recordDefaultMethods(String origin, int count) {}
67 
68   /**
69    * Returns metadata to include into the desugaring output or {@code null} if none.  Returning
70    * anything but {@code null} will cause an extra file to be written into the output, including
71    * an empty array.
72    */
toByteArray()73   @Nullable public byte[] toByteArray();
74 
75   /** Simple collectors that don't collect any information. */
76   public enum NoWriteCollectors implements DependencyCollector {
77     /** Singleton instance that does nothing. */
78     NOOP,
79     /**
80      * Singleton instance that does nothing besides throwing if {@link #missingImplementedInterface}
81      * is called.
82      */
83     FAIL_ON_MISSING {
84       @Override
missingImplementedInterface(String origin, String target)85       public void missingImplementedInterface(String origin, String target) {
86         throw new IllegalStateException(
87             String.format(
88                 "Couldn't find interface %s on the classpath for desugaring %s", target, origin));
89       }
90     };
91 
92     @Override
93     @Nullable
toByteArray()94     public final byte[] toByteArray() {
95       return null;
96     }
97   }
98 }
99