aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar shahan <shahan@google.com>2018-01-29 11:57:31 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-01-29 11:59:31 -0800
commit70c2e051e9b8db92228845b04d10b570ded8bfb7 (patch)
tree1dadb854aac345cdae8cf81412c0921a0132f5e6
parent42d62185f6f22ee836a703f58a25f671c367c9ab (diff)
Allows @AutoCodec to use factory methods.
Generalizes @AutoCodec.Constructor to @AutoCodec.Instantiator. PiperOrigin-RevId: 183702768
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/LanguageDependentFragment.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/ServerDirectories.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/FlagList.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java75
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/util/RegexFilter.java2
24 files changed, 90 insertions, 61 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java b/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
index bbae6b4c20..d121a3dfe9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
@@ -66,7 +66,7 @@ public final class BlazeDirectories {
private final Path localOutputPath;
private final String productName;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
public BlazeDirectories(ServerDirectories serverDirectories, Path workspace, String productName) {
this.serverDirectories = serverDirectories;
this.workspace = workspace;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/LanguageDependentFragment.java b/src/main/java/com/google/devtools/build/lib/analysis/LanguageDependentFragment.java
index 82bbef3af8..56c22f1f6f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/LanguageDependentFragment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/LanguageDependentFragment.java
@@ -52,7 +52,7 @@ public final class LanguageDependentFragment implements TransitiveInfoProvider {
private final String displayName;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
public LibraryLanguage(String displayName) {
this.displayName = displayName;
}
@@ -80,7 +80,7 @@ public final class LanguageDependentFragment implements TransitiveInfoProvider {
private final Label label;
private final ImmutableSet<LibraryLanguage> languages;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
public LanguageDependentFragment(Label label, ImmutableSet<LibraryLanguage> languages) {
this.label = label;
this.languages = languages;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
index ff12670bda..021c673010 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
@@ -45,7 +45,7 @@ public class PlatformConfiguration extends BuildConfiguration.Fragment {
private final ImmutableMap<Label, Label> toolchainResolutionOverrides;
private final ImmutableList<Label> enabledToolchainTypes;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
PlatformConfiguration(
Label executionPlatform,
ImmutableList<Label> extraExecutionPlatforms,
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ServerDirectories.java b/src/main/java/com/google/devtools/build/lib/analysis/ServerDirectories.java
index c653c8c9ba..6797cb21a2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ServerDirectories.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ServerDirectories.java
@@ -53,7 +53,7 @@ public final class ServerDirectories {
Strings.isNullOrEmpty(installMD5) ? null : checkMD5(HashCode.fromString(installMD5)));
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
ServerDirectories(Path installBase, Path outputBase, HashCode installMD5) {
this.installBase = installBase;
this.outputBase = outputBase;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java b/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
index d367ceec6a..a09a1ce8df 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/RunUnderConverter.java
@@ -65,7 +65,7 @@ public class RunUnderConverter implements Converter<RunUnder> {
private final Label runUnderLabel;
private final ImmutableList<String> runUnderList;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
RunUnderLabel(String input, Label runUnderLabel, ImmutableList<String> runUnderList) {
this.input = input;
this.runUnderLabel = runUnderLabel;
@@ -126,7 +126,7 @@ public class RunUnderConverter implements Converter<RunUnder> {
private final String runUnderCommand;
private final ImmutableList<String> runUnderList;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
RunUnderCommand(String input, String runUnderCommand, ImmutableList<String> runUnderList) {
this.input = input;
this.runUnderCommand = runUnderCommand;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfiguration.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfiguration.java
index 00f2f9e4ea..a29c105d03 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfiguration.java
@@ -123,7 +123,7 @@ public class BazelConfiguration extends Fragment {
this(os, options.useStrictActionEnv, determineShellExecutable(os, options.shellExecutable));
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
BazelConfiguration(OS os, boolean useStrictActionEnv, PathFragment shellExecutable) {
this.os = os;
this.useStrictActionEnv = useStrictActionEnv;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
index d0952b8d7d..a6ff6b086b 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
@@ -164,7 +164,7 @@ public class BazelPythonConfiguration extends BuildConfiguration.Fragment {
private final Options options;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
BazelPythonConfiguration(Options options) {
this.options = options;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index 08d4a0c611..ec656b93ef 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -887,7 +887,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
}
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
AndroidConfiguration(
Label sdk,
String cpu,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index 375c6c9b7e..eaccc1eff9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -91,7 +91,7 @@ public class AppleConfiguration extends BuildConfiguration.Fragment {
private final boolean mandatoryMinimumVersion;
private final boolean objcProviderFromLinked;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
AppleConfiguration(AppleCommandLineOptions options, String iosCpu) {
this.options = options;
this.iosCpu = iosCpu;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
index 09a8936000..06976f3f5b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
@@ -50,7 +50,7 @@ public class SwiftConfiguration extends BuildConfiguration.Fragment {
this(options.enableWholeModuleOptimization, ImmutableList.copyOf(options.copts));
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
SwiftConfiguration(boolean enableWholeModuleOptimization, ImmutableList<String> copts) {
this.enableWholeModuleOptimization = enableWholeModuleOptimization;
this.copts = copts;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
index 287c8895c3..8ff00a46d7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
@@ -124,7 +124,7 @@ public final class ConfigFeatureFlagConfiguration extends BuildConfiguration.Fra
this(options.getFlagValues());
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
ConfigFeatureFlagConfiguration(ImmutableSortedMap<Label, String> flagValues) {
this.flagValues = flagValues;
this.flagHash = this.flagValues.isEmpty() ? null : hashFlags(this.flagValues);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index bc2959f7b8..058f34db51 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -336,7 +336,7 @@ public final class CppConfiguration extends BuildConfiguration.Fragment {
cppToolchainInfo);
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
CppConfiguration(
Label crosstoolTop,
CrosstoolFile crosstoolFile,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java
index 6e0c657715..135b70be3b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppToolchainInfo.java
@@ -230,7 +230,7 @@ public final class CppToolchainInfo {
}
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
CppToolchainInfo(
CToolchain toolchain,
PathFragment crosstoolTopPathFragment,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
index 0753fbfba5..7244b7f3dc 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
@@ -78,7 +78,7 @@ public class CrosstoolConfigurationLoader {
private final CrosstoolConfig.CrosstoolRelease proto;
private final String md5;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
CrosstoolFile(String location, CrosstoolConfig.CrosstoolRelease proto, String md5) {
this.location = location;
this.proto = proto;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FlagList.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FlagList.java
index 258cf630ce..ef992520b9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FlagList.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FlagList.java
@@ -39,7 +39,7 @@ public class FlagList implements Serializable {
private final String name;
private final ImmutableList<String> flags;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
OptionalFlag(String name, ImmutableList<String> flags) {
this.name = name;
this.flags = flags;
@@ -58,7 +58,7 @@ public class FlagList implements Serializable {
private final ImmutableList<OptionalFlag> optionalFlags;
private final ImmutableList<String> suffixFlags;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
FlagList(
ImmutableList<String> prefixFlags,
ImmutableList<OptionalFlag> optionalFlags,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index 4e8d9ceac2..e81118d36a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -229,7 +229,7 @@ public final class JavaConfiguration extends Fragment {
this.pluginList = ImmutableList.copyOf(javaOptions.pluginList);
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
JavaConfiguration(
ImmutableList<String> commandLineJavacFlags,
Label javaLauncherLabel,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
index 0d07d7393b..582453b982 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
@@ -108,7 +108,7 @@ public class J2ObjcConfiguration extends Fragment {
Optional.fromNullable(j2ObjcOptions.deadCodeReport));
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
J2ObjcConfiguration(
List<String> translationFlags,
boolean removeDeadCode,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
index 85bfaa4a06..6139c2a541 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
@@ -117,7 +117,7 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
this.appleSdk = objcOptions.appleSdk;
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
ObjcConfiguration(
DottedVersion iosSimulatorVersion,
String iosSimulatorDevice,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
index e1c1c073ff..2838f3a6c1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
@@ -225,7 +225,7 @@ public class ProtoConfiguration extends Fragment {
private final ImmutableList<String> ccProtoLibrarySourceSuffixes;
private final Options options;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
public ProtoConfiguration(Options options) {
this.protocOpts = ImmutableList.copyOf(options.protocOpts);
this.ccProtoLibraryHeaderSuffixes = ImmutableList.copyOf(options.ccProtoLibraryHeaderSuffixes);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
index 83da07b243..f8ac8bc2c3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
@@ -41,7 +41,7 @@ public class PythonConfiguration extends BuildConfiguration.Fragment {
private final TriState buildPythonZip;
private final boolean buildTransitiveRunfilesTrees;
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
PythonConfiguration(
PythonVersion defaultPythonVersion,
boolean ignorePythonVersionAttribute,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java
index a5bb4cd30b..a4f9fa7adb 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java
@@ -40,19 +40,19 @@ public @interface AutoCodec {
*/
enum Strategy {
/**
- * Uses a constructor of the class to synthesize a codec.
+ * Uses a constructor or factory method of the class to synthesize a codec.
*
* <p>This strategy depends on
*
* <ul>
- * <li>a designated constructor to inspect to generate the codec
+ * <li>a designated constructor or factory method to inspect to generate the codec
* <li>the parameters must match member fields on name and type.
* </ul>
*
- * <p>If there is a unique constructor, that is the designated constructor, otherwise one must
- * be selected using the {@link AutoCodec.Constructor} annotation.
+ * <p>If there is a unique constructor, @AutoCodec may select that as the default instantiator,
+ * otherwise one must be selected using the {@link AutoCodec.Instantiator} annotation.
*/
- CONSTRUCTOR,
+ INSTANTIATOR,
/**
* Uses the public fields to infer serialization code.
*
@@ -70,18 +70,18 @@ public @interface AutoCodec {
}
/**
- * Marks a specific constructor when using the CONSTRUCTOR strategy.
+ * Marks a specific method when using the INSTANTIATOR strategy.
*
- * <p>Indicates a constructor for codec generation. A compile-time error will result if multiple
- * constructors are thus tagged.
+ * <p>Indicates an instantiator, either a constructor or factory method, for codec generation. A
+ * compile-time error will result if multiple methods are thus tagged.
*/
- @Target(ElementType.CONSTRUCTOR)
- @interface Constructor {}
+ @Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
+ @interface Instantiator {}
/**
* Marks a specific constructor parameter as a dependency.
*
- * <p>When a constructor selected for the {@code CONSTRUCTOR} strategy has one of its parameters
+ * <p>When a constructor selected for the {@code INSTANTIATOR} strategy has one of its parameters
* tagged {@code @Dependency}, {@code @AutoCodec} generates an {@link
* com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec} instead of the usual
* {@link com.google.devtools.build.lib.skyframe.serialization.ObjectCodec} with the dependency
@@ -97,7 +97,7 @@ public @interface AutoCodec {
@Target(ElementType.PARAMETER)
@interface Dependency {}
- Strategy strategy() default Strategy.CONSTRUCTOR;
+ Strategy strategy() default Strategy.INSTANTIATOR;
/**
* Specifies a deserialization dependency.
*
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java
index 052aa242b2..52f060f8cb 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodecProcessor.java
@@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.Nullable;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
@@ -40,6 +41,7 @@ import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
@@ -97,8 +99,8 @@ public class AutoCodecProcessor extends AbstractProcessor {
@Nullable TypeElement dependencyType = getDependencyType(annotation);
TypeSpec.Builder codecClassBuilder = null;
switch (annotation.strategy()) {
- case CONSTRUCTOR:
- codecClassBuilder = buildClassWithConstructorStrategy(encodedType, dependencyType);
+ case INSTANTIATOR:
+ codecClassBuilder = buildClassWithInstantiatorStrategy(encodedType, dependencyType);
break;
case PUBLIC_FIELDS:
codecClassBuilder = buildClassWithPublicFieldsStrategy(encodedType, dependencyType);
@@ -145,9 +147,9 @@ public class AutoCodecProcessor extends AbstractProcessor {
}
}
- private TypeSpec.Builder buildClassWithConstructorStrategy(
+ private TypeSpec.Builder buildClassWithInstantiatorStrategy(
TypeElement encodedType, @Nullable TypeElement dependency) {
- ExecutableElement constructor = selectConstructorForConstructorStrategy(encodedType);
+ ExecutableElement constructor = selectInstantiator(encodedType);
PartitionedParameters parameters = isolateDependency(constructor);
if (dependency != null) {
if (parameters.dependency != null) {
@@ -165,7 +167,7 @@ public class AutoCodecProcessor extends AbstractProcessor {
initializeUnsafeOffsets(codecClassBuilder, encodedType, parameters.fields);
- codecClassBuilder.addMethod(buildSerializeMethodWithConstructor(encodedType, parameters));
+ codecClassBuilder.addMethod(buildSerializeMethodWithInstantiator(encodedType, parameters));
MethodSpec.Builder deserializeBuilder =
AutoCodecUtil.initializeDeserializeMethodBuilder(encodedType, parameters.dependency);
@@ -206,33 +208,52 @@ public class AutoCodecProcessor extends AbstractProcessor {
return result;
}
- private static ExecutableElement selectConstructorForConstructorStrategy(
- TypeElement encodedType) {
+ private ExecutableElement selectInstantiator(TypeElement encodedType) {
List<ExecutableElement> constructors =
ElementFilter.constructorsIn(encodedType.getEnclosedElements());
- ImmutableList<ExecutableElement> markedConstructors =
- constructors
+ Stream<ExecutableElement> factoryMethods =
+ ElementFilter.methodsIn(encodedType.getEnclosedElements())
.stream()
- .filter(c -> c.getAnnotation(AutoCodec.Constructor.class) != null)
+ .filter(AutoCodecProcessor::hasInstantiatorAnnotation)
+ .peek(m -> verifyFactoryMethod(encodedType, m));
+ ImmutableList<ExecutableElement> markedInstantiators =
+ Stream.concat(
+ constructors.stream().filter(AutoCodecProcessor::hasInstantiatorAnnotation),
+ factoryMethods)
.collect(toImmutableList());
- if (markedConstructors.isEmpty()) {
+ if (markedInstantiators.isEmpty()) {
// If nothing is marked, see if there is a unique constructor.
if (constructors.size() > 1) {
throw new IllegalArgumentException(
encodedType.getQualifiedName()
- + " has multiple constructors but no Constructor annotation.");
+ + " has multiple constructors but no Instantiator annotation.");
}
// In Java, every class has at least one constructor, so this never fails.
return constructors.get(0);
}
- if (markedConstructors.size() == 1) {
- return markedConstructors.get(0);
+ if (markedInstantiators.size() == 1) {
+ return markedInstantiators.get(0);
}
throw new IllegalArgumentException(
- encodedType.getQualifiedName() + " has multiple Constructor annotations.");
+ encodedType.getQualifiedName() + " has multiple Instantiator annotations.");
}
- private MethodSpec buildSerializeMethodWithConstructor(
+ private static boolean hasInstantiatorAnnotation(Element elt) {
+ return elt.getAnnotation(AutoCodec.Instantiator.class) != null;
+ }
+
+ private void verifyFactoryMethod(TypeElement encodedType, ExecutableElement elt) {
+ if (!elt.getModifiers().contains(Modifier.STATIC)
+ || !env.getTypeUtils().isSubtype(elt.getReturnType(), encodedType.asType())) {
+ throw new IllegalArgumentException(
+ encodedType.getQualifiedName()
+ + " tags "
+ + elt.getSimpleName()
+ + " as an Instantiator, but it's not a valid factory method.");
+ }
+ }
+
+ private MethodSpec buildSerializeMethodWithInstantiator(
TypeElement encodedType, PartitionedParameters parameters) {
MethodSpec.Builder serializeBuilder =
AutoCodecUtil.initializeSerializeMethodBuilder(encodedType, parameters.dependency);
@@ -379,28 +400,36 @@ public class AutoCodecProcessor extends AbstractProcessor {
}
/**
- * Invokes the constructor and returns the value.
+ * Invokes the instantiator and returns the value.
*
- * <p>Used by the {@link AutoCodec.Strategy.CONSTRUCTOR} strategy.
+ * <p>Used by the {@link AutoCodec.Strategy.INSTANTIATOR} strategy.
*/
private static void addReturnNew(
- MethodSpec.Builder builder, TypeElement type, ExecutableElement constructor) {
- List<? extends TypeMirror> allThrown = constructor.getThrownTypes();
+ MethodSpec.Builder builder, TypeElement type, ExecutableElement instantiator) {
+ List<? extends TypeMirror> allThrown = instantiator.getThrownTypes();
if (!allThrown.isEmpty()) {
builder.beginControlFlow("try");
}
String parameters =
- constructor
+ instantiator
.getParameters()
.stream()
.map(AutoCodecProcessor::handleFromParameter)
.collect(Collectors.joining(", "));
- builder.addStatement("return new $T($L)", TypeName.get(type.asType()), parameters);
+ if (instantiator.getKind().equals(ElementKind.CONSTRUCTOR)) {
+ builder.addStatement("return new $T($L)", TypeName.get(type.asType()), parameters);
+ } else { // Otherwise, it's a factory method.
+ builder.addStatement(
+ "return $T.$L($L)",
+ TypeName.get(type.asType()),
+ instantiator.getSimpleName(),
+ parameters);
+ }
if (!allThrown.isEmpty()) {
for (TypeMirror thrown : allThrown) {
builder.nextControlFlow("catch ($T e)", TypeName.get(thrown));
builder.addStatement(
- "throw new $T(\"$L constructor threw an exception\", e)",
+ "throw new $T(\"$L instantiator threw an exception\", e)",
SerializationException.class,
type.getQualifiedName());
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
index 4706fa2f3b..9edf92777e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
@@ -87,7 +87,7 @@ public abstract class LineNumberTable implements Serializable {
this(computeLinestart(buffer), path, buffer.length);
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
Regular(int[] linestart, PathFragment path, int bufferLength) {
this.linestart = linestart;
this.path = path;
@@ -262,7 +262,7 @@ public abstract class LineNumberTable implements Serializable {
buffer.length);
}
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
HashLine(ImmutableList<SingleHashLine> table, PathFragment defaultPath, int bufferLength) {
this.table = table;
this.defaultPath = defaultPath;
diff --git a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
index 4d3b7ef670..c64ea5157e 100644
--- a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
+++ b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java
@@ -91,7 +91,7 @@ public final class RegexFilter {
* <p>Null {@code inclusionPattern} or {@code exclusionPattern} means that inclusion or exclusion
* matching will not be applied, respectively.
*/
- @AutoCodec.Constructor
+ @AutoCodec.Instantiator
RegexFilter(@Nullable Pattern inclusionPattern, @Nullable Pattern exclusionPattern) {
this.inclusionPattern = inclusionPattern;
this.exclusionPattern = exclusionPattern;