| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 1 | /* |
| ronshapiro | 5dde42d | 2016-06-17 09:03:35 -0700 | [diff] [blame] | 2 | * Copyright (C) 2016 The Dagger Authors. |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 3 | * |
| 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 | */ |
| dpb | 1b65b6a | 2016-07-11 12:11:24 -0700 | [diff] [blame] | 16 | |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 17 | package dagger.internal.codegen; |
| 18 | |
| ronshapiro | cc0f23d | 2018-01-02 15:27:45 -0800 | [diff] [blame] | 19 | import static com.squareup.javapoet.MethodSpec.methodBuilder; |
| 20 | import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder; |
| 21 | import static dagger.internal.codegen.TypeNames.providerOf; |
| ronshapiro | 57f302c | 2017-02-01 11:35:47 -0800 | [diff] [blame] | 22 | import static dagger.internal.codegen.TypeNames.rawTypeName; |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 23 | import static java.util.stream.StreamSupport.stream; |
| ronshapiro | cc0f23d | 2018-01-02 15:27:45 -0800 | [diff] [blame] | 24 | import static javax.lang.model.element.Modifier.PUBLIC; |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 25 | |
| ronshapiro | 57f302c | 2017-02-01 11:35:47 -0800 | [diff] [blame] | 26 | import com.google.auto.common.MoreElements; |
| dpb | c8c6c05 | 2017-07-28 10:48:06 -0700 | [diff] [blame] | 27 | import com.google.auto.common.MoreTypes; |
| ronshapiro | 57f302c | 2017-02-01 11:35:47 -0800 | [diff] [blame] | 28 | import com.squareup.javapoet.ClassName; |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 29 | import com.squareup.javapoet.CodeBlock; |
| dpb | c8c6c05 | 2017-07-28 10:48:06 -0700 | [diff] [blame] | 30 | import com.squareup.javapoet.MethodSpec; |
| ronshapiro | 9b197da | 2018-11-16 11:51:06 -0800 | [diff] [blame] | 31 | import com.squareup.javapoet.ParameterSpec; |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 32 | import com.squareup.javapoet.TypeName; |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 33 | import java.util.stream.Collector; |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 34 | import javax.lang.model.element.ExecutableElement; |
| dpb | c8c6c05 | 2017-07-28 10:48:06 -0700 | [diff] [blame] | 35 | import javax.lang.model.type.DeclaredType; |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 36 | import javax.lang.model.type.TypeMirror; |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 37 | |
| 38 | final class CodeBlocks { |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 39 | /** |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 40 | * Joins {@link CodeBlock} instances in a manner suitable for use as method parameters (or |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 41 | * arguments). |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 42 | */ |
| 43 | static Collector<CodeBlock, ?, CodeBlock> toParametersCodeBlock() { |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 44 | // 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(", "); |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 47 | } |
| 48 | |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 49 | /** Concatenates {@link CodeBlock} instances separated by newlines for readability. */ |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 50 | static Collector<CodeBlock, ?, CodeBlock> toConcatenatedCodeBlock() { |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 51 | return CodeBlock.joining("\n", "", "\n"); |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 52 | } |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 53 | |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 54 | /** Returns a comma-separated version of {@code codeBlocks} as one unified {@link CodeBlock}. */ |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 55 | static CodeBlock makeParametersCodeBlock(Iterable<CodeBlock> codeBlocks) { |
| gak | 1ab10de | 2017-01-06 12:57:33 -0800 | [diff] [blame] | 56 | return stream(codeBlocks.spliterator(), false).collect(toParametersCodeBlock()); |
| 57 | } |
| 58 | |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 59 | /** |
| ronshapiro | 9b197da | 2018-11-16 11:51:06 -0800 | [diff] [blame] | 60 | * 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 | /** |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 71 | * 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 | |
| dpb | c8c6c05 | 2017-07-28 10:48:06 -0700 | [diff] [blame] | 78 | /** 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 | |
| ronshapiro | cc0f23d | 2018-01-02 15:27:45 -0800 | [diff] [blame] | 83 | /** |
| 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 | |
| dpb | 3db68f0 | 2018-01-04 09:15:52 -0800 | [diff] [blame] | 101 | /** 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 | |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 106 | static CodeBlock type(TypeMirror type) { |
| 107 | return CodeBlock.of("$T", type); |
| ronshapiro | f22babc | 2016-01-29 12:16:16 -0800 | [diff] [blame] | 108 | } |
| 109 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 110 | static CodeBlock stringLiteral(String toWrap) { |
| ronshapiro | b9158d8 | 2016-04-13 11:00:56 -0700 | [diff] [blame] | 111 | return CodeBlock.of("$S", toWrap); |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 112 | } |
| 113 | |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 114 | /** Returns a javadoc {@literal @link} tag that poins to the given {@link ExecutableElement}. */ |
| 115 | static CodeBlock javadocLinkTo(ExecutableElement executableElement) { |
| 116 | CodeBlock.Builder builder = |
| ronshapiro | 57f302c | 2017-02-01 11:35:47 -0800 | [diff] [blame] | 117 | CodeBlock.builder() |
| 118 | .add( |
| 119 | "{@link $T#", |
| 120 | rawTypeName( |
| 121 | ClassName.get(MoreElements.asType(executableElement.getEnclosingElement())))); |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 122 | 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("("); |
| cushon | f5447bc | 2017-03-01 18:35:39 -0800 | [diff] [blame] | 137 | builder.add( |
| 138 | executableElement |
| 139 | .getParameters() |
| 140 | .stream() |
| ronshapiro | 3b7bbef | 2018-10-22 08:47:00 -0700 | [diff] [blame] | 141 | .map(parameter -> CodeBlock.of("$T", rawTypeName(TypeName.get(parameter.asType())))) |
| 142 | .collect(toParametersCodeBlock())); |
| gak | 00a6fb1 | 2016-11-14 23:33:06 -0800 | [diff] [blame] | 143 | return builder.add(")}").build(); |
| 144 | } |
| 145 | |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 146 | private CodeBlocks() {} |
| 147 | } |