Skip to content

Commit e72ded3

Browse files
committed
Merge pull request #235 from google/moe_writing_branch_from_061401e8f8d2b201f88f2bfd7509a49b2433685c
Merge from moe writing branch from 061401e
2 parents 5839c28 + acc0ea3 commit e72ded3

File tree

17 files changed

+584
-136
lines changed

17 files changed

+584
-136
lines changed

common/README.md

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,26 @@ Auto Common Utilities
33

44
## Overview
55

6-
The Auto project has a set of common utilities to help ease use of the annotation processing environment.
6+
The Auto project has a set of common utilities to help ease use of the annotation processing
7+
environment.
78

89
## Utility classes of note
910

1011
* MoreTypes - utilities and Equivalence wrappers for TypeMirror and related subtypes
1112
* MoreElements - utilities for Element and related subtypes
12-
* SuperficialValidation - very simple scanner to ensure an Element is valid and free from distortion from upstream compilation errors
13+
* SuperficialValidation - very simple scanner to ensure an Element is valid and free from
14+
distortion from upstream compilation errors
1315
* Visibility - utilities for working with Elements' visibility levels (public, protected, etc.)
16+
* BasicAnnotationProcessor/ProcessingStep - simple types that
17+
- implement a validating annotation processor
18+
- defer invalid elements until later
19+
- break processor actions into multiple steps (which may each handle different annotations)
1420

1521
## Usage/Setup
1622

