blob: bc8fccd90f9569fbbfbe88ddd0af335dcdaa3736 [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;
gak00a6fb12016-11-14 23:33:06 -080031import com.squareup.javapoet.TypeName;
gak1ab10de2017-01-06 12:57:33 -080032import java.util.stream.Collector;
gak00a6fb12016-11-14 23:33:06 -080033import javax.lang.model.element.ExecutableElement;
dpbc8c6c052017-07-28 10:48:06 -070034import javax.lang.model.type.DeclaredType;
ronshapiro3b7bbef2018-10-22 08:47:00 -070035import javax.lang.model.type.TypeMirror;
ronshapiro732e5022016-01-07 12:10:55 -080036
37final class CodeBlocks {
gak1ab10de2017-01-06 12:57:33 -080038 /**
gak1ab10de2017-01-06 12:57:33 -080039 * Joins {@link CodeBlock} instances in a manner suitable for use as method parameters (or
ronshapiro3b7bbef2018-10-22 08:47:00 -070040 * arguments).
gak1ab10de2017-01-06 12:57:33 -080041 */
42 static Collector<CodeBlock, ?, CodeBlock> toParametersCodeBlock() {
ronshapiro3b7bbef2018-10-22 08:47:00 -070043 // TODO(ronshapiro,jakew): consider adding zero-width spaces to help line breaking when the
44 // formatter is off. If not, inline this
45 return CodeBlock.joining(", ");
gak1ab10de2017-01-06 12:57:33 -080046 }
47
ronshapiro3b7bbef2018-10-22 08:47:00 -070048 /** Concatenates {@link CodeBlock} instances separated by newlines for readability. */
gak1ab10de2017-01-06 12:57:33 -080049 static Collector<CodeBlock, ?, CodeBlock> toConcatenatedCodeBlock() {
ronshapiro3b7bbef2018-10-22 08:47:00 -070050 return CodeBlock.joining("\n", "", "\n");
gak1ab10de2017-01-06 12:57:33 -080051 }
ronshapiro732e5022016-01-07 12:10:55 -080052
gak00a6fb12016-11-14 23:33:06 -080053 /** Returns a comma-separated version of {@code codeBlocks} as one unified {@link CodeBlock}. */
ronshapiro732e5022016-01-07 12:10:55 -080054 static CodeBlock makeParametersCodeBlock(Iterable<CodeBlock> codeBlocks) {
gak1ab10de2017-01-06 12:57:33 -080055 return stream(codeBlocks.spliterator(), false).collect(toParametersCodeBlock());
56 }
57
ronshapiro3b7bbef2018-10-22 08:47:00 -070058 /**
59 * Returns one unified {@link CodeBlock} which joins each item in {@code codeBlocks} with a
60 * newline.
61 */
62 static CodeBlock concat(Iterable<CodeBlock> codeBlocks) {
63 return stream(codeBlocks.spliterator(), false).collect(toConcatenatedCodeBlock());
64 }
65
dpbc8c6c052017-07-28 10:48:06 -070066 /** Adds an annotation to a method. */
67 static void addAnnotation(MethodSpec.Builder method, DeclaredType nullableType) {
68 method.addAnnotation(ClassName.get(MoreTypes.asTypeElement(nullableType)));
69 }
70
ronshapirocc0f23d2018-01-02 15:27:45 -080071 /**
72 * Returns an anonymous {@link javax.inject.Provider} class with the single {@link
73 * javax.inject.Provider#get()} method implemented by {@code body}.
74 */
75 static CodeBlock anonymousProvider(TypeName providedType, CodeBlock body) {
76 return CodeBlock.of("$L",
77 anonymousClassBuilder("")
78 .superclass(providerOf(providedType))
79 .addMethod(
80 methodBuilder("get")
81 .addAnnotation(Override.class)
82 .addModifiers(PUBLIC)
83 .returns(providedType)
84 .addCode(body)
85 .build())
86 .build());
87 }
88
dpb3db68f02018-01-04 09:15:52 -080089 /** Returns {@code expression} cast to a type. */
90 static CodeBlock cast(CodeBlock expression, Class<?> castTo) {
91 return CodeBlock.of("($T) $L", castTo, expression);
92 }
93
ronshapiro3b7bbef2018-10-22 08:47:00 -070094 static CodeBlock type(TypeMirror type) {
95 return CodeBlock.of("$T", type);
ronshapirof22babc2016-01-29 12:16:16 -080096 }
97
ronshapiro6475f472016-02-02 07:03:10 -080098 static CodeBlock stringLiteral(String toWrap) {
ronshapirob9158d82016-04-13 11:00:56 -070099 return CodeBlock.of("$S", toWrap);
ronshapiro6475f472016-02-02 07:03:10 -0800100 }
101
gak00a6fb12016-11-14 23:33:06 -0800102 /** Returns a javadoc {@literal @link} tag that poins to the given {@link ExecutableElement}. */
103 static CodeBlock javadocLinkTo(ExecutableElement executableElement) {
104 CodeBlock.Builder builder =
ronshapiro57f302c2017-02-01 11:35:47 -0800105 CodeBlock.builder()
106 .add(
107 "{@link $T#",
108 rawTypeName(
109 ClassName.get(MoreElements.asType(executableElement.getEnclosingElement()))));
gak00a6fb12016-11-14 23:33:06 -0800110 switch (executableElement.getKind()) {
111 case METHOD:
112 builder.add("$L", executableElement.getSimpleName());
113 break;
114 case CONSTRUCTOR:
115 builder.add("$L", executableElement.getEnclosingElement().getSimpleName());
116 break;
117 case STATIC_INIT:
118 case INSTANCE_INIT:
119 throw new IllegalArgumentException(
120 "cannot create a javadoc link to an initializer: " + executableElement);
121 default:
122 throw new AssertionError(executableElement.toString());
123 }
124 builder.add("(");
cushonf5447bc2017-03-01 18:35:39 -0800125 builder.add(
126 executableElement
127 .getParameters()
128 .stream()
ronshapiro3b7bbef2018-10-22 08:47:00 -0700129 .map(parameter -> CodeBlock.of("$T", rawTypeName(TypeName.get(parameter.asType()))))
130 .collect(toParametersCodeBlock()));
gak00a6fb12016-11-14 23:33:06 -0800131 return builder.add(")}").build();
132 }
133
ronshapiro732e5022016-01-07 12:10:55 -0800134 private CodeBlocks() {}
135}