blob: c1ca32d3c056e6cae0ab5c6da21342bd0250f20f [file] [log] [blame]
ronshapiro732e5022016-01-07 12:10:55 -08001/*
ronshapiro5dde42d2016-06-17 09:03:35 -07002 * Copyright (C) 2016 The Dagger Authors.
ronshapiro732e5022016-01-07 12:10:55 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
dpb1b65b6a2016-07-11 12:11:24 -070016
ronshapiro732e5022016-01-07 12:10:55 -080017package dagger.internal.codegen;
18
ronshapirocc0f23d2018-01-02 15:27:45 -080019import static com.squareup.javapoet.MethodSpec.methodBuilder;
20import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
21import static dagger.internal.codegen.TypeNames.providerOf;
ronshapiro57f302c2017-02-01 11:35:47 -080022import static dagger.internal.codegen.TypeNames.rawTypeName;
gak1ab10de2017-01-06 12:57:33 -080023import static java.util.stream.StreamSupport.stream;
ronshapirocc0f23d2018-01-02 15:27:45 -080024import static javax.lang.model.element.Modifier.PUBLIC;
gak1ab10de2017-01-06 12:57:33 -080025
ronshapiro57f302c2017-02-01 11:35:47 -080026import com.google.auto.common.MoreElements;
dpbc8c6c052017-07-28 10:48:06 -070027import com.google.auto.common.MoreTypes;
ronshapiro57f302c2017-02-01 11:35:47 -080028import com.squareup.javapoet.ClassName;
ronshapiro732e5022016-01-07 12:10:55 -080029import com.squareup.javapoet.CodeBlock;
dpbc8c6c052017-07-28 10:48:06 -070030import com.squareup.javapoet.MethodSpec;
ronshapiro9b197da2018-11-16 11:51:06 -080031import com.squareup.javapoet.ParameterSpec;
gak00a6fb12016-11-14 23:33:06 -080032import com.squareup.javapoet.TypeName;
gak1ab10de2017-01-06 12:57:33 -080033import java.util.stream.Collector;
gak00a6fb12016-11-14 23:33:06 -080034import javax.lang.model.element.ExecutableElement;
dpbc8c6c052017-07-28 10:48:06 -070035import javax.lang.model.type.DeclaredType;
ronshapiro3b7bbef2018-10-22 08:47:00 -070036import javax.lang.model.type.TypeMirror;
ronshapiro732e5022016-01-07 12:10:55 -080037
38final class CodeBlocks {
gak1ab10de2017-01-06 12:57:33 -080039 /**
gak1ab10de2017-01-06 12:57:33 -080040 * Joins {@link CodeBlock} instances in a manner suitable for use as method parameters (or
ronshapiro3b7bbef2018-10-22 08:47:00 -070041 * arguments).
gak1ab10de2017-01-06 12:57:33 -080042 */
43 static Collector<CodeBlock, ?, CodeBlock> toParametersCodeBlock() {
ronshapiro3b7bbef2018-10-22 08:47:00 -070044 // TODO(ronshapiro,jakew): consider adding zero-width spaces to help line breaking when the
45 // formatter is off. If not, inline this
46 return CodeBlock.joining(", ");
gak1ab10de2017-01-06 12:57:33 -080047 }
48
ronshapiro3b7bbef2018-10-22 08:47:00 -070049 /** Concatenates {@link CodeBlock} instances separated by newlines for readability. */
gak1ab10de2017-01-06 12:57:33 -080050 static Collector<CodeBlock, ?, CodeBlock> toConcatenatedCodeBlock() {
ronshapiro3b7bbef2018-10-22 08:47:00 -070051 return CodeBlock.joining("\n", "", "\n");
gak1ab10de2017-01-06 12:57:33 -080052 }
ronshapiro732e5022016-01-07 12:10:55 -080053
gak00a6fb12016-11-14 23:33:06 -080054 /** Returns a comma-separated version of {@code codeBlocks} as one unified {@link CodeBlock}. */
ronshapiro732e5022016-01-07 12:10:55 -080055 static CodeBlock makeParametersCodeBlock(Iterable<CodeBlock> codeBlocks) {
gak1ab10de2017-01-06 12:57:33 -080056 return stream(codeBlocks.spliterator(), false).collect(toParametersCodeBlock());
57 }
58
ronshapiro3b7bbef2018-10-22 08:47:00 -070059 /**
ronshapiro9b197da2018-11-16 11:51:06 -080060 * Returns a comma-separated {@link CodeBlock} using the name of every parameter in {@code
61 * parameters}.
62 */
63 static CodeBlock parameterNames(Iterable<ParameterSpec> parameters) {
64 // TODO(ronshapiro): Add DaggerStreams.stream(Iterable)
65 return stream(parameters.spliterator(), false)
66 .map(p -> CodeBlock.of("$N", p))
67 .collect(toParametersCodeBlock());
68 }
69
70 /**
ronshapiro3b7bbef2018-10-22 08:47:00 -070071 * Returns one unified {@link CodeBlock} which joins each item in {@code codeBlocks} with a
72 * newline.
73 */
74 static CodeBlock concat(Iterable<CodeBlock> codeBlocks) {
75 return stream(codeBlocks.spliterator(), false).collect(toConcatenatedCodeBlock());
76 }
77
dpbc8c6c052017-07-28 10:48:06 -070078 /** Adds an annotation to a method. */
79 static void addAnnotation(MethodSpec.Builder method, DeclaredType nullableType) {
80 method.addAnnotation(ClassName.get(MoreTypes.asTypeElement(nullableType)));
81 }
82
ronshapirocc0f23d2018-01-02 15:27:45 -080083 /**
84 * Returns an anonymous {@link javax.inject.Provider} class with the single {@link
85 * javax.inject.Provider#get()} method implemented by {@code body}.
86 */
87 static CodeBlock anonymousProvider(TypeName providedType, CodeBlock body) {
88 return CodeBlock.of("$L",
89 anonymousClassBuilder("")
90 .superclass(providerOf(providedType))
91 .addMethod(
92 methodBuilder("get")
93 .addAnnotation(Override.class)
94 .addModifiers(PUBLIC)
95 .returns(providedType)
96 .addCode(body)
97 .build())
98 .build());
99 }
100
dpb3db68f02018-01-04 09:15:52 -0800101 /** Returns {@code expression} cast to a type. */
102 static CodeBlock cast(CodeBlock expression, Class<?> castTo) {
103 return CodeBlock.of("($T) $L", castTo, expression);
104 }
105
ronshapiro3b7bbef2018-10-22 08:47:00 -0700106 static CodeBlock type(TypeMirror type) {
107 return CodeBlock.of("$T", type);
ronshapirof22babc2016-01-29 12:16:16 -0800108 }
109
ronshapiro6475f472016-02-02 07:03:10 -0800110 static CodeBlock stringLiteral(String toWrap) {
ronshapirob9158d82016-04-13 11:00:56 -0700111 return CodeBlock.of("$S", toWrap);
ronshapiro6475f472016-02-02 07:03:10 -0800112 }
113
gak00a6fb12016-11-14 23:33:06 -0800114 /** Returns a javadoc {@literal @link} tag that poins to the given {@link ExecutableElement}. */
115 static CodeBlock javadocLinkTo(ExecutableElement executableElement) {
116 CodeBlock.Builder builder =
ronshapiro57f302c2017-02-01 11:35:47 -0800117 CodeBlock.builder()
118 .add(
119 "{@link $T#",
120 rawTypeName(
121 ClassName.get(MoreElements.asType(executableElement.getEnclosingElement()))));
gak00a6fb12016-11-14 23:33:06 -0800122 switch (executableElement.getKind()) {
123 case METHOD:
124 builder.add("$L", executableElement.getSimpleName());
125 break;
126 case CONSTRUCTOR:
127 builder.add("$L", executableElement.getEnclosingElement().getSimpleName());
128 break;
129 case STATIC_INIT:
130 case INSTANCE_INIT:
131 throw new IllegalArgumentException(
132 "cannot create a javadoc link to an initializer: " + executableElement);
133 default:
134 throw new AssertionError(executableElement.toString());
135 }
136 builder.add("(");
cushonf5447bc2017-03-01 18:35:39 -0800137 builder.add(
138 executableElement
139 .getParameters()
140 .stream()
ronshapiro3b7bbef2018-10-22 08:47:00 -0700141 .map(parameter -> CodeBlock.of("$T", rawTypeName(TypeName.get(parameter.asType()))))
142 .collect(toParametersCodeBlock()));
gak00a6fb12016-11-14 23:33:06 -0800143 return builder.add(")}").build();
144 }
145
ronshapiro732e5022016-01-07 12:10:55 -0800146 private CodeBlocks() {}
147}