aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec/AutoCodec.java
blob: be6a2bb47b9b665911a9fd815a12c80bef80a9be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.skyframe.serialization.autocodec;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

/**
 * Specifies that AutoCodec should generate a codec implementation for the annotated class.
 *
 * <p>Example:
 *
 * <pre>{@code
 * @AutoCodec
 * class Target {
 *   public static final ObjectCodec<Target> CODEC = new Target_AutoCodec();
 * }
 * }</pre>
 *
 * The {@code _AutoCodec} suffix is added to the {@code Target} to obtain the generated class name.
 */
@Target(ElementType.TYPE)
public @interface AutoCodec {
  /**
   * AutoCodec recursively derives a codec using the public interfaces of the class.
   *
   * <p>Specific strategies are described below.
   */
  enum Strategy {
    /**
     * Uses a constructor or factory method of the class to synthesize a codec.
     *
     * <p>This strategy depends on
     *
     * <ul>
     *   <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, @AutoCodec may select that as the default instantiator,
     * otherwise one must be selected using the {@link AutoCodec.Instantiator} annotation.
     */
    INSTANTIATOR,
    /**
     * Uses the public fields to infer serialization code.
     *
     * <p>Serializes each public field. Calls the no-arg constructor of the class to instantiate an
     * instance for deserialization.
     */
    PUBLIC_FIELDS,
    /**
     * For use with abstract classes (enforced at compile time).
     *
     * <p>Uses reflection to determine the concrete subclass, stores the name of the subclass and
     * uses its codec to serialize the data.
     */
    POLYMORPHIC,
    /**
     * For use with classes that are singleton.
     *
     * <p>Commonly used with the POLYMORPHIC strategy.
     *
     * <p>The serialized class must have a codec accessible, static INSTANCE field.
     *
     * <p>Illegal to use with a non-Void dependency.
     */
    SINGLETON
  }

  /**
   * Marks a specific method when using the INSTANTIATOR strategy.
   *
   * <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, ElementType.METHOD})
  @interface Instantiator {}

  /**
   * Marks a specific constructor parameter as a dependency.
   *
   * <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
   * type parameter matching the tagged parameter type.
   *
   * <p>At deserialization, the {@code @Dependency} tagged parameter will be forwarded from the
   * {@code dependency} parameter of {@link
   * com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec#deserialize}.
   *
   * <p>A compiler error will result if more than one constructor parameter has the
   * {@code @Dependency} annotation or if the annotation itself has a dependency element.
   */
  @Target(ElementType.PARAMETER)
  @interface Dependency {}

  Strategy strategy() default Strategy.INSTANTIATOR;
  /**
   * Specifies a deserialization dependency.
   *
   * <p>When non-{@link Void}, 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
   * type parameter matching the returned type.
   *
   * <p>It is an error to use this in conjunction with {@code @AutoCodec.Dependency}.
   */
  Class<?> dependency() default Void.class;

  /**
   * Signals that the annotated element is only visible for use by serialization. It should not be
   * used by other callers.
   *
   * <p>TODO(janakr): Add an ErrorProne checker to enforce this.
   */
  @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
  @interface VisibleForSerialization {}
}