Skip to content

Commit ed20643

Browse files
committed
Directly include RequestOptions in ReqestBuilder using CRGP
https://www.artima.com/weblogs/viewpost.jsp?thread=133275 This means that you can write: Glide.with(context) .load(url) .placeholder(R.drawable.placeholder) .into(imageView); Instead of: Glide.with(contex) .apply(placeholderOf(R.drawable.placeholder) .into(imageView); Without using the generated API. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=211640993
1 parent 092e062 commit ed20643

File tree

42 files changed

+3890
-8010
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3890
-8010
lines changed

annotation/compiler/src/main/java/com/bumptech/glide/annotation/compiler/AppModuleProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ boolean maybeWriteAppModule() {
8888
writeRequestOptions(generatedCodePackageName, generatedRequestOptions);
8989

9090
TypeSpec generatedRequestBuilder =
91-
requestBuilderGenerator.generate(generatedCodePackageName, generatedRequestOptions);
91+
requestBuilderGenerator.generate(generatedCodePackageName, indexedClassNames.extensions);
9292
writeRequestBuilder(generatedCodePackageName, generatedRequestBuilder);
9393

9494
TypeSpec requestManager =
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.bumptech.glide.annotation.compiler;
2+
3+
/**
4+
* Generates unique field ids for classes generated by Glide's annotation processor.
5+
*/
6+
final class FieldUniqueIdGenerator {
7+
private static int nextStaticFieldUniqueId;
8+
9+
private FieldUniqueIdGenerator() {
10+
// Utility class.
11+
}
12+
13+
static int next() {
14+
return nextStaticFieldUniqueId++;
15+
}
16+
}

annotation/compiler/src/main/java/com/bumptech/glide/annotation/compiler/GlideExtensionValidator.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ private void validateNewGlideOption(ExecutableElement executableElement) {
100100
validateNewGlideOptionAnnotations(executableElement);
101101
validateGlideOptionParameters(executableElement);
102102
TypeMirror returnType = executableElement.getReturnType();
103-
if (!isRequestOptions(returnType)) {
104-
throw new IllegalArgumentException("@GlideOption methods should return a RequestOptions"
105-
+ " object, but " + getQualifiedMethodName(executableElement) + " returns " + returnType
106-
+ ". If you're using old style @GlideOption methods, your method may have a void return"
107-
+ " type, but doing so is deprecated and support will be removed in a future version");
103+
if (!isBaseRequestOptions(returnType)) {
104+
throw new IllegalArgumentException("@GlideOption methods should return a"
105+
+ " BaseRequestOptions<?> object, but " + getQualifiedMethodName(executableElement)
106+
+ " returns " + returnType + ". If you're using old style @GlideOption methods, your"
107+
+ " method may have a void return type, but doing so is deprecated and support will be"
108+
+ " removed in a future version");
108109
}
109110
validateGlideOptionOverride(executableElement);
110111
}
@@ -122,45 +123,45 @@ private void validateDeprecatedGlideOption(ExecutableElement executableElement)
122123
private static void validateGlideOptionParameters(ExecutableElement executableElement) {
123124
if (executableElement.getParameters().isEmpty()) {
124125
throw new IllegalArgumentException("@GlideOption methods must take a "
125-
+ "RequestOptions object as their first parameter, but "
126+
+ "BaseRequestOptions<?> object as their first parameter, but "
126127
+ getQualifiedMethodName(executableElement) + " has none");
127128
}
128129
VariableElement first = executableElement.getParameters().get(0);
129130
TypeMirror expected = first.asType();
130-
if (!isRequestOptions(expected)) {
131+
if (!isBaseRequestOptions(expected)) {
131132
throw new IllegalArgumentException("@GlideOption methods must take a"
132-
+ " RequestOptions object as their first parameter, but the first parameter in "
133+
+ " BaseRequestOptions<?> object as their first parameter, but the first parameter in "
133134
+ getQualifiedMethodName(executableElement) + " is " + expected);
134135
}
135136
}
136137

137-
private static boolean isRequestOptions(TypeMirror typeMirror) {
138-
return typeMirror.toString().equals("com.bumptech.glide.request.RequestOptions");
138+
private static boolean isBaseRequestOptions(TypeMirror typeMirror) {
139+
return typeMirror.toString().equals("com.bumptech.glide.request.BaseRequestOptions<?>");
139140
}
140141

141142
private void validateGlideOptionOverride(ExecutableElement element) {
142143
int overrideType = processorUtil.getOverrideType(element);
143-
boolean isOverridingRequestOptionsMethod = isMethodInRequestOptions(element);
144-
if (isOverridingRequestOptionsMethod && overrideType == GlideOption.OVERRIDE_NONE) {
144+
boolean isOverridingBaseRequestOptionsMethod = isMethodInBaseRequestOptions(element);
145+
if (isOverridingBaseRequestOptionsMethod && overrideType == GlideOption.OVERRIDE_NONE) {
145146
throw new IllegalArgumentException("Accidentally attempting to override a method in"
146-
+ " RequestOptions. Add an 'override' value in the @GlideOption annotation"
147+
+ " BaseRequestOptions. Add an 'override' value in the @GlideOption annotation"
147148
+ " if this is intentional. Offending method: "
148149
+ getQualifiedMethodName(element));
149-
} else if (!isOverridingRequestOptionsMethod && overrideType != GlideOption.OVERRIDE_NONE) {
150+
} else if (!isOverridingBaseRequestOptionsMethod && overrideType != GlideOption.OVERRIDE_NONE) {
150151
throw new IllegalArgumentException("Requested to override an existing method in"
151-
+ " RequestOptions, but no such method was found. Offending method: "
152+
+ " BaseRequestOptions, but no such method was found. Offending method: "
152153
+ getQualifiedMethodName(element));
153154
}
154155
}
155156

156-
private boolean isMethodInRequestOptions(ExecutableElement toFind) {
157+
private boolean isMethodInBaseRequestOptions(ExecutableElement toFind) {
157158
// toFind is a method in a GlideExtension whose first argument is a BaseRequestOptions<?> type.
158159
// Since we're comparing against methods in BaseRequestOptions itself, we need to drop that
159160
// first type.
160161
TypeElement requestOptionsType =
161162
processingEnvironment
162163
.getElementUtils()
163-
.getTypeElement(RequestOptionsGenerator.REQUEST_OPTIONS_QUALIFIED_NAME);
164+
.getTypeElement(RequestOptionsGenerator.BASE_REQUEST_OPTIONS_QUALIFIED_NAME);
164165
List<String> toFindParameterNames = getComparableParameterNames(toFind, true /*skipFirst*/);
165166
String toFindSimpleName = toFind.getSimpleName().toString();
166167
for (Element element : requestOptionsType.getEnclosedElements()) {

annotation/compiler/src/main/java/com/bumptech/glide/annotation/compiler/RequestBuilderGenerator.java

Lines changed: 18 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.bumptech.glide.annotation.GlideOption;
88
import com.google.common.base.Function;
99
import com.google.common.base.Joiner;
10-
import com.google.common.base.Predicate;
1110
import com.google.common.collect.FluentIterable;
1211
import com.google.common.collect.ImmutableList;
1312
import com.google.common.collect.ImmutableSet;
@@ -23,12 +22,8 @@
2322
import com.squareup.javapoet.TypeVariableName;
2423
import com.squareup.javapoet.WildcardTypeName;
2524
import java.io.File;
26-
import java.util.ArrayList;
27-
import java.util.Collections;
28-
import java.util.HashSet;
2925
import java.util.List;
3026
import java.util.Set;
31-
import javax.annotation.Nullable;
3227
import javax.annotation.processing.ProcessingEnvironment;
3328
import javax.lang.model.element.AnnotationMirror;
3429
import javax.lang.model.element.ExecutableElement;
@@ -113,12 +108,11 @@ final class RequestBuilderGenerator {
113108

114109
private final ProcessingEnvironment processingEnv;
115110
private final ProcessorUtil processorUtil;
116-
private ClassName generatedRequestBuilderClassName;
111+
private final RequestOptionsOverrideGenerator requestOptionsOverrideGenerator;
117112
private final TypeVariableName transcodeTypeName;
118-
private ParameterizedTypeName generatedRequestBuilderOfTranscodeType;
119113
private final TypeElement requestOptionsType;
120114
private final TypeElement requestBuilderType;
121-
private ClassName requestOptionsClassName;
115+
private ClassName generatedRequestBuilderClassName;
122116

123117
RequestBuilderGenerator(ProcessingEnvironment processingEnv, ProcessorUtil processorUtil) {
124118
this.processingEnv = processingEnv;
@@ -131,29 +125,28 @@ final class RequestBuilderGenerator {
131125

132126
requestOptionsType = processingEnv.getElementUtils().getTypeElement(
133127
REQUEST_OPTIONS_QUALIFIED_NAME);
128+
129+
requestOptionsOverrideGenerator =
130+
new RequestOptionsOverrideGenerator(processingEnv, processorUtil);
134131
}
135132

136-
TypeSpec generate(String generatedCodePackageName, @Nullable TypeSpec generatedOptions) {
133+
TypeSpec generate(String generatedCodePackageName, Set<String> glideExtensionClassNames) {
137134
generatedRequestBuilderClassName =
138135
ClassName.get(generatedCodePackageName, GENERATED_REQUEST_BUILDER_SIMPLE_NAME);
139-
generatedRequestBuilderOfTranscodeType =
136+
ParameterizedTypeName generatedRequestBuilderOfTranscodeType =
140137
ParameterizedTypeName.get(generatedRequestBuilderClassName, transcodeTypeName);
141-
142-
if (generatedOptions != null) {
143-
requestOptionsClassName =
144-
ClassName.get(generatedCodePackageName, generatedOptions.name);
145-
} else {
146-
requestOptionsClassName =
147-
ClassName.get(
148-
RequestOptionsGenerator.REQUEST_OPTIONS_PACKAGE_NAME,
149-
RequestBuilderGenerator.REQUEST_OPTIONS_SIMPLE_NAME);
150-
}
138+
RequestOptionsExtensionGenerator requestOptionsExtensionGenerator =
139+
new RequestOptionsExtensionGenerator(generatedRequestBuilderOfTranscodeType, processorUtil);
151140

152141
ParameterizedTypeName requestBuilderOfTranscodeType =
153142
ParameterizedTypeName.get(
154143
ClassName.get(REQUEST_BUILDER_PACKAGE_NAME, REQUEST_BUILDER_SIMPLE_NAME),
155144
transcodeTypeName);
156145

146+
List<MethodSpec> requestOptionsExtensionMethods =
147+
requestOptionsExtensionGenerator.generateInstanceMethodsForExtensions(
148+
glideExtensionClassNames);
149+
157150
return TypeSpec.classBuilder(GENERATED_REQUEST_BUILDER_SIMPLE_NAME)
158151
.addJavadoc("Contains all public methods from {@link $T}, all options from\n",
159152
requestBuilderType)
@@ -176,8 +169,11 @@ TypeSpec generate(String generatedCodePackageName, @Nullable TypeSpec generatedO
176169
.addSuperinterface(Cloneable.class)
177170
.addMethods(generateConstructors())
178171
.addMethod(generateDownloadOnlyRequestMethod())
179-
.addMethods(generateGeneratedRequestOptionsEquivalents(generatedOptions))
172+
.addMethods(
173+
requestOptionsOverrideGenerator.generateInstanceMethodOverridesForRequestOptions(
174+
generatedRequestBuilderOfTranscodeType, EXCLUDED_METHODS_FROM_BASE_REQUEST_OPTIONS))
180175
.addMethods(generateRequestBuilderOverrides())
176+
.addMethods(requestOptionsExtensionMethods)
181177
.build();
182178
}
183179

@@ -198,6 +194,7 @@ public MethodSpec apply(ExecutableElement input) {
198194
});
199195
}
200196

197+
201198
/**
202199
* Generates an override of a particular method in {@code com.bumptech.glide.RequestBuilder} that
203200
* returns {@code com.bumptech.glide.RequestBuilder} so that it returns our generated subclass
@@ -245,152 +242,6 @@ public String apply(ParameterSpec input) {
245242
return builder.build();
246243
}
247244

248-
/**
249-
* Generates methods with equivalent names and arguments to methods annotated with
250-
* {@link GlideOption} in
251-
* {@link com.bumptech.glide.annotation.GlideExtension}s that return our generated
252-
* {@code com.bumptech.glide.RequestBuilder} subclass.
253-
*/
254-
private List<MethodSpec> generateGeneratedRequestOptionsEquivalents(
255-
@Nullable final TypeSpec generatedOptions) {
256-
if (generatedOptions == null) {
257-
return Collections.emptyList();
258-
}
259-
return FluentIterable
260-
.from(generatedOptions.methodSpecs)
261-
.filter(new Predicate<MethodSpec>() {
262-
@Override
263-
public boolean apply(MethodSpec input) {
264-
return isUsefulGeneratedRequestOption(input);
265-
}
266-
})
267-
.transform(new Function<MethodSpec, MethodSpec>() {
268-
@Override
269-
public MethodSpec apply(MethodSpec input) {
270-
return generateGeneratedRequestOptionEquivalent(input);
271-
}
272-
})
273-
.toList();
274-
}
275-
276-
/**
277-
* Returns {@code true} if the given {@link MethodSpec} is a useful method to have in our
278-
* {@code com.bumptech.glide.RequestBuilder} subclass.
279-
*
280-
* <p>Only newly generated methods will be included in the generated
281-
* {@code com.bumptech.glide.request.BaseRequestBuilder} subclass, so we only have to filter out
282-
* methods that override other methods to avoid duplicates.
283-
*/
284-
private boolean isUsefulGeneratedRequestOption(MethodSpec requestOptionMethod) {
285-
return
286-
!EXCLUDED_METHODS_FROM_BASE_REQUEST_OPTIONS.contains(requestOptionMethod.name)
287-
&& requestOptionMethod.hasModifier(Modifier.PUBLIC)
288-
&& !requestOptionMethod.hasModifier(Modifier.STATIC)
289-
&& requestOptionMethod.returnType.toString()
290-
.equals(requestOptionsClassName.toString());
291-
}
292-
293-
/**
294-
* Generates a particular method with an equivalent name and arguments to the given method
295-
* from the generated {@code com.bumptech.glide.request.BaseRequestBuilder} subclass.
296-
*/
297-
private MethodSpec generateGeneratedRequestOptionEquivalent(MethodSpec requestOptionMethod) {
298-
CodeBlock callRequestOptionsMethod = CodeBlock.builder()
299-
.add(".$N(", requestOptionMethod.name)
300-
.add(FluentIterable.from(requestOptionMethod.parameters)
301-
.transform(new Function<ParameterSpec, String>() {
302-
@Override
303-
public String apply(ParameterSpec input) {
304-
return input.name;
305-
}
306-
})
307-
.join(Joiner.on(", ")))
308-
.add(");\n")
309-
.build();
310-
311-
MethodSpec.Builder result = MethodSpec.methodBuilder(requestOptionMethod.name)
312-
.addJavadoc(
313-
processorUtil.generateSeeMethodJavadoc(requestOptionsClassName, requestOptionMethod))
314-
.addModifiers(Modifier.PUBLIC)
315-
.varargs(requestOptionMethod.varargs)
316-
.addAnnotations(
317-
FluentIterable.from(requestOptionMethod.annotations)
318-
.filter(new Predicate<AnnotationSpec>() {
319-
@Override
320-
public boolean apply(AnnotationSpec input) {
321-
return !input.type.equals(TypeName.get(Override.class))
322-
// SafeVarargs can only be applied to final methods. GlideRequest is
323-
// non-final to allow for mocking.
324-
&& !input.type.equals(TypeName.get(SafeVarargs.class))
325-
// We need to combine warnings below.
326-
&& !input.type.equals(TypeName.get(SuppressWarnings.class));
327-
}
328-
})
329-
.toList()
330-
)
331-
.addTypeVariables(requestOptionMethod.typeVariables)
332-
.addParameters(requestOptionMethod.parameters)
333-
.returns(generatedRequestBuilderOfTranscodeType)
334-
.beginControlFlow(
335-
"if (getMutableOptions() instanceof $T)", requestOptionsClassName)
336-
.addCode("this.requestOptions = (($T) getMutableOptions())",
337-
requestOptionsClassName)
338-
.addCode(callRequestOptionsMethod)
339-
.nextControlFlow("else")
340-
.addCode(CodeBlock.of("this.requestOptions = new $T().apply(this.requestOptions)",
341-
requestOptionsClassName))
342-
.addCode(callRequestOptionsMethod)
343-
.endControlFlow()
344-
.addStatement("return this");
345-
346-
AnnotationSpec suppressWarnings = buildSuppressWarnings(requestOptionMethod);
347-
if (suppressWarnings != null) {
348-
result.addAnnotation(suppressWarnings);
349-
}
350-
return result.build();
351-
}
352-
353-
@Nullable
354-
private AnnotationSpec buildSuppressWarnings(MethodSpec requestOptionMethod) {
355-
Set<String> suppressions = new HashSet<>();
356-
if (requestOptionMethod.annotations.contains(
357-
AnnotationSpec.builder(SuppressWarnings.class).build())) {
358-
for (AnnotationSpec annotation : requestOptionMethod.annotations) {
359-
if (annotation.type.equals(TypeName.get(SuppressWarnings.class))) {
360-
List<CodeBlock> codeBlocks = annotation.members.get("value");
361-
suppressions.addAll(FluentIterable.from(codeBlocks).transform(
362-
new Function<CodeBlock, String>() {
363-
@Override
364-
public String apply(CodeBlock input) {
365-
return input.toString();
366-
}
367-
}).toSet());
368-
}
369-
}
370-
}
371-
372-
if (requestOptionMethod.annotations.contains(
373-
AnnotationSpec.builder(SafeVarargs.class).build())) {
374-
suppressions.add("unchecked");
375-
suppressions.add("varargs");
376-
}
377-
378-
if (suppressions.isEmpty()) {
379-
return null;
380-
}
381-
// Enforce ordering across compilers (Internal and External compilers end up disagreeing on the
382-
// order produced by the Set additions above.)
383-
ArrayList<String> suppressionsList = new ArrayList<>(suppressions);
384-
Collections.sort(suppressionsList);
385-
386-
AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class);
387-
for (String suppression : suppressionsList) {
388-
builder.addMember("value", "$S", suppression);
389-
}
390-
391-
return builder.build();
392-
}
393-
394245
private List<MethodSpec> generateConstructors() {
395246
ParameterizedTypeName classOfTranscodeType =
396247
ParameterizedTypeName.get(ClassName.get(Class.class), transcodeTypeName);

0 commit comments

Comments
 (0)