77import com .bumptech .glide .annotation .GlideOption ;
88import com .google .common .base .Function ;
99import com .google .common .base .Joiner ;
10- import com .google .common .base .Predicate ;
1110import com .google .common .collect .FluentIterable ;
1211import com .google .common .collect .ImmutableList ;
1312import com .google .common .collect .ImmutableSet ;
2322import com .squareup .javapoet .TypeVariableName ;
2423import com .squareup .javapoet .WildcardTypeName ;
2524import java .io .File ;
26- import java .util .ArrayList ;
27- import java .util .Collections ;
28- import java .util .HashSet ;
2925import java .util .List ;
3026import java .util .Set ;
31- import javax .annotation .Nullable ;
3227import javax .annotation .processing .ProcessingEnvironment ;
3328import javax .lang .model .element .AnnotationMirror ;
3429import 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