17-
Auto common utilities have a standard maven setup which can be used from Gradle, Ivy, Ant, or other systems which consume binary artifacts from the central maven repositories.
23+
Auto common utilities have a standard [Maven](http://maven.apache.org) setup which can also be
24+
used from Gradle, Ivy, Ant, or other systems which consume binary artifacts from the central Maven
25+
binary artifact repositories.
1826

1927
```xml
2028
<dependency>
@@ -23,3 +31,49 @@ Auto common utilities have a standard maven setup which can be used from Gradle,
2331
<version>1.0-SNAPSHOT</version> <!-- or use a known release version -->
2432
</dependency>
2533
```
34+
35+
## Processor Resilience
36+
37+
Auto Common Utilities is used by a variety of annotation processors in Google and new versions
38+
may have breaking changes. Users of auto-common are urged to use
39+
[shade](https://maven.apache.org/plugins/maven-shade-plugin/) or
40+
[jarjar](https://code.google.com/p/jarjar/) (or something similar) in packaging their processors
41+
so that conflicting versions of this library do not adversely interact with each other.
42+
43+
For example, in a Maven build you can repackage `com.google.auto.common` into
44+
`your.processor.shaded.auto.common` like this:
45+
46+
```xml
47+
<project>
48+
<!-- your other config -->
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<artifactId>maven-shade-plugin</artifactId>
53+
<executions>
54+
<execution>
55+
<phase>package</phase>
56+
<goals>
57+
<goal>shade</goal>
58+
</goals>
59+
<configuration>
60+
<artifactSet>
61+
<excludes>
62+
<!-- exclude dependencies you don't want to bundle in your processor -->
63+
</excludes>
64+
</artifactSet>
65+
<relocations>
66+
<relocation>
67+
<pattern>com.google.auto.common</pattern>
68+
<shadedPattern>your.processor.shaded.auto.common</shadedPattern>
69+
</relocation>
70+
</relocations>
71+
</configuration>
72+
</execution>
73+
</executions>
74+
</plugin>
75+
</plugins>
76+
</build>
77+
</project>
78+
```
79+

common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.collect.ImmutableList;
2323
import com.google.common.collect.ImmutableSet;
2424
import com.google.common.collect.SetMultimap;
25+
import com.google.common.collect.Sets;
2526
import com.google.testing.compile.JavaFileObjects;
2627

2728
import org.junit.Test;
@@ -38,15 +39,17 @@
3839
import javax.lang.model.SourceVersion;
3940
import javax.lang.model.element.Element;
4041
import javax.tools.JavaFileObject;
41-
import javax.tools.StandardLocation;
4242

4343
@RunWith(JUnit4.class)
4444
public class BasicAnnotationProcessorTest {
45+
46+
private Set<Element> elementsGeneratingCode = Sets.newHashSet();
47+
4548
@Retention(RetentionPolicy.SOURCE)
4649
public @interface RequiresGeneratedCode {}
4750

4851
/** Asserts that the code generated by {@link GeneratesCode} and its processor is present. */
49-
public static class RequiresGeneratedCodeProcessor extends BasicAnnotationProcessor {
52+
public class RequiresGeneratedCodeProcessor extends BasicAnnotationProcessor {
5053
boolean processed = false;
5154

5255
@Override
@@ -61,12 +64,7 @@ protected Iterable<? extends ProcessingStep> initSteps() {
6164
public void process(
6265
SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
6366
processed = true;
64-
try {
65-
processingEnv.getFiler()
66-
.getResource(StandardLocation.SOURCE_OUTPUT, "test", "SomeGeneratedClass");
67-
} catch (IOException e) {
68-
throw new AssertionError(e);
69-
}
67+
assertThat(elementsGeneratingCode).isNotEmpty();
7068
}
7169

7270
@Override
@@ -81,7 +79,8 @@ public Set<? extends Class<? extends Annotation>> annotations() {
8179
public @interface GeneratesCode {}
8280

8381
/** Generates a class called {@code test.SomeGeneratedClass}. */
84-
public static class GeneratesCodeProcessor extends BasicAnnotationProcessor {
82+
public class GeneratesCodeProcessor extends BasicAnnotationProcessor {
83+
8584
@Override
8685
public SourceVersion getSupportedSourceVersion() {
8786
return SourceVersion.latestSupported();
@@ -109,7 +108,9 @@ public Set<? extends Class<? extends Annotation>> annotations() {
109108
});
110109
}
111110

111+
// TODO(gak): Use jimfs to simulate the file system.
112112
private void generateClass(Element sourceType) throws IOException {
113+
elementsGeneratingCode.add(sourceType);
113114
JavaFileObject source =
114115
processingEnv.getFiler().createSourceFile("test.SomeGeneratedClass", sourceType);
115116
PrintWriter writer = new PrintWriter(source.openWriter());

factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.common.collect.ImmutableList;
2525
import com.google.common.collect.ImmutableListMultimap;
2626
import com.google.common.collect.ImmutableSet;
27+
import com.google.common.collect.ImmutableSetMultimap;
2728
import com.google.common.collect.ImmutableSortedSet;
2829
import com.google.common.collect.Iterables;
2930
import com.google.common.collect.Multimaps;
@@ -97,25 +98,30 @@ private void doProcess(RoundEnvironment roundEnv) {
9798

9899
ImmutableListMultimap.Builder<String, FactoryMethodDescriptor> indexedMethods =
99100
ImmutableListMultimap.builder();
100-
ImmutableSet.Builder<ImplementationMethodDescriptor> implementationMethodDescriptors =
101-
ImmutableSet.builder();
101+
ImmutableSetMultimap.Builder<String, ImplementationMethodDescriptor>
102+
implementationMethodDescriptorsBuilder = ImmutableSetMultimap.builder();
102103
for (Element element : roundEnv.getElementsAnnotatedWith(AutoFactory.class)) {
103104
Optional<AutoFactoryDeclaration> declaration = declarationFactory.createIfValid(element);
104105
if (declaration.isPresent()) {
106+
String factoryName = declaration.get().getFactoryName(
107+
elements.getPackageOf(element).getQualifiedName(),
108+
getAnnotatedType(element).getSimpleName());
109+
105110
TypeElement extendingType = declaration.get().extendingType();
106111
List<ExecutableElement> supertypeMethods =
107112
ElementFilter.methodsIn(elements.getAllMembers(extendingType));
108113
for (ExecutableElement supertypeMethod : supertypeMethods) {
109114
if (supertypeMethod.getModifiers().contains(Modifier.ABSTRACT)) {
110115
ExecutableType methodType = Elements2.getExecutableElementAsMemberOf(
111116
types, supertypeMethod, extendingType);
112-
implementationMethodDescriptors.add(new ImplementationMethodDescriptor.Builder()
113-
.name(supertypeMethod.getSimpleName().toString())
114-
.returnType(getAnnotatedType(element).getQualifiedName().toString())
115-
.publicMethod()
116-
.passedParameters(Parameter.forParameterList(
117-
supertypeMethod.getParameters(), methodType.getParameterTypes()))
118-
.build());
117+
implementationMethodDescriptorsBuilder.put(factoryName,
118+
new ImplementationMethodDescriptor.Builder()
119+
.name(supertypeMethod.getSimpleName().toString())
120+
.returnType(getAnnotatedType(element).getQualifiedName().toString())
121+
.publicMethod()
122+
.passedParameters(Parameter.forParameterList(
123+
supertypeMethod.getParameters(), methodType.getParameterTypes()))
124+
.build());
119125
}
120126
}
121127
for (TypeElement implementingType : declaration.get().implementingTypes()) {
@@ -125,13 +131,14 @@ private void doProcess(RoundEnvironment roundEnv) {
125131
if (interfaceMethod.getModifiers().contains(Modifier.ABSTRACT)) {
126132
ExecutableType methodType = Elements2.getExecutableElementAsMemberOf(
127133
types, interfaceMethod, implementingType);
128-
implementationMethodDescriptors.add(new ImplementationMethodDescriptor.Builder()
129-
.name(interfaceMethod.getSimpleName().toString())
130-
.returnType(getAnnotatedType(element).getQualifiedName().toString())
131-
.publicMethod()
132-
.passedParameters(Parameter.forParameterList(
133-
interfaceMethod.getParameters(), methodType.getParameterTypes()))
134-
.build());
134+
implementationMethodDescriptorsBuilder.put(factoryName,
135+
new ImplementationMethodDescriptor.Builder()
136+
.name(interfaceMethod.getSimpleName().toString())
137+
.returnType(getAnnotatedType(element).getQualifiedName().toString())
138+
.publicMethod()
139+
.passedParameters(Parameter.forParameterList(
140+
interfaceMethod.getParameters(), methodType.getParameterTypes()))
141+
.build());
135142
}
136143
}
137144
}
@@ -147,6 +154,9 @@ private void doProcess(RoundEnvironment roundEnv) {
147154
}));
148155
}
149156

157+
ImmutableSetMultimap<String, ImplementationMethodDescriptor>
158+
implementationMethodDescriptors = implementationMethodDescriptorsBuilder.build();
159+
150160
for (Entry<String, Collection<FactoryMethodDescriptor>> entry
151161
: indexedMethods.build().asMap().entrySet()) {
152162
ImmutableSet.Builder<String> extending = ImmutableSet.builder();
@@ -180,8 +190,7 @@ private void doProcess(RoundEnvironment roundEnv) {
180190
implementing.build(),
181191
publicType,
182192
ImmutableSet.copyOf(entry.getValue()),
183-
// TODO(gak): this needs to be indexed too
184-
implementationMethodDescriptors.build(),
193+
implementationMethodDescriptors.get(entry.getKey()),
185194
allowSubclasses));
186195
} catch (IOException e) {
187196
messager.printMessage(Kind.ERROR, "failed");

0 commit comments

Comments
 (0)