| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 1 | /* |
| ronshapiro | 5dde42d | 2016-06-17 09:03:35 -0700 | [diff] [blame] | 2 | * Copyright (C) 2014 The Dagger Authors. |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 3 | * |
| ronshapiro | 3a179ec | 2017-04-14 09:22:17 -0700 | [diff] [blame] | 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 |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| ronshapiro | 3a179ec | 2017-04-14 09:22:17 -0700 | [diff] [blame] | 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. |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 15 | */ |
| dpb | 1b65b6a | 2016-07-11 12:11:24 -0700 | [diff] [blame] | 16 | |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 17 | package dagger.internal.codegen; |
| 18 | |
| gak | 645274e | 2017-01-04 11:34:17 -0800 | [diff] [blame] | 19 | import static com.google.common.base.CaseFormat.LOWER_CAMEL; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 20 | import static com.google.common.base.CaseFormat.UPPER_CAMEL; |
| 21 | import static com.google.common.base.Preconditions.checkArgument; |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 22 | import static com.google.common.base.Preconditions.checkState; |
| gak | 645274e | 2017-01-04 11:34:17 -0800 | [diff] [blame] | 23 | import static com.google.common.base.Verify.verify; |
| gak | 4d86019 | 2016-10-13 23:41:00 -0700 | [diff] [blame] | 24 | import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION; |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 25 | import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_MULTIBOUND_MAP; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 26 | import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_MULTIBOUND_SET; |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 27 | import static dagger.internal.codegen.Optionals.optionalComparator; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 28 | import static dagger.internal.codegen.TypeNames.DOUBLE_CHECK; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 29 | import static dagger.internal.codegen.TypeNames.MAP_FACTORY; |
| 30 | import static dagger.internal.codegen.TypeNames.MAP_OF_PRODUCED_PRODUCER; |
| 31 | import static dagger.internal.codegen.TypeNames.MAP_OF_PRODUCER_PRODUCER; |
| 32 | import static dagger.internal.codegen.TypeNames.MAP_PRODUCER; |
| 33 | import static dagger.internal.codegen.TypeNames.MAP_PROVIDER_FACTORY; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 34 | import static dagger.internal.codegen.TypeNames.PROVIDER_OF_LAZY; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 35 | import static dagger.internal.codegen.TypeNames.SET_FACTORY; |
| 36 | import static dagger.internal.codegen.TypeNames.SET_OF_PRODUCED_PRODUCER; |
| 37 | import static dagger.internal.codegen.TypeNames.SET_PRODUCER; |
| ronshapiro | 0b1bcc6 | 2017-05-26 11:14:20 -0700 | [diff] [blame] | 38 | import static dagger.internal.codegen.Util.toImmutableList; |
| ronshapiro | 6d1e6ac | 2017-10-09 09:00:32 -0700 | [diff] [blame^] | 39 | import static dagger.internal.codegen.Util.toImmutableSet; |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 40 | import static java.util.Comparator.comparing; |
| gak | 645274e | 2017-01-04 11:34:17 -0800 | [diff] [blame] | 41 | import static javax.lang.model.SourceVersion.isName; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 42 | |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 43 | import com.google.common.base.CaseFormat; |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 44 | import com.google.common.base.Joiner; |
| sameb | 0d49be8 | 2015-01-22 17:29:48 -0800 | [diff] [blame] | 45 | import com.google.common.collect.ImmutableList; |
| Christian Edward Gruber | 2a90069 | 2014-07-01 22:28:26 -0700 | [diff] [blame] | 46 | import com.google.common.collect.ImmutableMap; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 47 | import com.google.common.collect.ImmutableSet; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 48 | import com.google.common.collect.Iterables; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 49 | import com.google.common.collect.Maps; |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 50 | import com.squareup.javapoet.ClassName; |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 51 | import com.squareup.javapoet.CodeBlock; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 52 | import com.squareup.javapoet.FieldSpec; |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 53 | import com.squareup.javapoet.ParameterizedTypeName; |
| 54 | import com.squareup.javapoet.TypeName; |
| ronshapiro | 9540fb2 | 2016-01-13 09:46:47 -0800 | [diff] [blame] | 55 | import com.squareup.javapoet.TypeVariableName; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 56 | import dagger.internal.SetFactory; |
| 57 | import dagger.producers.Produced; |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 58 | import dagger.producers.Producer; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 59 | import dagger.producers.internal.SetOfProducedProducer; |
| 60 | import dagger.producers.internal.SetProducer; |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 61 | import java.util.Comparator; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 62 | import java.util.Iterator; |
| ronshapiro | 0b1bcc6 | 2017-05-26 11:14:20 -0700 | [diff] [blame] | 63 | import java.util.List; |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 64 | import javax.inject.Provider; |
| gak | 645274e | 2017-01-04 11:34:17 -0800 | [diff] [blame] | 65 | import javax.lang.model.SourceVersion; |
| gak | 6624110 | 2016-09-13 12:23:00 -0700 | [diff] [blame] | 66 | import javax.lang.model.element.Element; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 67 | import javax.lang.model.element.TypeElement; |
| ronshapiro | 9540fb2 | 2016-01-13 09:46:47 -0800 | [diff] [blame] | 68 | import javax.lang.model.element.TypeParameterElement; |
| Gregory Kick | 03c3c2d | 2014-06-18 17:05:47 -0700 | [diff] [blame] | 69 | |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 70 | /** |
| 71 | * Utilities for generating files. |
| 72 | * |
| 73 | * @author Gregory Kick |
| 74 | * @since 2.0 |
| 75 | */ |
| 76 | class SourceFiles { |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 77 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 78 | private static final Joiner CLASS_FILE_NAME_JOINER = Joiner.on('_'); |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 79 | |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 80 | /** |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 81 | * Sorts {@link DependencyRequest} instances in an order likely to reflect their logical |
| 82 | * importance. |
| 83 | */ |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 84 | static final Comparator<DependencyRequest> DEPENDENCY_ORDERING = |
| 85 | // put fields before parameters |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 86 | comparing( |
| 87 | (DependencyRequest request) -> request.requestElement().map(Element::getKind), |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 88 | optionalComparator()) |
| 89 | // order by dependency kind |
| 90 | .thenComparing(DependencyRequest::kind) |
| 91 | // then sort by name |
| 92 | .thenComparing( |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 93 | request -> |
| 94 | request.requestElement().map(element -> element.getSimpleName().toString()), |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 95 | optionalComparator()); |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 96 | |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 97 | /** |
| dpb | 5719880 | 2015-12-17 12:18:15 -0800 | [diff] [blame] | 98 | * Generates names and keys for the factory class fields needed to hold the framework classes for |
| 99 | * all of the dependencies of {@code binding}. It is responsible for choosing a name that |
| 100 | * |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 101 | * <ul> |
| dpb | 5719880 | 2015-12-17 12:18:15 -0800 | [diff] [blame] | 102 | * <li>represents all of the dependency requests for this key |
| 103 | * <li>is <i>probably</i> associated with the type being bound |
| 104 | * <li>is unique within the class |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 105 | * </ul> |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 106 | * |
| dpb | 5719880 | 2015-12-17 12:18:15 -0800 | [diff] [blame] | 107 | * @param binding must be an unresolved binding (type parameters must match its type element's) |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 108 | */ |
| gak | 59d2c99 | 2015-01-14 14:33:46 -0800 | [diff] [blame] | 109 | static ImmutableMap<BindingKey, FrameworkField> generateBindingFieldsForDependencies( |
| dpb | f6be7d6 | 2016-01-22 11:43:21 -0800 | [diff] [blame] | 110 | Binding binding) { |
| 111 | checkArgument(!binding.unresolved().isPresent(), "binding must be unresolved: %s", binding); |
| 112 | |
| gak | 59d2c99 | 2015-01-14 14:33:46 -0800 | [diff] [blame] | 113 | ImmutableMap.Builder<BindingKey, FrameworkField> bindingFields = ImmutableMap.builder(); |
| gak | 75b9b72 | 2016-09-29 15:48:40 -0700 | [diff] [blame] | 114 | for (Binding.DependencyAssociation dependencyAssociation : binding.dependencyAssociations()) { |
| 115 | FrameworkDependency frameworkDependency = dependencyAssociation.frameworkDependency(); |
| dpb | f6be7d6 | 2016-01-22 11:43:21 -0800 | [diff] [blame] | 116 | bindingFields.put( |
| 117 | frameworkDependency.bindingKey(), |
| dpb | d289ddc | 2016-04-28 13:09:11 -0700 | [diff] [blame] | 118 | FrameworkField.create( |
| 119 | ClassName.get(frameworkDependency.frameworkClass()), |
| 120 | TypeName.get(frameworkDependency.bindingKey().key().type()), |
| gak | 75b9b72 | 2016-09-29 15:48:40 -0700 | [diff] [blame] | 121 | fieldNameForDependency(dependencyAssociation.dependencyRequests()))); |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 122 | } |
| beder | 3e950f3 | 2014-12-19 17:48:47 -0800 | [diff] [blame] | 123 | return bindingFields.build(); |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 124 | } |
| 125 | |
| gak | 75b9b72 | 2016-09-29 15:48:40 -0700 | [diff] [blame] | 126 | private static String fieldNameForDependency(ImmutableSet<DependencyRequest> dependencyRequests) { |
| dpb | f6be7d6 | 2016-01-22 11:43:21 -0800 | [diff] [blame] | 127 | // collect together all of the names that we would want to call the provider |
| 128 | ImmutableSet<String> dependencyNames = |
| ronshapiro | 6d1e6ac | 2017-10-09 09:00:32 -0700 | [diff] [blame^] | 129 | dependencyRequests.stream().map(DependencyVariableNamer::name).collect(toImmutableSet()); |
| dpb | f6be7d6 | 2016-01-22 11:43:21 -0800 | [diff] [blame] | 130 | |
| 131 | if (dependencyNames.size() == 1) { |
| 132 | // if there's only one name, great! use it! |
| 133 | return Iterables.getOnlyElement(dependencyNames); |
| 134 | } else { |
| 135 | // in the event that a field is being used for a bunch of deps with different names, |
| 136 | // add all the names together with "And"s in the middle. E.g.: stringAndS |
| 137 | Iterator<String> namesIterator = dependencyNames.iterator(); |
| 138 | String first = namesIterator.next(); |
| 139 | StringBuilder compositeNameBuilder = new StringBuilder(first); |
| 140 | while (namesIterator.hasNext()) { |
| 141 | compositeNameBuilder |
| 142 | .append("And") |
| 143 | .append(CaseFormat.LOWER_CAMEL.to(UPPER_CAMEL, namesIterator.next())); |
| 144 | } |
| 145 | return compositeNameBuilder.toString(); |
| 146 | } |
| 147 | } |
| 148 | |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 149 | static CodeBlock frameworkTypeUsageStatement( |
| 150 | CodeBlock frameworkTypeMemberSelect, DependencyRequest.Kind dependencyKind) { |
| 151 | switch (dependencyKind) { |
| 152 | case LAZY: |
| ronshapiro | b9158d8 | 2016-04-13 11:00:56 -0700 | [diff] [blame] | 153 | return CodeBlock.of("$T.lazy($L)", DOUBLE_CHECK, frameworkTypeMemberSelect); |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 154 | case INSTANCE: |
| 155 | case FUTURE: |
| ronshapiro | b9158d8 | 2016-04-13 11:00:56 -0700 | [diff] [blame] | 156 | return CodeBlock.of("$L.get()", frameworkTypeMemberSelect); |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 157 | case PROVIDER: |
| 158 | case PRODUCER: |
| 159 | case MEMBERS_INJECTOR: |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 160 | return frameworkTypeMemberSelect; |
| dpb | c9bd6d8 | 2016-04-19 07:25:06 -0700 | [diff] [blame] | 161 | case PROVIDER_OF_LAZY: |
| 162 | return CodeBlock.of("$T.create($L)", PROVIDER_OF_LAZY, frameworkTypeMemberSelect); |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 163 | default: // including PRODUCED |
| 164 | throw new AssertionError(dependencyKind); |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 165 | } |
| 166 | } |
| 167 | |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 168 | /** |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 169 | * Returns a mapping of {@link DependencyRequest}s to {@link CodeBlock}s that {@linkplain |
| 170 | * #frameworkTypeUsageStatement(CodeBlock, DependencyRequest.Kind) use them}. |
| 171 | */ |
| 172 | static ImmutableMap<DependencyRequest, CodeBlock> frameworkFieldUsages( |
| 173 | ImmutableSet<DependencyRequest> dependencies, ImmutableMap<BindingKey, FieldSpec> fields) { |
| 174 | return Maps.toMap( |
| 175 | dependencies, |
| 176 | dep -> |
| 177 | frameworkTypeUsageStatement( |
| 178 | CodeBlock.of("$N", fields.get(dep.bindingKey())), dep.kind())); |
| 179 | } |
| 180 | |
| 181 | /** |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 182 | * Returns the generated factory or members injector name for a binding. |
| 183 | */ |
| 184 | static ClassName generatedClassNameForBinding(Binding binding) { |
| 185 | switch (binding.bindingType()) { |
| Christian Edward Gruber | 4aec5ba | 2014-05-20 19:37:11 -0700 | [diff] [blame] | 186 | case PROVISION: |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 187 | case PRODUCTION: |
| 188 | ContributionBinding contribution = (ContributionBinding) binding; |
| dpb | dd27603 | 2016-07-11 09:34:43 -0700 | [diff] [blame] | 189 | checkArgument(contribution.bindingTypeElement().isPresent()); |
| 190 | ClassName enclosingClassName = ClassName.get(contribution.bindingTypeElement().get()); |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 191 | switch (contribution.bindingKind()) { |
| 192 | case INJECTION: |
| 193 | case PROVISION: |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 194 | case PRODUCTION: |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 195 | return enclosingClassName |
| 196 | .topLevelClassName() |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 197 | .peerClass( |
| ronshapiro | 23527f6 | 2016-04-20 10:33:08 -0700 | [diff] [blame] | 198 | classFileName(enclosingClassName) |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 199 | + "_" |
| 200 | + factoryPrefix(contribution) |
| 201 | + "Factory"); |
| 202 | |
| 203 | default: |
| 204 | throw new AssertionError(); |
| 205 | } |
| 206 | |
| 207 | case MEMBERS_INJECTION: |
| dpb | 4955ef9 | 2016-04-29 12:31:14 -0700 | [diff] [blame] | 208 | return membersInjectorNameForType( |
| 209 | ((MembersInjectionBinding) binding).membersInjectedType()); |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 210 | |
| Christian Edward Gruber | 4aec5ba | 2014-05-20 19:37:11 -0700 | [diff] [blame] | 211 | default: |
| 212 | throw new AssertionError(); |
| 213 | } |
| 214 | } |
| Christian Edward Gruber | 791bd29 | 2014-05-20 19:36:41 -0700 | [diff] [blame] | 215 | |
| gak | 4d86019 | 2016-10-13 23:41:00 -0700 | [diff] [blame] | 216 | static TypeName parameterizedGeneratedTypeNameForBinding(Binding binding) { |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 217 | ClassName className = generatedClassNameForBinding(binding); |
| gak | 4d86019 | 2016-10-13 23:41:00 -0700 | [diff] [blame] | 218 | ImmutableList<TypeVariableName> typeParameters = bindingTypeElementTypeVariableNames(binding); |
| 219 | return typeParameters.isEmpty() |
| 220 | ? className |
| 221 | : ParameterizedTypeName.get(className, Iterables.toArray(typeParameters, TypeName.class)); |
| Christian Edward Gruber | 10876b0 | 2014-06-01 11:24:55 -0700 | [diff] [blame] | 222 | } |
| 223 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 224 | static ClassName membersInjectorNameForType(TypeElement typeElement) { |
| ronshapiro | a296c10 | 2016-01-14 12:33:42 -0800 | [diff] [blame] | 225 | return siblingClassName(typeElement, "_MembersInjector"); |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 226 | } |
| 227 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 228 | static String classFileName(ClassName className) { |
| ronshapiro | 732e502 | 2016-01-07 12:10:55 -0800 | [diff] [blame] | 229 | return CLASS_FILE_NAME_JOINER.join(className.simpleNames()); |
| 230 | } |
| 231 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 232 | static ClassName generatedMonitoringModuleName( |
| ronshapiro | a296c10 | 2016-01-14 12:33:42 -0800 | [diff] [blame] | 233 | TypeElement componentElement) { |
| 234 | return siblingClassName(componentElement, "_MonitoringModule"); |
| 235 | } |
| 236 | |
| beder | 893f770 | 2016-02-17 05:22:50 -0800 | [diff] [blame] | 237 | static ClassName generatedProductionExecutorModuleName(TypeElement componentElement) { |
| 238 | return siblingClassName(componentElement, "_ProductionExecutorModule"); |
| 239 | } |
| 240 | |
| ronshapiro | 6475f47 | 2016-02-02 07:03:10 -0800 | [diff] [blame] | 241 | // TODO(ronshapiro): when JavaPoet migration is complete, replace the duplicated code |
| 242 | // which could use this. |
| 243 | private static ClassName siblingClassName(TypeElement typeElement, String suffix) { |
| 244 | ClassName className = ClassName.get(typeElement); |
| ronshapiro | 23527f6 | 2016-04-20 10:33:08 -0700 | [diff] [blame] | 245 | return className.topLevelClassName().peerClass(classFileName(className) + suffix); |
| beder | 0e6f248 | 2015-10-23 08:37:55 -0700 | [diff] [blame] | 246 | } |
| 247 | |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 248 | /** |
| 249 | * The {@link java.util.Set} factory class name appropriate for set bindings. |
| 250 | * |
| 251 | * <ul> |
| 252 | * <li>{@link SetFactory} for provision bindings. |
| 253 | * <li>{@link SetProducer} for production bindings for {@code Set<T>}. |
| 254 | * <li>{@link SetOfProducedProducer} for production bindings for {@code Set<Produced<T>>}. |
| 255 | * </ul> |
| 256 | */ |
| 257 | static ClassName setFactoryClassName(ContributionBinding binding) { |
| 258 | checkArgument(binding.bindingKind().equals(SYNTHETIC_MULTIBOUND_SET)); |
| 259 | if (binding.bindingType().equals(BindingType.PROVISION)) { |
| 260 | return SET_FACTORY; |
| 261 | } else { |
| 262 | SetType setType = SetType.from(binding.key()); |
| 263 | return setType.elementsAreTypeOf(Produced.class) ? SET_OF_PRODUCED_PRODUCER : SET_PRODUCER; |
| 264 | } |
| 265 | } |
| 266 | |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 267 | /** The {@link java.util.Map} factory class name appropriate for map bindings. */ |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 268 | static ClassName mapFactoryClassName(ContributionBinding binding) { |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 269 | checkState(binding.bindingKind().equals(SYNTHETIC_MULTIBOUND_MAP), binding.bindingKind()); |
| 270 | MapType mapType = MapType.from(binding.key()); |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 271 | switch (binding.bindingType()) { |
| sraub | e1028b7 | 2017-08-28 18:03:22 -0700 | [diff] [blame] | 272 | case PROVISION: |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 273 | return mapType.valuesAreTypeOf(Provider.class) ? MAP_PROVIDER_FACTORY : MAP_FACTORY; |
| 274 | case PRODUCTION: |
| 275 | return mapType.valuesAreFrameworkType() |
| 276 | ? mapType.valuesAreTypeOf(Producer.class) |
| 277 | ? MAP_OF_PRODUCER_PRODUCER |
| 278 | : MAP_OF_PRODUCED_PRODUCER |
| 279 | : MAP_PRODUCER; |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 280 | default: |
| ronshapiro | b449911 | 2017-08-30 11:34:31 -0700 | [diff] [blame] | 281 | throw new IllegalArgumentException(binding.bindingType().toString()); |
| ronshapiro | 2c9ec49 | 2017-05-26 15:03:38 -0700 | [diff] [blame] | 282 | } |
| 283 | } |
| 284 | |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 285 | private static String factoryPrefix(ContributionBinding binding) { |
| Christian Edward Gruber | 4aec5ba | 2014-05-20 19:37:11 -0700 | [diff] [blame] | 286 | switch (binding.bindingKind()) { |
| 287 | case INJECTION: |
| Christian Edward Gruber | 791bd29 | 2014-05-20 19:36:41 -0700 | [diff] [blame] | 288 | return ""; |
| Christian Edward Gruber | 791bd29 | 2014-05-20 19:36:41 -0700 | [diff] [blame] | 289 | |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 290 | case PROVISION: |
| Ron Shapiro | 5f21a80 | 2016-09-21 10:23:55 -0400 | [diff] [blame] | 291 | case PRODUCTION: |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 292 | return CaseFormat.LOWER_CAMEL.to( |
| dpb | dd27603 | 2016-07-11 09:34:43 -0700 | [diff] [blame] | 293 | UPPER_CAMEL, binding.bindingElement().get().getSimpleName().toString()); |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 294 | |
| beder | 72466bc | 2014-12-08 10:51:05 -0800 | [diff] [blame] | 295 | default: |
| 296 | throw new IllegalArgumentException(); |
| 297 | } |
| 298 | } |
| 299 | |
| ronshapiro | 9540fb2 | 2016-01-13 09:46:47 -0800 | [diff] [blame] | 300 | static ImmutableList<TypeVariableName> bindingTypeElementTypeVariableNames(Binding binding) { |
| gak | 4d86019 | 2016-10-13 23:41:00 -0700 | [diff] [blame] | 301 | if (binding instanceof ContributionBinding) { |
| 302 | ContributionBinding contributionBinding = (ContributionBinding) binding; |
| 303 | if (!contributionBinding.bindingKind().equals(INJECTION) |
| 304 | && !contributionBinding.requiresModuleInstance()) { |
| 305 | return ImmutableList.of(); |
| 306 | } |
| 307 | } |
| ronshapiro | 0b1bcc6 | 2017-05-26 11:14:20 -0700 | [diff] [blame] | 308 | List<? extends TypeParameterElement> typeParameters = |
| 309 | binding.bindingTypeElement().get().getTypeParameters(); |
| 310 | return typeParameters.stream().map(TypeVariableName::get).collect(toImmutableList()); |
| ronshapiro | 9540fb2 | 2016-01-13 09:46:47 -0800 | [diff] [blame] | 311 | } |
| 312 | |
| gak | 645274e | 2017-01-04 11:34:17 -0800 | [diff] [blame] | 313 | /** |
| 314 | * Returns a name to be used for variables of the given {@linkplain TypeElement type}. Prefer |
| 315 | * semantically meaningful variable names, but if none can be derived, this will produce something |
| 316 | * readable. |
| 317 | */ |
| 318 | // TODO(gak): maybe this should be a function of TypeMirrors instead of Elements? |
| 319 | static String simpleVariableName(TypeElement typeElement) { |
| 320 | String candidateName = UPPER_CAMEL.to(LOWER_CAMEL, typeElement.getSimpleName().toString()); |
| 321 | String variableName = protectAgainstKeywords(candidateName); |
| 322 | verify(isName(variableName), "'%s' was expected to be a valid variable name"); |
| 323 | return variableName; |
| 324 | } |
| 325 | |
| 326 | private static String protectAgainstKeywords(String candidateName) { |
| 327 | switch (candidateName) { |
| 328 | case "package": |
| 329 | return "pkg"; |
| 330 | case "boolean": |
| 331 | return "b"; |
| 332 | case "double": |
| 333 | return "d"; |
| 334 | case "byte": |
| 335 | return "b"; |
| 336 | case "int": |
| 337 | return "i"; |
| 338 | case "short": |
| 339 | return "s"; |
| 340 | case "char": |
| 341 | return "c"; |
| 342 | case "void": |
| 343 | return "v"; |
| 344 | case "class": |
| 345 | return "clazz"; |
| 346 | case "float": |
| 347 | return "f"; |
| 348 | case "long": |
| 349 | return "l"; |
| 350 | default: |
| 351 | return SourceVersion.isKeyword(candidateName) ? candidateName + '_' : candidateName; |
| 352 | } |
| 353 | } |
| 354 | |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 355 | private SourceFiles() {} |
| 356 | } |