Snap for 5735642 from 2bff65eed14b618c746b2df5e437a4211ed1be8a to sdk-release
Change-Id: If5ef62d08c1031e41c8475026084bb9459e301c5
diff --git a/.gitignore b/.gitignore
index cbd8ca8..fabb38f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,10 +30,6 @@
gen-external-apklibs
-bazel-bin
-bazel-genfiles
-bazel-out
-bazel-testlogs
-bazel-dagger
+/bazel-*
*.pyc
diff --git a/.travis.yml b/.travis.yml
index 439bcec..9015f2e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
language: android
os: linux
-dist: precise
+dist: trusty
sudo: required
addons:
apt:
@@ -53,7 +53,7 @@
# permission to push to the repo.
- secure: "UpTUhCQzAGbr5JetRg2GZxp/dPDep/7Il3yGeyDECopciWdx41OPk/QNqAXBhNtKuEaMVsmASyoteuhgaTryQdV4qUIGVOMhES6kbOlYy3nwK44VdsNeeepwVospyDyZbxMtXq5LuHWuTADmAl1mdjNPNoziXc523zjnUzUx/EQ="
- JDK_FOR_PUBLISHING: *jdk_for_publishing
- - BAZEL_VERSION="0.19.2"
+ - BAZEL_VERSION="0.24.1"
after_success:
- util/generate-latest-docs.sh
diff --git a/Android.bp b/Android.bp
index b8ba1ab..a0f4055 100644
--- a/Android.bp
+++ b/Android.bp
@@ -88,7 +88,6 @@
jars: ["lib/javax.inject-1.jar"],
}
-
java_import_host {
name: "dagger2-bootstrap-compiler-jar",
jars: ["java/dagger/internal/codegen/bootstrap_compiler_deploy.jar"],
@@ -148,22 +147,18 @@
name: "dagger2-compiler",
processor_class: "dagger.internal.codegen.ComponentProcessor",
generates_api: true,
-
- javacflags: [
- // Required for use of javax.annotation.Generated per http://b/62050818
- "-J--add-modules=java.xml.ws.annotation",
- ],
-
use_tools_jar: true,
srcs: [
"java/dagger/internal/codegen/**/*.java",
+ "java/dagger/internal/codegen/**/*.proto",
"java/dagger/model/*.java",
"java/dagger/spi/*.java",
],
exclude_srcs: [
+ "java/dagger/internal/codegen/BindingGraphStatisticsCollector.java",
"java/dagger/internal/codegen/DaggerKythePlugin.java",
],
@@ -199,6 +194,11 @@
"dagger2-bootstrap-compiler",
],
+ proto: {
+ type: "full",
+ include_dirs: ["external/protobuf/src/"],
+ },
+
java_version: "1.8",
}
diff --git a/BUILD b/BUILD
index 651372a..8becb3e 100644
--- a/BUILD
+++ b/BUILD
@@ -63,6 +63,9 @@
"//java/dagger/internal/codegen:processor",
"//java/dagger/internal/codegen:validation",
"//java/dagger/internal/codegen:writing",
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
+ "//java/dagger/internal/codegen/serialization",
"//java/dagger/model:internal-proxies",
"//java/dagger/errorprone",
"@com_google_auto_auto_common//jar",
@@ -80,6 +83,9 @@
"//java/dagger/internal/codegen:libprocessor-src.jar",
"//java/dagger/internal/codegen:libvalidation-src.jar",
"//java/dagger/internal/codegen:libwriting-src.jar",
+ "//java/dagger/internal/codegen/javapoet:libjavapoet-src.jar",
+ "//java/dagger/internal/codegen/langmodel:liblangmodel-src.jar",
+ # TODO(ronshapiro): is there a generated src.jar for protos in Bazel?
"//java/dagger/errorprone:liberrorprone-src.jar",
],
)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 79d185a..45f15c4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,3 +23,47 @@
information on using pull requests.
[GitHub Help]: https://help.github.com/articles/about-pull-requests/
+
+## Building Dagger
+
+Dagger is built with [`bazel`](https://bazel.build).
+
+### Building Dagger from the command line
+
+* [Install Bazel](https://docs.bazel.build/versions/master/install.html)
+* Build the Dagger project with `bazel build <target>`
+ * Learn more about Bazel targets [here][bazel targets].
+ * If you see an error similar to `ERROR: missing input file
+ '@androidsdk//:build-tools/26.0.2/aapt'`, install the missing build
+ tools version with the android `sdkmanager` tool.
+* Run tests with `bazel test <target>`, or `bazel test //...` to run all
+ tests
+* You can install the Dagger libraries in your **local maven repository** by
+ running the `./util/install-local-snapshot.sh` script.
+ * It will build the libraries and install them with a `LOCAL-SNAPSHOT`
+ version.
+
+[bazel targets]: https://docs.bazel.build/versions/master/build-ref.html
+
+### Importing the Dagger project in IntelliJ/Android Studio
+
+* Visit `Preferences > Plugins` in the IDE menu.
+ * Search for `bazel` and install the plugin.
+ * If no result shows up, click on `Search in repositories`, search for
+ `bazel` and install the plugin.
+* Select `Import Bazel Project`.
+* Input the path to the Dagger project under `workspace`, click `Next`.
+* Select `Generate from BUILD file`, type `BUILD` in the `Build file` input,
+ click `Next`.
+* [Android Studio only] In the `Project View` form, uncomment one of the
+ `android_sdk_platform` lines. Pick one that you have installed, then click
+ `Finish`.
+* If you get an error on Bazel sync, `Cannot run program "bazel"`, then:
+ * In the command line, run `where bazel` and copy the output (e.g.
+ `/usr/local/bin/bazel`)
+ * In Android Studio, go to `Preferences > Bazel Settings` and replace
+ `Bazel binary location` with what you just copied.
+* Note that the first sync can take a long time. When build files are changed,
+ you can run partial syncs (which should be faster) from the file menu.
+* [Android Studio only] To view the Dagger project structure, open the
+ `Project` view and switch the top selector from `Android` to `Project`.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..59b9e25
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,17 @@
+name: "dagger2"
+description:
+ "A fast dependency injector for Android and Java."
+
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://dagger.dev"
+ }
+ url {
+ type: GIT
+ value: "https://github.com/google/dagger"
+ }
+ version: "dagger-2.23.1"
+ last_upgrade_date { year: 2019 month: 6 day: 14 }
+ license_type: PERMISSIVE
+}
diff --git a/OWNERS b/OWNERS
index 22cc91a..87a5dbe 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1 @@
-paulduffin@google.com
-nfuller@google.com
+include platform/libcore:/OWNERS
diff --git a/README.md b/README.md
index 13523c0..a9ebc26 100644
--- a/README.md
+++ b/README.md
@@ -180,12 +180,8 @@
* [Dagger development Javadocs][latestapi] (from the `master` branch
on GitHub)
* [Google's Dagger project site on GitHub][project]
- * <a href="https://plus.google.com/118328287768685565185"
- rel="publisher">Google+ Dagger Project Page</a>
- * [Google+ Dagger Users Community][community]
* 1.x (square/dagger)
* [Square's original Dagger project site on GitHub][square]
- * [Square Open Source Community][squarecommunity]
If you do not use maven, gradle, ivy, or other build systems that consume
@@ -198,9 +194,7 @@
## Building Dagger
-Dagger is built with [`bazel`]. The tests can be run with `bazel test //...`.
-`util/install-local-snapshot.sh` will build all of the Dagger libraries and
-install a copy in your local maven repository with the version `LOCAL-SNAPSHOT`.
+See [the CONTRIBUTING.md docs][Building Dagger].
## License
@@ -218,18 +212,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-[20api]: https://google.github.io/dagger/api/2.0/
+[20api]: https://dagger.dev/api/2.0/
[`bazel`]: https://bazel.build
[bazel-external-deps]: https://docs.bazel.build/versions/master/external.html#depending-on-other-bazel-projects
-[community]: https://plus.google.com/communities/111933036769103367883
+[Building Dagger]: CONTRIBUTING.md#building-dagger
[dagger-snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/dagger/
[databinding]: https://developer.android.com/topic/libraries/data-binding/
[gaktalk]: https://www.youtube.com/watch?v=oK_XtfXPkqw
-[latestapi]: https://google.github.io/dagger/api/latest/
+[latestapi]: https://dagger.dev/api/latest/
[mavenbadge-svg]: https://maven-badges.herokuapp.com/maven-central/com.google.dagger/dagger/badge.svg
[mavencentral]: https://search.maven.org/artifact/com.google.dagger/dagger
[project]: http://github.com/google/dagger/
[proposal]: https://github.com/square/dagger/issues/366
[square]: http://github.com/square/dagger/
-[squarecommunity]: https://plus.google.com/communities/109244258569782858265
-[website]: https://google.github.io/dagger
+[website]: https://dagger.dev
diff --git a/WORKSPACE b/WORKSPACE
index afdcae6..8758b38 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -16,10 +16,19 @@
http_archive(
name = "google_bazel_common",
- strip_prefix = "bazel-common-1c225e62390566a9e88916471948ddd56e5f111c",
- urls = ["https://github.com/google/bazel-common/archive/1c225e62390566a9e88916471948ddd56e5f111c.zip"],
+ strip_prefix = "bazel-common-26011657fee96a949c66500b1662c4c7288a4968",
+ urls = ["https://github.com/google/bazel-common/archive/26011657fee96a949c66500b1662c4c7288a4968.zip"],
)
load("@google_bazel_common//:workspace_defs.bzl", "google_common_workspace_rules")
google_common_workspace_rules()
+
+# This fixes an issue with protobuf starting to use zlib by default in 3.7.0.
+# TODO(ronshapiro): Figure out if this is in fact necessary, or if proto can depend on the
+# @bazel_tools library directly. See discussion in
+# https://github.com/protocolbuffers/protobuf/pull/5389#issuecomment-481785716
+bind(
+ name = "zlib",
+ actual = "@bazel_tools//third_party/zlib",
+)
diff --git a/android-annotation-stubs/gen_annotations.sh b/android-annotation-stubs/gen_annotations.sh
index 4b19fc7..21aeb46 100755
--- a/android-annotation-stubs/gen_annotations.sh
+++ b/android-annotation-stubs/gen_annotations.sh
@@ -1,15 +1,64 @@
#!/bin/bash
+declare -A INNER
+declare -A PARAMETER
+declare -A IMPORT
+
ANNOTATIONS=(
org.checkerframework.checker.nullness.compatqual.NullableDecl
+ net.ltgt.gradle.incap.IncrementalAnnotationProcessor
)
+PARAMETER["net.ltgt.gradle.incap.IncrementalAnnotationProcessor"]="IncrementalAnnotationProcessorType"
+IMPORT["net.ltgt.gradle.incap.IncrementalAnnotationProcessor"]="net.ltgt.gradle.incap.IncrementalAnnotationProcessorType"
+
for a in ${ANNOTATIONS[@]}; do
package=${a%.*}
class=${a##*.}
dir=$(dirname $0)/src/${package//.//}
file=${class}.java
+ inner=${INNER[$a]}
+ parameter=${PARAMETER[$a]}
+ import=
+
+ if [ -n "${parameter}" ]; then
+ parameter="${parameter} value();"
+ fi
+
+ for i in ${IMPORT[$a]}; do
+ import="${import}import ${i};"
+ done
mkdir -p ${dir}
- sed -e"s/__PACKAGE__/${package}/" -e"s/__CLASS__/${class}/" tmpl.java > ${dir}/${file}
+ sed -e"s/__PACKAGE__/${package}/" \
+ -e"s/__CLASS__/${class}/" \
+ -e"s/__INNER__/${inner}/" \
+ -e"s/__PARAMETER__/${parameter}/" \
+ -e"s/__IMPORT__/${import}/" \
+ $(dirname $0)/tmpl.java > ${dir}/${file}
+ google-java-format -i ${dir}/${file}
done
+
+f=$(dirname $0)/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
+cat > ${f} <<EOF
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.ltgt.gradle.incap;
+public enum IncrementalAnnotationProcessorType {
+ DYNAMIC
+}
+EOF
diff --git a/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessor.java b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessor.java
new file mode 100644
index 0000000..aa1ce76
--- /dev/null
+++ b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.ltgt.gradle.incap;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/* This is an annotation stub to avoid dependencies on annotations that aren't
+ * in the Android platform source tree. */
+
+@Target({
+ ElementType.ANNOTATION_TYPE,
+ ElementType.CONSTRUCTOR,
+ ElementType.FIELD,
+ ElementType.LOCAL_VARIABLE,
+ ElementType.METHOD,
+ ElementType.PACKAGE,
+ ElementType.PARAMETER,
+ ElementType.TYPE,
+ ElementType.TYPE_PARAMETER,
+ ElementType.TYPE_USE
+})
+@Retention(RetentionPolicy.SOURCE)
+public @interface IncrementalAnnotationProcessor {
+
+ IncrementalAnnotationProcessorType value();
+}
diff --git a/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
new file mode 100644
index 0000000..83e3590
--- /dev/null
+++ b/android-annotation-stubs/src/net/ltgt/gradle/incap/IncrementalAnnotationProcessorType.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.ltgt.gradle.incap;
+public enum IncrementalAnnotationProcessorType {
+ DYNAMIC
+}
diff --git a/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java b/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java
index 15e3f9b..2d39b0f 100644
--- a/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java
+++ b/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java
@@ -25,15 +25,16 @@
* in the Android platform source tree. */
@Target({
- ElementType.ANNOTATION_TYPE,
- ElementType.CONSTRUCTOR,
- ElementType.FIELD,
- ElementType.LOCAL_VARIABLE,
- ElementType.METHOD,
- ElementType.PACKAGE,
- ElementType.PARAMETER,
- ElementType.TYPE,
- ElementType.TYPE_PARAMETER,
- ElementType.TYPE_USE})
+ ElementType.ANNOTATION_TYPE,
+ ElementType.CONSTRUCTOR,
+ ElementType.FIELD,
+ ElementType.LOCAL_VARIABLE,
+ ElementType.METHOD,
+ ElementType.PACKAGE,
+ ElementType.PARAMETER,
+ ElementType.TYPE,
+ ElementType.TYPE_PARAMETER,
+ ElementType.TYPE_USE
+})
@Retention(RetentionPolicy.SOURCE)
public @interface NullableDecl {}
diff --git a/android-annotation-stubs/tmpl.java b/android-annotation-stubs/tmpl.java
index 814c143..c4df609 100644
--- a/android-annotation-stubs/tmpl.java
+++ b/android-annotation-stubs/tmpl.java
@@ -20,20 +20,24 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+__IMPORT__
/* This is an annotation stub to avoid dependencies on annotations that aren't
* in the Android platform source tree. */
@Target({
- ElementType.ANNOTATION_TYPE,
- ElementType.CONSTRUCTOR,
- ElementType.FIELD,
- ElementType.LOCAL_VARIABLE,
- ElementType.METHOD,
- ElementType.PACKAGE,
- ElementType.PARAMETER,
- ElementType.TYPE,
- ElementType.TYPE_PARAMETER,
- ElementType.TYPE_USE})
+ ElementType.ANNOTATION_TYPE,
+ ElementType.CONSTRUCTOR,
+ ElementType.FIELD,
+ ElementType.LOCAL_VARIABLE,
+ ElementType.METHOD,
+ ElementType.PACKAGE,
+ ElementType.PARAMETER,
+ ElementType.TYPE,
+ ElementType.TYPE_PARAMETER,
+ ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
-public @interface __CLASS__ {}
+public @interface __CLASS__ {
+ __INNER__
+ __PARAMETER__
+}
diff --git a/java/dagger/BUILD b/java/dagger/BUILD
index 5f5cfbf..3485431 100644
--- a/java/dagger/BUILD
+++ b/java/dagger/BUILD
@@ -30,7 +30,9 @@
javacopts = SOURCE_7_TARGET_7 + DOCLINT_HTML_AND_SYNTAX,
tags = ["maven_coordinates=com.google.dagger:dagger:" + POM_VERSION],
exports = ["@google_bazel_common//third_party/java/jsr330_inject"],
- deps = ["@google_bazel_common//third_party/java/jsr330_inject"],
+ deps = [
+ "@google_bazel_common//third_party/java/jsr330_inject",
+ ],
)
pom_file(
diff --git a/java/dagger/MapKey.java b/java/dagger/MapKey.java
index 89307be..46dbf93 100644
--- a/java/dagger/MapKey.java
+++ b/java/dagger/MapKey.java
@@ -100,7 +100,7 @@
* <p>(Note that there must be a class {@code MyMapKeyImpl} that implements {@code MyMapKey} in
* order to call {@link Map#get(Object)} on the provided map.)
*
- * @see <a href="https://google.github.io/dagger/multibindings#map-multibindings">Map multibinding</a>
+ * @see <a href="https://dagger.dev/multibindings#map-multibindings">Map multibinding</a>
*/
@Documented
@Target(ANNOTATION_TYPE)
diff --git a/java/dagger/Reusable.java b/java/dagger/Reusable.java
index f2419d5..2cb68aa 100644
--- a/java/dagger/Reusable.java
+++ b/java/dagger/Reusable.java
@@ -29,7 +29,7 @@
* <p>{@code @Reusable} is useful when you want to limit the number of provisions of a type, but
* there is no specific lifetime over which there must be only one instance.
*
- * @see <a href="https://google.github.io/dagger/users-guide#reusable-scope">Reusable Scope</a>
+ * @see <a href="https://dagger.dev/users-guide#reusable-scope">Reusable Scope</a>
*/
@Documented
@Beta
diff --git a/java/dagger/android/AndroidInjection.java b/java/dagger/android/AndroidInjection.java
index 102a429..2f4fb4c 100644
--- a/java/dagger/android/AndroidInjection.java
+++ b/java/dagger/android/AndroidInjection.java
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (C) 2017 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -39,79 +39,99 @@
* otherwise throws an {@link IllegalArgumentException}.
*
* @throws RuntimeException if the {@link Application} doesn't implement {@link
- * HasActivityInjector}.
+ * HasAndroidInjector} or {@link HasActivityInjector}.
*/
public static void inject(Activity activity) {
checkNotNull(activity, "activity");
Application application = activity.getApplication();
- if (!(application instanceof HasActivityInjector)) {
+ AndroidInjector<? super Activity> injector;
+ if (application instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) application).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+ } else if (application instanceof HasActivityInjector) {
+ injector = ((HasActivityInjector) application).activityInjector();
+ checkNotNull(injector, "%s.activityInjector() returned null", application.getClass());
+ } else {
throw new RuntimeException(
String.format(
- "%s does not implement %s",
+ "%s does not implement %s or %s",
application.getClass().getCanonicalName(),
+ HasAndroidInjector.class.getCanonicalName(),
HasActivityInjector.class.getCanonicalName()));
}
- AndroidInjector<Activity> activityInjector =
- ((HasActivityInjector) application).activityInjector();
- checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
-
- activityInjector.inject(activity);
+ injector.inject(activity);
}
/**
* Injects {@code fragment} if an associated {@link AndroidInjector} implementation can be found,
* otherwise throws an {@link IllegalArgumentException}.
*
- * <p>Uses the following algorithm to find the appropriate {@code AndroidInjector<Fragment>} to
- * use to inject {@code fragment}:
+ * <p>Uses the following algorithm to find the appropriate {@link AndroidInjector} to use to
+ * inject {@code fragment}:
*
* <ol>
- * <li>Walks the parent-fragment hierarchy to find the a fragment that implements {@link
- * HasFragmentInjector}, and if none do
+ * <li>Walks the parent-fragment hierarchy to find a fragment that implements {@link
+ * HasAndroidInjector} or {@link HasFragmentInjector}, and if none do
* <li>Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements
- * {@link HasFragmentInjector}, and if not
- * <li>Uses the {@link android.app.Application} if it implements {@link HasFragmentInjector}.
+ * {@link HasAndroidInjector} or {@link HasFragmentInjector}, and if not
+ * <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}
+ * {@link HasFragmentInjector}.
* </ol>
*
- * If none of them implement {@link HasFragmentInjector}, a {@link IllegalArgumentException} is
- * thrown.
+ * If none of them implement {@link HasAndroidInjector} or {@link HasFragmentInjector}, a {@link
+ * IllegalArgumentException} is thrown.
*
* @throws IllegalArgumentException if no parent fragment, activity, or application implements
- * {@link HasFragmentInjector}.
+ * {@link HasAndroidInjector} or {@link HasFragmentInjector}.
*/
public static void inject(Fragment fragment) {
checkNotNull(fragment, "fragment");
- HasFragmentInjector hasFragmentInjector = findHasFragmentInjector(fragment);
+
+ Object hasInjector = findHasFragmentInjector(fragment);
+ AndroidInjector<? super Fragment> injector;
+ if (hasInjector instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) hasInjector).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", hasInjector.getClass());
+ } else if (hasInjector instanceof HasFragmentInjector) {
+ injector = ((HasFragmentInjector) hasInjector).fragmentInjector();
+ checkNotNull(injector, "%s.fragmentInjector() returned null", hasInjector.getClass());
+ } else {
+ throw new RuntimeException(
+ String.format(
+ "%s does not implement %s or %s",
+ hasInjector.getClass().getCanonicalName(),
+ HasAndroidInjector.class.getCanonicalName(),
+ HasFragmentInjector.class.getCanonicalName()));
+ }
+
if (Log.isLoggable(TAG, DEBUG)) {
Log.d(
TAG,
String.format(
"An injector for %s was found in %s",
fragment.getClass().getCanonicalName(),
- hasFragmentInjector.getClass().getCanonicalName()));
+ hasInjector.getClass().getCanonicalName()));
}
- AndroidInjector<Fragment> fragmentInjector = hasFragmentInjector.fragmentInjector();
- checkNotNull(
- fragmentInjector, "%s.fragmentInjector() returned null", hasFragmentInjector.getClass());
-
- fragmentInjector.inject(fragment);
+ injector.inject(fragment);
}
- private static HasFragmentInjector findHasFragmentInjector(Fragment fragment) {
+ private static Object findHasFragmentInjector(Fragment fragment) {
Fragment parentFragment = fragment;
while ((parentFragment = parentFragment.getParentFragment()) != null) {
- if (parentFragment instanceof HasFragmentInjector) {
- return (HasFragmentInjector) parentFragment;
+ if (parentFragment instanceof HasAndroidInjector
+ || parentFragment instanceof HasFragmentInjector) {
+ return parentFragment;
}
}
Activity activity = fragment.getActivity();
- if (activity instanceof HasFragmentInjector) {
- return (HasFragmentInjector) activity;
+ if (activity instanceof HasAndroidInjector || activity instanceof HasFragmentInjector) {
+ return activity;
}
- if (activity.getApplication() instanceof HasFragmentInjector) {
- return (HasFragmentInjector) activity.getApplication();
+ Application application = activity.getApplication();
+ if (application instanceof HasAndroidInjector || application instanceof HasFragmentInjector) {
+ return application;
}
throw new IllegalArgumentException(
String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
@@ -122,23 +142,28 @@
* otherwise throws an {@link IllegalArgumentException}.
*
* @throws RuntimeException if the {@link Application} doesn't implement {@link
- * HasServiceInjector}.
+ * HasAndroidInjector} or {@link HasServiceInjector}.
*/
public static void inject(Service service) {
checkNotNull(service, "service");
Application application = service.getApplication();
- if (!(application instanceof HasServiceInjector)) {
+ AndroidInjector<? super Service> injector;
+ if (application instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) application).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+ } else if (application instanceof HasServiceInjector) {
+ injector = ((HasServiceInjector) application).serviceInjector();
+ checkNotNull(injector, "%s.serviceInjector() returned null", application.getClass());
+ } else {
throw new RuntimeException(
String.format(
- "%s does not implement %s",
+ "%s does not implement %s or %s",
application.getClass().getCanonicalName(),
+ HasAndroidInjector.class.getCanonicalName(),
HasServiceInjector.class.getCanonicalName()));
}
- AndroidInjector<Service> serviceInjector = ((HasServiceInjector) application).serviceInjector();
- checkNotNull(serviceInjector, "%s.serviceInjector() returned null", application.getClass());
-
- serviceInjector.inject(service);
+ injector.inject(service);
}
/**
@@ -146,28 +171,32 @@
* be found, otherwise throws an {@link IllegalArgumentException}.
*
* @throws RuntimeException if the {@link Application} from {@link
- * Context#getApplicationContext()} doesn't implement {@link HasBroadcastReceiverInjector}.
+ * Context#getApplicationContext()} doesn't implement {@link HasAndroidInjector} or {@link
+ * HasBroadcastReceiverInjector}.
*/
public static void inject(BroadcastReceiver broadcastReceiver, Context context) {
checkNotNull(broadcastReceiver, "broadcastReceiver");
checkNotNull(context, "context");
+
Application application = (Application) context.getApplicationContext();
- if (!(application instanceof HasBroadcastReceiverInjector)) {
+ AndroidInjector<? super BroadcastReceiver> injector;
+ if (application instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) application).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+ } else if (application instanceof HasBroadcastReceiverInjector) {
+ injector = ((HasBroadcastReceiverInjector) application).broadcastReceiverInjector();
+ checkNotNull(
+ injector, "%s.broadcastReceiverInjector() returned null", application.getClass());
+ } else {
throw new RuntimeException(
String.format(
- "%s does not implement %s",
+ "%s does not implement %s or %s",
application.getClass().getCanonicalName(),
+ HasAndroidInjector.class.getCanonicalName(),
HasBroadcastReceiverInjector.class.getCanonicalName()));
}
- AndroidInjector<BroadcastReceiver> broadcastReceiverInjector =
- ((HasBroadcastReceiverInjector) application).broadcastReceiverInjector();
- checkNotNull(
- broadcastReceiverInjector,
- "%s.broadcastReceiverInjector() returned null",
- application.getClass());
-
- broadcastReceiverInjector.inject(broadcastReceiver);
+ injector.inject(broadcastReceiver);
}
/**
@@ -175,27 +204,29 @@
* found, otherwise throws an {@link IllegalArgumentException}.
*
* @throws RuntimeException if the {@link Application} doesn't implement {@link
- * HasContentProviderInjector}.
+ * HasAndroidInjector} or {@link HasContentProviderInjector}.
*/
public static void inject(ContentProvider contentProvider) {
checkNotNull(contentProvider, "contentProvider");
Application application = (Application) contentProvider.getContext().getApplicationContext();
- if (!(application instanceof HasContentProviderInjector)) {
+
+ AndroidInjector<? super ContentProvider> injector;
+ if (application instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) application).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", application.getClass());
+ } else if (application instanceof HasContentProviderInjector) {
+ injector = ((HasContentProviderInjector) application).contentProviderInjector();
+ checkNotNull(injector, "%s.contentProviderInjector() returned null", application.getClass());
+ } else {
throw new RuntimeException(
String.format(
- "%s does not implement %s",
+ "%s does not implement %s or %s",
application.getClass().getCanonicalName(),
- HasContentProviderInjector.class.getCanonicalName()));
+ HasAndroidInjector.class.getCanonicalName(),
+ HasBroadcastReceiverInjector.class.getCanonicalName()));
}
- AndroidInjector<ContentProvider> contentProviderInjector =
- ((HasContentProviderInjector) application).contentProviderInjector();
- checkNotNull(
- contentProviderInjector,
- "%s.contentProviderInjector() returned null",
- application.getClass());
-
- contentProviderInjector.inject(contentProvider);
+ injector.inject(contentProvider);
}
private AndroidInjection() {}
diff --git a/java/dagger/android/ContributesAndroidInjector.java b/java/dagger/android/ContributesAndroidInjector.java
index 76492d1..5aa9312 100644
--- a/java/dagger/android/ContributesAndroidInjector.java
+++ b/java/dagger/android/ContributesAndroidInjector.java
@@ -32,7 +32,7 @@
* a concrete Android framework type (e.g. {@code FooActivity}, {@code BarFragment}, {@code
* MyService}, etc). The method should have no parameters.
*
- * <p>For more information, see <a href="https://google.github.io/dagger/android">the docs</a>
+ * <p>For more information, see <a href="https://dagger.dev/android">the docs</a>
*/
@Documented
@Retention(RUNTIME)
diff --git a/java/dagger/android/DaggerActivity.java b/java/dagger/android/DaggerActivity.java
index 1fd9b9d..43708f3 100644
--- a/java/dagger/android/DaggerActivity.java
+++ b/java/dagger/android/DaggerActivity.java
@@ -28,9 +28,9 @@
* inject {@link Fragment}s attached to it.
*/
@Beta
-public abstract class DaggerActivity extends Activity implements HasFragmentInjector {
+public abstract class DaggerActivity extends Activity implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -39,7 +39,7 @@
}
@Override
- public AndroidInjector<Fragment> fragmentInjector() {
- return fragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/DaggerApplication.java b/java/dagger/android/DaggerApplication.java
index ca9ea43..d09050b 100644
--- a/java/dagger/android/DaggerApplication.java
+++ b/java/dagger/android/DaggerApplication.java
@@ -16,36 +16,21 @@
package dagger.android;
-import android.app.Activity;
import android.app.Application;
-import android.app.Fragment;
-import android.app.Service;
-import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import com.google.errorprone.annotations.ForOverride;
import dagger.internal.Beta;
import javax.inject.Inject;
/**
- * An {@link Application} that injects its members and can be used to inject {@link Activity}s,
- * {@link Fragment}s, {@link Service}s, {@link BroadcastReceiver}s and {@link ContentProvider}s
- * attached to it. Injection is performed in {@link #onCreate()} or the first call to {@link
- * AndroidInjection#inject(ContentProvider)}, whichever happens first.
+ * An {@link Application} that injects its members and can be used to inject objects that the
+ * Android framework instantiates, such as Activitys, Fragments, or Services. Injection is performed
+ * in {@link #onCreate()} or the first call to {@link AndroidInjection#inject(ContentProvider)},
+ * whichever happens first.
*/
@Beta
-public abstract class DaggerApplication extends Application
- implements HasActivityInjector,
- HasFragmentInjector,
- HasServiceInjector,
- HasBroadcastReceiverInjector,
- HasContentProviderInjector {
-
- @Inject DispatchingAndroidInjector<Activity> activityInjector;
- @Inject DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
- @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
- @Inject DispatchingAndroidInjector<Service> serviceInjector;
- @Inject DispatchingAndroidInjector<ContentProvider> contentProviderInjector;
- private volatile boolean needToInject = true;
+public abstract class DaggerApplication extends Application implements HasAndroidInjector {
+ @Inject volatile DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onCreate() {
@@ -69,14 +54,14 @@
* allowing for a partially-constructed instance to escape.
*/
private void injectIfNecessary() {
- if (needToInject) {
+ if (androidInjector == null) {
synchronized (this) {
- if (needToInject) {
+ if (androidInjector == null) {
@SuppressWarnings("unchecked")
AndroidInjector<DaggerApplication> applicationInjector =
(AndroidInjector<DaggerApplication>) applicationInjector();
applicationInjector.inject(this);
- if (needToInject) {
+ if (androidInjector == null) {
throw new IllegalStateException(
"The AndroidInjector returned from applicationInjector() did not inject the "
+ "DaggerApplication");
@@ -86,37 +71,12 @@
}
}
- @Inject
- void setInjected() {
- needToInject = false;
- }
-
@Override
- public DispatchingAndroidInjector<Activity> activityInjector() {
- return activityInjector;
- }
-
- @Override
- public DispatchingAndroidInjector<Fragment> fragmentInjector() {
- return fragmentInjector;
- }
-
- @Override
- public DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
- return broadcastReceiverInjector;
- }
-
- @Override
- public DispatchingAndroidInjector<Service> serviceInjector() {
- return serviceInjector;
- }
-
- // injectIfNecessary is called here but not on the other *Injector() methods because it is the
- // only one that should be called (in AndroidInjection.inject(ContentProvider)) before
- // Application.onCreate()
- @Override
- public AndroidInjector<ContentProvider> contentProviderInjector() {
+ public AndroidInjector<Object> androidInjector() {
+ // injectIfNecessary should already be called unless we are about to inject a ContentProvider,
+ // which can happen before Application.onCreate()
injectIfNecessary();
- return contentProviderInjector;
+
+ return androidInjector;
}
}
diff --git a/java/dagger/android/DaggerDialogFragment.java b/java/dagger/android/DaggerDialogFragment.java
index 00e65f2..3cbc0f1 100644
--- a/java/dagger/android/DaggerDialogFragment.java
+++ b/java/dagger/android/DaggerDialogFragment.java
@@ -33,9 +33,9 @@
*/
@Deprecated
@Beta
-public abstract class DaggerDialogFragment extends DialogFragment implements HasFragmentInjector {
+public abstract class DaggerDialogFragment extends DialogFragment implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onAttach(Context context) {
@@ -44,7 +44,7 @@
}
@Override
- public AndroidInjector<Fragment> fragmentInjector() {
- return childFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/DaggerFragment.java b/java/dagger/android/DaggerFragment.java
index c95c457..187820b 100644
--- a/java/dagger/android/DaggerFragment.java
+++ b/java/dagger/android/DaggerFragment.java
@@ -32,9 +32,9 @@
*/
@Beta
@Deprecated
-public abstract class DaggerFragment extends Fragment implements HasFragmentInjector {
+public abstract class DaggerFragment extends Fragment implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onAttach(Context context) {
@@ -43,7 +43,7 @@
}
@Override
- public AndroidInjector<Fragment> fragmentInjector() {
- return childFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/HasAndroidInjector.java b/java/dagger/android/HasAndroidInjector.java
new file mode 100644
index 0000000..3b49718
--- /dev/null
+++ b/java/dagger/android/HasAndroidInjector.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android;
+
+import dagger.internal.Beta;
+
+/** Provides an {@link AndroidInjector}. */
+@Beta
+public interface HasAndroidInjector {
+ /** Returns an {@link AndroidInjector}. */
+ AndroidInjector<Object> androidInjector();
+}
diff --git a/java/dagger/android/processor/AndroidInjectorDescriptor.java b/java/dagger/android/processor/AndroidInjectorDescriptor.java
index 7c5ae07..3ec6613 100644
--- a/java/dagger/android/processor/AndroidInjectorDescriptor.java
+++ b/java/dagger/android/processor/AndroidInjectorDescriptor.java
@@ -43,9 +43,7 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
-import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
/**
@@ -85,13 +83,9 @@
}
static final class Validator {
- private final Types types;
- private final Elements elements;
private final Messager messager;
- Validator(Types types, Elements elements, Messager messager) {
- this.types = types;
- this.elements = elements;
+ Validator(Messager messager) {
this.messager = messager;
}
diff --git a/java/dagger/android/processor/AndroidMapKeyValidator.java b/java/dagger/android/processor/AndroidMapKeyValidator.java
index 4cdcd2a..f6e808a 100644
--- a/java/dagger/android/processor/AndroidMapKeyValidator.java
+++ b/java/dagger/android/processor/AndroidMapKeyValidator.java
@@ -131,7 +131,7 @@
messager.printMessage(
Kind.ERROR,
String.format(
- "%s should bind %s, not %s. See https://google.github.io/dagger/android",
+ "%s should bind %s, not %s. See https://dagger.dev/android",
method, requiredReturnType, returnType),
method);
}
diff --git a/java/dagger/android/processor/AndroidProcessor.java b/java/dagger/android/processor/AndroidProcessor.java
index c468170..5c17341 100644
--- a/java/dagger/android/processor/AndroidProcessor.java
+++ b/java/dagger/android/processor/AndroidProcessor.java
@@ -18,6 +18,7 @@
import static javax.tools.Diagnostic.Kind.ERROR;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
+import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
import com.google.auto.common.BasicAnnotationProcessor;
import com.google.auto.service.AutoService;
@@ -36,6 +37,7 @@
import javax.lang.model.SourceVersion;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
+import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
/**
* An {@linkplain javax.annotation.processing.Processor annotation processor} to verify usage of
@@ -51,6 +53,7 @@
* R8 in <a href="https://r8.googlesource.com/r8/+/389123dfcc11e6dda0eec31ab62e1b7eb0da80d2">May
* 2018</a>.
*/
+@IncrementalAnnotationProcessor(ISOLATING)
@AutoService(Processor.class)
public final class AndroidProcessor extends BasicAnnotationProcessor {
private static final String FLAG_EXPERIMENTAL_USE_STRING_KEYS =
@@ -66,7 +69,7 @@
return ImmutableList.of(
new AndroidMapKeyValidator(elements, types, messager),
new ContributesAndroidInjectorGenerator(
- new AndroidInjectorDescriptor.Validator(types, elements, messager),
+ new AndroidInjectorDescriptor.Validator(messager),
useStringKeys(),
filer,
elements,
diff --git a/java/dagger/android/processor/BUILD b/java/dagger/android/processor/BUILD
index 00c1021..5754143 100644
--- a/java/dagger/android/processor/BUILD
+++ b/java/dagger/android/processor/BUILD
@@ -22,8 +22,7 @@
"DOCLINT_HTML_AND_SYNTAX",
"DOCLINT_REFERENCES",
)
-load("//tools:maven.bzl", "pom_file", "POM_VERSION")
-load("//tools:simple_jar.bzl", "simple_jar")
+load("//tools:maven.bzl", "POM_VERSION", "pom_file")
filegroup(
name = "srcs",
@@ -34,13 +33,13 @@
name = "processor",
srcs = [":srcs"],
javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
- resource_jars = [":processor_manifest_files.jar"],
tags = ["maven_coordinates=com.google.dagger:dagger-android-processor:" + POM_VERSION],
deps = [
"@google_bazel_common//third_party/java/guava",
"@google_bazel_common//third_party/java/auto:service",
"@google_bazel_common//third_party/java/auto:value",
"@google_bazel_common//third_party/java/auto:common",
+ "@google_bazel_common//third_party/java/incap",
"@google_bazel_common//third_party/java/javapoet",
"@google_bazel_common//third_party/java/google_java_format",
"//java/dagger:core",
@@ -65,11 +64,6 @@
visibility = ["//visibility:private"],
)
-simple_jar(
- name = "processor_manifest_files",
- srcs = glob(["META-INF/**"]),
-)
-
pom_file(
name = "pom",
artifact_id = "dagger-android-processor",
diff --git a/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java b/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java
index bae454b..5c99fd4 100644
--- a/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java
+++ b/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java
@@ -35,7 +35,6 @@
import com.google.common.collect.SetMultimap;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
@@ -171,7 +170,7 @@
ClassName subcomponentFactoryName) {
AnnotationSpec.Builder subcomponentAnnotation = AnnotationSpec.builder(Subcomponent.class);
for (ClassName module : descriptor.modules()) {
- subcomponentAnnotation.addMember("modules", CodeBlock.of("$T.class", module));
+ subcomponentAnnotation.addMember("modules", "$T.class", module);
}
return interfaceBuilder(subcomponentName)
diff --git a/java/dagger/android/processor/META-INF/gradle/incremental.annotation.processors b/java/dagger/android/processor/META-INF/gradle/incremental.annotation.processors
deleted file mode 100644
index 22b8a95..0000000
--- a/java/dagger/android/processor/META-INF/gradle/incremental.annotation.processors
+++ /dev/null
@@ -1 +0,0 @@
-dagger.android.processor.AndroidProcessor,isolating
diff --git a/java/dagger/android/support/AndroidSupportInjection.java b/java/dagger/android/support/AndroidSupportInjection.java
index f5e206e..1624345 100644
--- a/java/dagger/android/support/AndroidSupportInjection.java
+++ b/java/dagger/android/support/AndroidSupportInjection.java
@@ -20,9 +20,11 @@
import static dagger.internal.Preconditions.checkNotNull;
import android.app.Activity;
+import android.app.Application;
import android.support.v4.app.Fragment;
import android.util.Log;
import dagger.android.AndroidInjector;
+import dagger.android.HasAndroidInjector;
import dagger.internal.Beta;
/** Injects core Android types from support libraries. */
@@ -31,62 +33,75 @@
private static final String TAG = "dagger.android.support";
/**
- * Injects {@code fragment} if an associated {@link dagger.android.AndroidInjector} implementation
- * can be found, otherwise throws an {@link IllegalArgumentException}.
+ * Injects {@code fragment} if an associated {@link AndroidInjector} implementation can be found,
+ * otherwise throws an {@link IllegalArgumentException}.
*
- * <p>Uses the following algorithm to find the appropriate {@code AndroidInjector<Fragment>} to
- * use to inject {@code fragment}:
+ * <p>Uses the following algorithm to find the appropriate {@link AndroidInjector} to use to
+ * inject {@code fragment}:
*
* <ol>
- * <li>Walks the parent-fragment hierarchy to find the a fragment that implements {@link
- * HasSupportFragmentInjector}, and if none do
+ * <li>Walks the parent-fragment hierarchy to find a fragment that implements {@link
+ * HasAndroidInjector} or {@link HasSupportFragmentInjector}, and if none do
* <li>Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements
- * {@link HasSupportFragmentInjector}, and if not
- * <li>Uses the {@link android.app.Application} if it implements {@link
- * HasSupportFragmentInjector}.
+ * {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}, and if not
+ * <li>Uses the {@link android.app.Application} if it implements {@link HasAndroidInjector}
+ * {@link HasSupportFragmentInjector}.
* </ol>
*
- * If none of them implement {@link HasSupportFragmentInjector}, a {@link
- * IllegalArgumentException} is thrown.
+ * If none of them implement {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}, a
+ * {@link IllegalArgumentException} is thrown.
*
* @throws IllegalArgumentException if no parent fragment, activity, or application implements
- * {@link HasSupportFragmentInjector}.
+ * {@link HasAndroidInjector} or {@link HasSupportFragmentInjector}.
*/
public static void inject(Fragment fragment) {
checkNotNull(fragment, "fragment");
- HasSupportFragmentInjector hasSupportFragmentInjector = findHasFragmentInjector(fragment);
+
+ Object hasInjector = findHasSupportFragmentInjector(fragment);
+ AndroidInjector<? super Fragment> injector;
+ if (hasInjector instanceof HasAndroidInjector) {
+ injector = ((HasAndroidInjector) hasInjector).androidInjector();
+ checkNotNull(injector, "%s.androidInjector() returned null", hasInjector.getClass());
+ } else if (hasInjector instanceof HasSupportFragmentInjector) {
+ injector = ((HasSupportFragmentInjector) hasInjector).supportFragmentInjector();
+ checkNotNull(injector, "%s.supportFragmentInjector() returned null", hasInjector.getClass());
+ } else {
+ throw new RuntimeException(
+ String.format(
+ "%s does not implement %s or %s",
+ hasInjector.getClass().getCanonicalName(),
+ HasAndroidInjector.class.getCanonicalName(),
+ HasSupportFragmentInjector.class.getCanonicalName()));
+ }
+
if (Log.isLoggable(TAG, DEBUG)) {
Log.d(
TAG,
String.format(
"An injector for %s was found in %s",
fragment.getClass().getCanonicalName(),
- hasSupportFragmentInjector.getClass().getCanonicalName()));
+ hasInjector.getClass().getCanonicalName()));
}
- AndroidInjector<Fragment> fragmentInjector =
- hasSupportFragmentInjector.supportFragmentInjector();
- checkNotNull(
- fragmentInjector,
- "%s.supportFragmentInjector() returned null",
- hasSupportFragmentInjector.getClass());
-
- fragmentInjector.inject(fragment);
+ injector.inject(fragment);
}
- private static HasSupportFragmentInjector findHasFragmentInjector(Fragment fragment) {
+ private static Object findHasSupportFragmentInjector(Fragment fragment) {
Fragment parentFragment = fragment;
while ((parentFragment = parentFragment.getParentFragment()) != null) {
- if (parentFragment instanceof HasSupportFragmentInjector) {
- return (HasSupportFragmentInjector) parentFragment;
+ if (parentFragment instanceof HasAndroidInjector
+ || parentFragment instanceof HasSupportFragmentInjector) {
+ return parentFragment;
}
}
Activity activity = fragment.getActivity();
- if (activity instanceof HasSupportFragmentInjector) {
- return (HasSupportFragmentInjector) activity;
+ if (activity instanceof HasAndroidInjector || activity instanceof HasSupportFragmentInjector) {
+ return activity;
}
- if (activity.getApplication() instanceof HasSupportFragmentInjector) {
- return (HasSupportFragmentInjector) activity.getApplication();
+ Application application = activity.getApplication();
+ if (application instanceof HasAndroidInjector
+ || application instanceof HasSupportFragmentInjector) {
+ return application;
}
throw new IllegalArgumentException(
String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
diff --git a/java/dagger/android/support/DaggerAppCompatActivity.java b/java/dagger/android/support/DaggerAppCompatActivity.java
index 4621e9a..ccc4faa 100644
--- a/java/dagger/android/support/DaggerAppCompatActivity.java
+++ b/java/dagger/android/support/DaggerAppCompatActivity.java
@@ -18,12 +18,11 @@
import android.os.Bundle;
import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import dagger.android.AndroidInjection;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasFragmentInjector;
+import dagger.android.HasAndroidInjector;
import dagger.internal.Beta;
import javax.inject.Inject;
@@ -33,10 +32,9 @@
*/
@Beta
public abstract class DaggerAppCompatActivity extends AppCompatActivity
- implements HasFragmentInjector, HasSupportFragmentInjector {
+ implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
- @Inject DispatchingAndroidInjector<android.app.Fragment> frameworkFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -45,12 +43,7 @@
}
@Override
- public AndroidInjector<Fragment> supportFragmentInjector() {
- return supportFragmentInjector;
- }
-
- @Override
- public AndroidInjector<android.app.Fragment> fragmentInjector() {
- return frameworkFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/support/DaggerAppCompatDialogFragment.java b/java/dagger/android/support/DaggerAppCompatDialogFragment.java
index 6592c23..1efaeec 100644
--- a/java/dagger/android/support/DaggerAppCompatDialogFragment.java
+++ b/java/dagger/android/support/DaggerAppCompatDialogFragment.java
@@ -21,6 +21,7 @@
import android.support.v7.app.AppCompatDialogFragment;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
+import dagger.android.HasAndroidInjector;
import dagger.internal.Beta;
import javax.inject.Inject;
@@ -31,9 +32,9 @@
*/
@Beta
public abstract class DaggerAppCompatDialogFragment extends AppCompatDialogFragment
- implements HasSupportFragmentInjector {
+ implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onAttach(Context context) {
@@ -42,7 +43,7 @@
}
@Override
- public AndroidInjector<Fragment> supportFragmentInjector() {
- return childFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/support/DaggerApplication.java b/java/dagger/android/support/DaggerApplication.java
index 294d2aa..1cb3bd8 100644
--- a/java/dagger/android/support/DaggerApplication.java
+++ b/java/dagger/android/support/DaggerApplication.java
@@ -16,27 +16,15 @@
package dagger.android.support;
-import android.support.v4.app.Fragment;
import dagger.android.AndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import javax.inject.Inject;
/**
- * An {@link android.app.Application} that injects its members and can be used to inject {@link
- * android.app.Activity}s, {@linkplain android.app.Fragment framework fragments}, {@linkplain
- * Fragment support fragments}, {@link android.app.Service}s, {@link
- * android.content.BroadcastReceiver}s, and {@link android.content.ContentProvider}s attached to it.
+ * An {@link Application} that injects its members and can be used to inject classes that the
+ * Android framework instantiates. Injection is performed in {@link #onCreate()} or the first call
+ * to {@link AndroidInjection#inject(ContentProvider)}, whichever happens first.
*/
-public abstract class DaggerApplication extends dagger.android.DaggerApplication
- implements HasSupportFragmentInjector {
-
- @Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
-
+// TODO(ronshapiro): deprecate and remove this class
+public abstract class DaggerApplication extends dagger.android.DaggerApplication {
@Override
protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
-
- @Override
- public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
- return supportFragmentInjector;
- }
}
diff --git a/java/dagger/android/support/DaggerDialogFragment.java b/java/dagger/android/support/DaggerDialogFragment.java
index 18feb6e..69b90bc 100644
--- a/java/dagger/android/support/DaggerDialogFragment.java
+++ b/java/dagger/android/support/DaggerDialogFragment.java
@@ -21,6 +21,7 @@
import android.support.v4.app.Fragment;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
+import dagger.android.HasAndroidInjector;
import dagger.internal.Beta;
import javax.inject.Inject;
@@ -30,10 +31,9 @@
* its members will be injected again.
*/
@Beta
-public abstract class DaggerDialogFragment extends DialogFragment
- implements HasSupportFragmentInjector {
+public abstract class DaggerDialogFragment extends DialogFragment implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onAttach(Context context) {
@@ -42,7 +42,7 @@
}
@Override
- public AndroidInjector<Fragment> supportFragmentInjector() {
- return childFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/android/support/DaggerFragment.java b/java/dagger/android/support/DaggerFragment.java
index c7335a8..332cdaa 100644
--- a/java/dagger/android/support/DaggerFragment.java
+++ b/java/dagger/android/support/DaggerFragment.java
@@ -20,6 +20,7 @@
import android.support.v4.app.Fragment;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
+import dagger.android.HasAndroidInjector;
import dagger.internal.Beta;
import javax.inject.Inject;
@@ -29,9 +30,9 @@
* members will be injected again.
*/
@Beta
-public abstract class DaggerFragment extends Fragment implements HasSupportFragmentInjector {
+public abstract class DaggerFragment extends Fragment implements HasAndroidInjector {
- @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;
+ @Inject DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onAttach(Context context) {
@@ -40,7 +41,7 @@
}
@Override
- public AndroidInjector<Fragment> supportFragmentInjector() {
- return childFragmentInjector;
+ public AndroidInjector<Object> androidInjector() {
+ return androidInjector;
}
}
diff --git a/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java b/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
index c2d9024..e98fe9b 100644
--- a/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
+++ b/java/dagger/errorprone/AndroidSupportInjectionModuleMigrator.java
@@ -58,13 +58,12 @@
@Override
public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {
if (MODULE_CLASS_LITERAL.matches(tree, state)) {
- return buildDescription(tree)
- .addFix(
- SuggestedFix.builder()
- .replace(tree, "AndroidInjectionModule.class")
- .addImport("dagger.android.AndroidInjectionModule")
- .build())
- .build();
+ return describeMatch(
+ tree,
+ SuggestedFix.builder()
+ .replace(tree, "AndroidInjectionModule.class")
+ .addImport("dagger.android.AndroidInjectionModule")
+ .build());
}
return Description.NO_MATCH;
}
diff --git a/java/dagger/grpc/server/CallScoped.java b/java/dagger/grpc/server/CallScoped.java
index a477f9d..4b9d14f 100644
--- a/java/dagger/grpc/server/CallScoped.java
+++ b/java/dagger/grpc/server/CallScoped.java
@@ -16,12 +16,14 @@
package dagger.grpc.server;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
import javax.inject.Scope;
-/**
- * A scope that lasts as long as a single gRPC {@link io.grpc.ServerCall}.
- */
+/** A scope that lasts as long as a single gRPC {@link io.grpc.ServerCall}. */
+@Retention(RUNTIME)
@Scope
@Documented
public @interface CallScoped {}
diff --git a/java/dagger/grpc/server/README.md b/java/dagger/grpc/server/README.md
index c8d027c..5fe8d5c 100644
--- a/java/dagger/grpc/server/README.md
+++ b/java/dagger/grpc/server/README.md
@@ -1,10 +1,10 @@
# Dagger-gRPC on the Server
This package contains the public types used to create gRPC server applications
-using https://google.github.io/dagger.
+using https://dagger.dev.
It is maintained by the Dagger team.
It is in development, and is planned for open-source release as part of Dagger.
-See user documentation at https://google.github.io/dagger/grpc.
+See user documentation at https://dagger.dev/grpc.
diff --git a/java/dagger/grpc/server/processor/GrpcServiceProcessor.java b/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
index 58495e2..e361fdb 100644
--- a/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
+++ b/java/dagger/grpc/server/processor/GrpcServiceProcessor.java
@@ -40,7 +40,7 @@
/**
* Generates code from types annotated with {@link GrpcService @GrpcService}.
*
- * @see <a href="https://google.github.io/dagger/grpc">https://google.github.io/dagger/grpc</a>
+ * @see <a href="https://dagger.dev/grpc">https://dagger.dev/grpc</a>
*/
@AutoService(Processor.class)
public class GrpcServiceProcessor extends BasicAnnotationProcessor implements ProcessingStep {
diff --git a/java/dagger/internal/ComponentDefinitionType.java b/java/dagger/internal/ComponentDefinitionType.java
new file mode 100644
index 0000000..1ab8b13
--- /dev/null
+++ b/java/dagger/internal/ComponentDefinitionType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Target;
+
+/** Specifies the user-defined component that is being implemented by the annotated class. */
+@Target(TYPE)
+public @interface ComponentDefinitionType {
+ Class<?> value();
+}
diff --git a/java/dagger/internal/ConfigureInitializationParameters.java b/java/dagger/internal/ConfigureInitializationParameters.java
new file mode 100644
index 0000000..1ca0fbb
--- /dev/null
+++ b/java/dagger/internal/ConfigureInitializationParameters.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a {@code configureInitialization()} method with {@code ComponentRequirement}s that it
+ * accepts as parameters.
+ */
+@Target(METHOD)
+public @interface ConfigureInitializationParameters {
+ /**
+ * The list of parameters.
+ *
+ * Each value is a {@link dagger.internal.codegen.serialization.ComponentRequirementProto}
+ * serialized in Base64.
+ */
+ String[] value() default {};
+}
diff --git a/java/dagger/internal/ModifiableBinding.java b/java/dagger/internal/ModifiableBinding.java
new file mode 100644
index 0000000..1e658e4
--- /dev/null
+++ b/java/dagger/internal/ModifiableBinding.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Target;
+
+/** Annotates methods that implement bindings that may be modified by subclass implementations. */
+@Target(METHOD)
+public @interface ModifiableBinding {
+ /** {@code ModifiableBindingType} of the binding. */
+ // TODO(ronshapiro): should this be a shared enum with dagger.internal.codegen?
+ String modifiableBindingType();
+
+ /** A {@link dagger.internal.codegen.serialization.BindingRequestProto} serialized in Base64. */
+ String bindingRequest();
+
+ /**
+ * For a multibinding, the keys of all contributions it depends on in this implementation.
+ */
+ String[] multibindingContributions() default {};
+}
diff --git a/java/dagger/internal/ModifiableModule.java b/java/dagger/internal/ModifiableModule.java
new file mode 100644
index 0000000..983321e
--- /dev/null
+++ b/java/dagger/internal/ModifiableModule.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+/**
+ * Annotates methods that return {@linkplain dagger.Module modules} that may be modified by subclass
+ * implementations.
+ */
+public @interface ModifiableModule {
+ /** The serialized {@code ComponentRequirement} of this method's module. */
+ String value();
+}
diff --git a/java/dagger/internal/codegen/AnnotationCreatorGenerator.java b/java/dagger/internal/codegen/AnnotationCreatorGenerator.java
index c38b747..273f552 100644
--- a/java/dagger/internal/codegen/AnnotationCreatorGenerator.java
+++ b/java/dagger/internal/codegen/AnnotationCreatorGenerator.java
@@ -21,7 +21,7 @@
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static dagger.internal.codegen.AnnotationExpression.createMethodName;
import static dagger.internal.codegen.AnnotationExpression.getAnnotationCreatorClassName;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -36,6 +36,7 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
diff --git a/java/dagger/internal/codegen/AnnotationExpression.java b/java/dagger/internal/codegen/AnnotationExpression.java
index 9072fe2..8d729e2 100644
--- a/java/dagger/internal/codegen/AnnotationExpression.java
+++ b/java/dagger/internal/codegen/AnnotationExpression.java
@@ -17,8 +17,8 @@
package dagger.internal.codegen;
import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
import static dagger.internal.codegen.SourceFiles.classFileName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
import static java.util.stream.Collectors.toList;
import com.google.auto.common.MoreElements;
diff --git a/java/dagger/internal/codegen/AnnotationProtoConverter.java b/java/dagger/internal/codegen/AnnotationProtoConverter.java
new file mode 100644
index 0000000..282d8ca
--- /dev/null
+++ b/java/dagger/internal/codegen/AnnotationProtoConverter.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Maps.transformValues;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import dagger.internal.codegen.serialization.AnnotationProto;
+import dagger.internal.codegen.serialization.AnnotationValueProto;
+import java.util.Collections;
+import java.util.List;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+/** Converts {@link AnnotationMirror}s to {@link AnnotationProto}s and vice-versa. */
+final class AnnotationProtoConverter {
+ private final TypeProtoConverter typeProtoConverter;
+
+ @Inject
+ AnnotationProtoConverter(TypeProtoConverter typeProtoConverter) {
+ this.typeProtoConverter = typeProtoConverter;
+ }
+
+ /** Translates an {@link AnnotationMirror} to a proto representation. */
+ static AnnotationProto toProto(AnnotationMirror annotationMirror) {
+ AnnotationProto.Builder builder = AnnotationProto.newBuilder();
+ builder.setAnnotationType(TypeProtoConverter.toProto(annotationMirror.getAnnotationType()));
+ getAnnotationValuesWithDefaults(annotationMirror)
+ .forEach(
+ (attribute, value) ->
+ builder.putAllValues(
+ Collections.singletonMap(
+ attribute.getSimpleName().toString(), annotationValueProto(value))));
+ return builder.build();
+ }
+
+ /** Creates an {@link AnnotationMirror} from its proto representation. */
+ AnnotationMirror fromProto(AnnotationProto annotation) {
+ return SimpleAnnotationMirror.of(
+ MoreTypes.asTypeElement(typeProtoConverter.fromProto(annotation.getAnnotationType())),
+ transformValues(annotation.getValues(), AnnotationValueFromProto::new));
+ }
+
+ private static final AnnotationValueVisitor<
+ AnnotationValueProto.Builder, AnnotationValueProto.Builder>
+ ANNOTATION_VALUE_TO_PROTO =
+ new SimpleAnnotationValueVisitor8<
+ AnnotationValueProto.Builder, AnnotationValueProto.Builder>() {
+ @Override
+ public AnnotationValueProto.Builder visitAnnotation(
+ AnnotationMirror nestedAnnotation, AnnotationValueProto.Builder builder) {
+ return builder
+ .setNestedAnnotation(toProto(nestedAnnotation))
+ .setKind(AnnotationValueProto.Kind.ANNOTATION);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitBoolean(
+ boolean b, AnnotationValueProto.Builder builder) {
+ return builder.setBooleanValue(b).setKind(AnnotationValueProto.Kind.BOOLEAN);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitChar(
+ char c, AnnotationValueProto.Builder builder) {
+ return builder
+ .setStringValue(String.valueOf(c))
+ .setKind(AnnotationValueProto.Kind.CHAR);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitByte(
+ byte b, AnnotationValueProto.Builder builder) {
+ return builder.setIntValue(b).setKind(AnnotationValueProto.Kind.BYTE);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitShort(
+ short s, AnnotationValueProto.Builder builder) {
+ return builder.setIntValue(s).setKind(AnnotationValueProto.Kind.SHORT);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitInt(
+ int i, AnnotationValueProto.Builder builder) {
+ return builder.setIntValue(i).setKind(AnnotationValueProto.Kind.INT);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitFloat(
+ float f, AnnotationValueProto.Builder builder) {
+ return builder.setFloatValue(f).setKind(AnnotationValueProto.Kind.FLOAT);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitLong(
+ long l, AnnotationValueProto.Builder builder) {
+ return builder.setLongValue(l).setKind(AnnotationValueProto.Kind.LONG);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitDouble(
+ double d, AnnotationValueProto.Builder builder) {
+ return builder.setDoubleValue(d).setKind(AnnotationValueProto.Kind.DOUBLE);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitString(
+ String s, AnnotationValueProto.Builder builder) {
+ return builder.setStringValue(s).setKind(AnnotationValueProto.Kind.STRING);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitType(
+ TypeMirror t, AnnotationValueProto.Builder builder) {
+ return builder
+ .setClassLiteral(TypeProtoConverter.toProto(t))
+ .setKind(AnnotationValueProto.Kind.CLASS_LITERAL);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitEnumConstant(
+ VariableElement c, AnnotationValueProto.Builder builder) {
+ return builder
+ .setEnumType(TypeProtoConverter.toProto(c.asType()))
+ .setEnumName(c.getSimpleName().toString())
+ .setKind(AnnotationValueProto.Kind.ENUM);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitArray(
+ List<? extends AnnotationValue> values, AnnotationValueProto.Builder builder) {
+ values.forEach(value -> builder.addArrayValues(annotationValueProto(value)));
+ return builder.setKind(AnnotationValueProto.Kind.ARRAY);
+ }
+
+ @Override
+ public AnnotationValueProto.Builder visitUnknown(
+ AnnotationValue av, AnnotationValueProto.Builder builder) {
+ throw new UnsupportedOperationException(av.toString());
+ }
+ };
+
+ /** Translates an {@link AnnotationValue} to a proto representation. */
+ private static AnnotationValueProto annotationValueProto(AnnotationValue annotationValue) {
+ return annotationValue
+ .accept(ANNOTATION_VALUE_TO_PROTO, AnnotationValueProto.newBuilder())
+ .build();
+ }
+
+ private class AnnotationValueFromProto implements AnnotationValue {
+ private final AnnotationValueProto proto;
+
+ AnnotationValueFromProto(AnnotationValueProto proto) {
+ this.proto = proto;
+ }
+
+ @Override
+ public Object getValue() {
+ switch (proto.getKind()) {
+ case BOOLEAN:
+ return proto.getBooleanValue();
+ case BYTE:
+ return (byte) proto.getIntValue();
+ case SHORT:
+ return (short) proto.getIntValue();
+ case CHAR:
+ return getCharValue();
+ case INT:
+ return proto.getIntValue();
+ case FLOAT:
+ return proto.getFloatValue();
+ case LONG:
+ return proto.getLongValue();
+ case DOUBLE:
+ return proto.getDoubleValue();
+ case STRING:
+ return proto.getStringValue();
+ case CLASS_LITERAL:
+ return typeProtoConverter.fromProto(proto.getClassLiteral());
+ case ENUM:
+ return getEnumConstant();
+ case ANNOTATION:
+ return fromProto(proto.getNestedAnnotation());
+ case ARRAY:
+ return getArrayValues();
+ case UNKNOWN:
+ case UNRECOGNIZED:
+ // fall through
+ }
+ throw new AssertionError(proto);
+ }
+
+ @Override
+ public <R, P> R accept(AnnotationValueVisitor<R, P> visitor, P passedValue) {
+ switch (proto.getKind()) {
+ case BOOLEAN:
+ return visitor.visitBoolean(proto.getBooleanValue(), passedValue);
+ case BYTE:
+ return visitor.visitByte((byte) proto.getIntValue(), passedValue);
+ case SHORT:
+ return visitor.visitShort((short) proto.getIntValue(), passedValue);
+ case CHAR:
+ return visitor.visitChar(getCharValue(), passedValue);
+ case INT:
+ return visitor.visitInt(proto.getIntValue(), passedValue);
+ case FLOAT:
+ return visitor.visitFloat(proto.getFloatValue(), passedValue);
+ case LONG:
+ return visitor.visitLong(proto.getLongValue(), passedValue);
+ case DOUBLE:
+ return visitor.visitDouble(proto.getDoubleValue(), passedValue);
+ case STRING:
+ return visitor.visitString((String) getValue(), passedValue);
+ case CLASS_LITERAL:
+ return visitor.visitType((TypeMirror) getValue(), passedValue);
+ case ENUM:
+ return visitor.visitEnumConstant((VariableElement) getValue(), passedValue);
+ case ANNOTATION:
+ return visitor.visitAnnotation((AnnotationMirror) getValue(), passedValue);
+ case ARRAY:
+ return visitor.visitArray(getArrayValues(), passedValue);
+ case UNKNOWN:
+ case UNRECOGNIZED:
+ // fall through
+ }
+ throw new AssertionError(proto);
+ }
+
+ private char getCharValue() {
+ checkState(proto.getKind().equals(AnnotationValueProto.Kind.CHAR));
+ return proto.getStringValue().charAt(0);
+ }
+
+ private VariableElement getEnumConstant() {
+ checkState(proto.getKind().equals(AnnotationValueProto.Kind.ENUM));
+ TypeMirror enumType = typeProtoConverter.fromProto(proto.getEnumType());
+ return fieldsIn(MoreTypes.asTypeElement(enumType).getEnclosedElements()).stream()
+ .filter(value -> value.getSimpleName().contentEquals(proto.getEnumName()))
+ .findFirst()
+ .get();
+ }
+
+ private ImmutableList<AnnotationValue> getArrayValues() {
+ checkState(proto.getKind().equals(AnnotationValueProto.Kind.ARRAY));
+ return proto.getArrayValuesList().stream()
+ .map(AnnotationValueFromProto::new)
+ .collect(toImmutableList());
+ }
+ }
+}
diff --git a/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java b/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java
index 1e66e59..fc30eaa 100644
--- a/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/AnonymousProviderCreationExpression.java
@@ -17,12 +17,13 @@
package dagger.internal.codegen;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.CodeBlocks.anonymousProvider;
+import static dagger.internal.codegen.javapoet.CodeBlocks.anonymousProvider;
import static dagger.model.RequestKind.INSTANCE;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.Expression;
/**
* A {@link javax.inject.Provider} creation expression for an anonymous inner class whose
diff --git a/java/dagger/internal/codegen/AnyBindingMethodValidator.java b/java/dagger/internal/codegen/AnyBindingMethodValidator.java
index 23393b6..bad9636 100644
--- a/java/dagger/internal/codegen/AnyBindingMethodValidator.java
+++ b/java/dagger/internal/codegen/AnyBindingMethodValidator.java
@@ -18,9 +18,9 @@
import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableMap;
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index e7b6b60..824a72e 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -19,18 +19,19 @@
load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX", "DOCLINT_REFERENCES")
load("//tools:maven.bzl", "POM_VERSION", "pom_file")
-load("//tools:simple_jar.bzl", "simple_jar")
EXPERIMENTAL_VISUALIZER_SRCS = ["BindingNetworkVisualizer.java"]
-KYTHE_SRCS = [
- "DaggerKythePlugin.java",
- "JavacPluginModule.java",
-]
+JAVAC_PLUGIN_MODULE_SRCS = ["JavacPluginModule.java"]
+
+KYTHE_SRCS = ["DaggerKythePlugin.java"]
+
+STATISTICS_COLLECTOR_SRCS = ["BindingGraphStatisticsCollector.java"]
CODEGEN_SRCS = glob(
["*.java"],
- exclude = EXPERIMENTAL_VISUALIZER_SRCS + KYTHE_SRCS,
+ exclude = EXPERIMENTAL_VISUALIZER_SRCS + KYTHE_SRCS + STATISTICS_COLLECTOR_SRCS +
+ JAVAC_PLUGIN_MODULE_SRCS,
)
CODEGEN_PLUGINS = [":bootstrap_compiler_plugin"]
@@ -47,6 +48,7 @@
"@google_bazel_common//third_party/java/jsr250_annotations",
"@google_bazel_common//third_party/java/jsr330_inject",
"//java/dagger:core",
+ "//java/dagger/internal/codegen/serialization",
"//java/dagger/producers",
"//java/dagger/model",
"//java/dagger/spi",
@@ -78,23 +80,20 @@
java_library(
name = "base",
srcs = [
- "Accessibility.java",
- "AnnotationSpecs.java",
+ "AnnotationProtoConverter.java",
"ClearableCache.java",
- "CodeBlocks.java",
"CompilerOptions.java",
"ComponentAnnotation.java",
"ContributionType.java",
- "DaggerElements.java",
"DaggerStatistics.java",
"DaggerStatisticsCollectingProcessingStep.java",
"DaggerStatisticsCollector.java",
"DaggerStatisticsRecorder.java",
- "DaggerTypes.java",
"DiagnosticFormatting.java",
- "Expression.java",
+ "ElementFormatter.java",
"FeatureStatus.java",
"Formatter.java",
+ "ForwardingCompilerOptions.java",
"FrameworkTypes.java",
"InjectionAnnotations.java",
"Keys.java",
@@ -105,6 +104,7 @@
"MoreAnnotationValues.java",
"MultibindingAnnotations.java",
"OptionalType.java",
+ "ProcessingEnvironmentCompilerOptions.java",
"ProcessingOptions.java",
"RequestKinds.java",
"Scopes.java",
@@ -114,8 +114,7 @@
"SourceFileGenerationException.java", # Used in :writing and :processor
"SourceFileGenerator.java", # Needed by InjectBindingRegistry in :binding and also :writing
"TypeCheckingProcessingStep.java",
- "TypeNames.java",
- "TypeSpecs.java",
+ "TypeProtoConverter.java",
"UniqueNameSet.java",
"Util.java",
"ValidationType.java",
@@ -123,7 +122,10 @@
],
plugins = CODEGEN_PLUGINS,
tags = ["maven:merged"],
- deps = CODEGEN_DEPS,
+ deps = CODEGEN_DEPS + [
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
+ ],
)
# Classes that help to build a model of the binding graph
@@ -165,6 +167,7 @@
"FrameworkType.java",
"FrameworkTypeMapper.java",
"InjectBindingRegistry.java",
+ "InjectionSiteFactory.java",
"KeyFactory.java",
"KeyVariableNamer.java", # needs ConfigurationAnnotations, SourceFiles
"MapKeys.java",
@@ -184,7 +187,11 @@
],
plugins = CODEGEN_PLUGINS,
tags = ["maven:merged"],
- deps = CODEGEN_DEPS + [":base"],
+ deps = CODEGEN_DEPS + [
+ ":base",
+ "//java/dagger/internal/codegen/langmodel",
+ "//java/dagger/internal/codegen/javapoet",
+ ],
)
# Code related to validating the user-written Dagger code
@@ -192,10 +199,14 @@
name = "validation",
srcs = [
"AnyBindingMethodValidator.java",
+ "BindingElementValidator.java",
"BindingGraphPlugins.java",
"BindingGraphValidator.java",
"BindingMethodProcessingStep.java",
"BindingMethodValidator.java",
+ "BindsInstanceElementValidator.java",
+ "BindsInstanceMethodValidator.java",
+ "BindsInstanceParameterValidator.java",
"BindsInstanceProcessingStep.java",
"BindsMethodValidator.java",
"BindsOptionalOfMethodValidator.java",
@@ -221,6 +232,7 @@
deps = CODEGEN_DEPS + [
":base",
":binding",
+ "//java/dagger/internal/codegen/langmodel",
],
)
@@ -244,6 +256,7 @@
":base",
":binding",
":validation",
+ "//java/dagger/internal/codegen/langmodel",
],
)
@@ -333,14 +346,11 @@
deps = CODEGEN_DEPS + [
":base",
":binding",
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
],
)
-simple_jar(
- name = "processor_manifest_files",
- srcs = glob(["META-INF/**"]),
-)
-
# The processor's "main", if you will
java_library(
name = "processor",
@@ -355,6 +365,7 @@
"ComponentProcessingStep.java",
"ComponentProcessor.java",
"CurrentImplementationSubcomponent.java",
+ "DeserializedComponentImplementationBuilder.java",
"GenerationOptionsModule.java",
"InjectBindingRegistryImpl.java",
"InjectBindingRegistryModule.java",
@@ -369,7 +380,6 @@
"TopLevelImplementationComponent.java",
],
plugins = CODEGEN_PLUGINS,
- resource_jars = [":processor_manifest_files.jar"],
tags = ["maven_coordinates=com.google.dagger:dagger-compiler:" + POM_VERSION],
deps = CODEGEN_DEPS + [
":base",
@@ -377,6 +387,9 @@
":binding_graph_validation",
":writing",
":validation",
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
+ "@google_bazel_common//third_party/java/incap",
],
)
@@ -391,6 +404,23 @@
":binding_graph_validation",
":writing",
":validation",
+ "//java/dagger/internal/codegen/serialization",
+ "//java/dagger/internal/codegen/javapoet",
+ ],
+)
+
+java_library(
+ name = "javac-plugin-module",
+ srcs = JAVAC_PLUGIN_MODULE_SRCS,
+ plugins = [":component-codegen"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":base",
+ ":binding",
+ ":javac",
+ ":processor",
+ "//java/dagger:core",
+ "//java/dagger/internal/codegen/langmodel",
],
)
@@ -401,18 +431,26 @@
deps = [
":base",
":binding",
+ ":javac",
+ ":javac-plugin-module",
":kythe_plugin",
":processor",
"//java/dagger:core",
+ "//java/dagger/internal/codegen/langmodel",
"//java/dagger/model",
"//java/dagger/producers",
- "@bazel_tools//third_party/java/jdk/langtools:javac",
"@google_bazel_common//third_party/java/auto:common",
"@google_bazel_common//third_party/java/auto:service",
"@google_bazel_common//third_party/java/guava",
],
)
+# Replacement for @bazel_tools//third_party/java/jdk/langtools:javac, which seems to have gone away?
+java_import(
+ name = "javac",
+ jars = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
+)
+
# A _deploy.jar consisting of the java_librarys in https://github.com/kythe/kythe needed to build a
# Kythe plugin
# TODO(ronshapiro): replace this with a http_archive of the next release in
@@ -433,7 +471,6 @@
name = "bootstrap_compiler_plugin",
generates_api = 1,
processor_class = "dagger.internal.codegen.ComponentProcessor",
- visibility = ["//visibility:private"],
deps = [":bootstrap_compiler"],
)
@@ -452,7 +489,11 @@
srcs = CODEGEN_SRCS,
javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
plugins = CODEGEN_PLUGINS,
- deps = CODEGEN_DEPS,
+ deps = CODEGEN_DEPS + [
+ "//java/dagger/internal/codegen/langmodel",
+ "//java/dagger/internal/codegen/javapoet",
+ "@google_bazel_common//third_party/java/incap",
+ ],
)
java_plugin(
@@ -468,3 +509,19 @@
],
deps = [":processor"],
)
+
+java_library(
+ name = "statistics",
+ srcs = STATISTICS_COLLECTOR_SRCS,
+ plugins = [":component-codegen"],
+ deps = [
+ ":base",
+ ":binding",
+ ":javac",
+ ":javac-plugin-module",
+ ":processor",
+ "//java/dagger:core",
+ "//java/dagger/model",
+ "@google_bazel_common//third_party/java/error_prone:check_api",
+ ],
+)
diff --git a/java/dagger/internal/codegen/Binding.java b/java/dagger/internal/codegen/Binding.java
index 46e8b75..c0f6b71 100644
--- a/java/dagger/internal/codegen/Binding.java
+++ b/java/dagger/internal/codegen/Binding.java
@@ -32,6 +32,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingKind;
import dagger.model.DependencyRequest;
import dagger.model.Key;
@@ -82,6 +83,11 @@
/** The {@link BindingType} of this binding. */
abstract BindingType bindingType();
+ /** The {@link FrameworkType} of this binding. */
+ final FrameworkType frameworkType() {
+ return FrameworkType.forBindingType(bindingType());
+ }
+
/**
* The explicit set of {@link DependencyRequest dependencies} required to satisfy this binding as
* defined by the user-defined injection sites.
@@ -112,7 +118,7 @@
* union of {@link #explicitDependencies()} and {@link #implicitDependencies()}. This returns an
* unmodifiable set.
*/
- ImmutableSet<DependencyRequest> dependencies() {
+ final ImmutableSet<DependencyRequest> dependencies() {
return dependencies.get();
}
@@ -158,7 +164,7 @@
/* TODO(dpb): The stable-order postcondition is actually hard to verify in code for two equal
* instances of Binding, because it really depends on the order of the binding's dependencies,
* and two equal instances of Binding may have the same dependencies in a different order. */
- ImmutableList<FrameworkDependency> frameworkDependencies() {
+ final ImmutableList<FrameworkDependency> frameworkDependencies() {
return frameworkDependencies.get();
}
@@ -206,7 +212,7 @@
* multiple times if the {@linkplain Binding#unresolved() unresolved} binding requires it. If that
* distinction is not important, the entries can be merged into a single mapping.
*/
- ImmutableList<DependencyAssociation> dependencyAssociations() {
+ final ImmutableList<DependencyAssociation> dependencyAssociations() {
return dependencyAssociations.get();
}
@@ -230,7 +236,8 @@
* Returns the mapping from each {@linkplain #dependencies dependency} to its associated {@link
* FrameworkDependency}.
*/
- ImmutableMap<DependencyRequest, FrameworkDependency> dependenciesToFrameworkDependenciesMap() {
+ final ImmutableMap<DependencyRequest, FrameworkDependency>
+ dependenciesToFrameworkDependenciesMap() {
return frameworkDependenciesMap.get();
}
diff --git a/java/dagger/internal/codegen/BindingDeclaration.java b/java/dagger/internal/codegen/BindingDeclaration.java
index d7aa1fb..c9520cd 100644
--- a/java/dagger/internal/codegen/BindingDeclaration.java
+++ b/java/dagger/internal/codegen/BindingDeclaration.java
@@ -16,6 +16,7 @@
package dagger.internal.codegen;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.model.BindingKind;
import dagger.model.Key;
import java.util.Optional;
@@ -48,7 +49,7 @@
* The type enclosing the {@link #bindingElement()}, or {@link Optional#empty()} if {@link
* #bindingElement()} is empty.
*/
- Optional<TypeElement> bindingTypeElement() {
+ final Optional<TypeElement> bindingTypeElement() {
return bindingElement().map(DaggerElements::closestEnclosingTypeElement);
}
diff --git a/java/dagger/internal/codegen/BindingDeclarationFormatter.java b/java/dagger/internal/codegen/BindingDeclarationFormatter.java
index 1ba5d96..d850165 100644
--- a/java/dagger/internal/codegen/BindingDeclarationFormatter.java
+++ b/java/dagger/internal/codegen/BindingDeclarationFormatter.java
@@ -17,8 +17,8 @@
package dagger.internal.codegen;
import static com.google.common.collect.Sets.immutableEnumSet;
-import static dagger.internal.codegen.DaggerElements.elementToString;
import static dagger.internal.codegen.DiagnosticFormatting.stripCommonTypePrefixes;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
import static javax.lang.model.element.ElementKind.PARAMETER;
import static javax.lang.model.type.TypeKind.DECLARED;
import static javax.lang.model.type.TypeKind.EXECUTABLE;
diff --git a/java/dagger/internal/codegen/BindingElementValidator.java b/java/dagger/internal/codegen/BindingElementValidator.java
new file mode 100644
index 0000000..0051912
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingElementValidator.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
+import static dagger.internal.codegen.MapKeys.getMapKeys;
+import static dagger.internal.codegen.Scopes.scopesOf;
+import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static javax.lang.model.type.TypeKind.ARRAY;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.TYPEVAR;
+import static javax.lang.model.type.TypeKind.VOID;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.FormatMethod;
+import dagger.MapKey;
+import dagger.Provides;
+import dagger.model.Key;
+import dagger.model.Scope;
+import dagger.multibindings.ElementsIntoSet;
+import dagger.multibindings.IntoMap;
+import dagger.producers.Produces;
+import java.lang.annotation.Annotation;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.inject.Qualifier;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+/** A validator for elements that represent binding declarations. */
+abstract class BindingElementValidator<E extends Element> {
+ private final Class<? extends Annotation> bindingAnnotation;
+ private final AllowsMultibindings allowsMultibindings;
+ private final AllowsScoping allowsScoping;
+ private final Map<E, ValidationReport<E>> cache = new HashMap<>();
+
+ /**
+ * Creates a validator object.
+ *
+ * @param bindingAnnotation the annotation on an element that identifies it as a binding element
+ */
+ protected BindingElementValidator(
+ Class<? extends Annotation> bindingAnnotation,
+ AllowsMultibindings allowsMultibindings,
+ AllowsScoping allowsScoping) {
+ this.bindingAnnotation = bindingAnnotation;
+ this.allowsMultibindings = allowsMultibindings;
+ this.allowsScoping = allowsScoping;
+ }
+
+ /** Returns a {@link ValidationReport} for {@code element}. */
+ final ValidationReport<E> validate(E element) {
+ return reentrantComputeIfAbsent(cache, element, this::validateUncached);
+ }
+
+ private ValidationReport<E> validateUncached(E element) {
+ return elementValidator(element).validate();
+ }
+
+ /**
+ * Returns an error message of the form "<{@link #bindingElements()}> <i>rule</i>", where
+ * <i>rule</i> comes from calling {@link String#format(String, Object...)} on {@code ruleFormat}
+ * and the other arguments.
+ */
+ @FormatMethod
+ protected final String bindingElements(String ruleFormat, Object... args) {
+ return new Formatter().format("%s ", bindingElements()).format(ruleFormat, args).toString();
+ }
+
+ /**
+ * The kind of elements that this validator validates. Should be plural. Used for error reporting.
+ */
+ protected abstract String bindingElements();
+
+ /** The verb describing the {@link ElementValidator#bindingElementType()} in error messages. */
+ // TODO(ronshapiro,dpb): improve the name of this method and it's documentation.
+ protected abstract String bindingElementTypeVerb();
+
+ /** The error message when a binding element has a bad type. */
+ protected String badTypeMessage() {
+ return bindingElements(
+ "must %s a primitive, an array, a type variable, or a declared type",
+ bindingElementTypeVerb());
+ }
+
+ /**
+ * The error message when a the type for a binding element with {@link
+ * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a not set type.
+ */
+ protected String elementsIntoSetNotASetMessage() {
+ return bindingElements(
+ "annotated with @ElementsIntoSet must %s a Set", bindingElementTypeVerb());
+ }
+
+ /**
+ * The error message when a the type for a binding element with {@link
+ * ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} is a raw set.
+ */
+ protected String elementsIntoSetRawSetMessage() {
+ return bindingElements(
+ "annotated with @ElementsIntoSet cannot %s a raw Set", bindingElementTypeVerb());
+ }
+
+ /*** Returns an {@link ElementValidator} for validating the given {@code element}. */
+ protected abstract ElementValidator elementValidator(E element);
+
+ /** Validator for a single binding element. */
+ protected abstract class ElementValidator {
+ protected final E element;
+ protected final ValidationReport.Builder<E> report;
+
+ protected ElementValidator(E element) {
+ this.element = element;
+ this.report = ValidationReport.about(element);
+ }
+
+ /** Checks the element for validity. */
+ private ValidationReport<E> validate() {
+ checkType();
+ checkQualifiers();
+ checkMapKeys();
+ checkMultibindings();
+ checkScopes();
+ checkAdditionalProperties();
+ return report.build();
+ }
+
+ /** Check any additional properties of the element. Does nothing by default. */
+ protected void checkAdditionalProperties() {}
+
+ /**
+ * The type declared by this binding element. This may differ from a binding's {@link
+ * Key#type()}, for example in multibindings. An {@link Optional#empty()} return value indicates
+ * that the contributed type is ambiguous or missing, i.e. a {@code @BindsInstance} method with
+ * zero or many parameters.
+ */
+ // TODO(dpb): should this be an ImmutableList<TypeMirror>, with this class checking the size?
+ protected abstract Optional<TypeMirror> bindingElementType();
+
+ /**
+ * Adds an error if the {@link #bindingElementType() binding element type} is not appropriate.
+ *
+ * <p>Adds an error if the type is not a primitive, array, declared type, or type variable.
+ *
+ * <p>If the binding is not a multibinding contribution, adds an error if the type is a
+ * framework type.
+ *
+ * <p>If the element has {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES}, adds an
+ * error if the type is not a {@code Set<T>} for some {@code T}
+ */
+ protected void checkType() {
+ switch (ContributionType.fromBindingElement(element)) {
+ case UNIQUE:
+ /* Validate that a unique binding is not attempting to bind a framework type. This
+ * validation is only appropriate for unique bindings because multibindings may collect
+ * framework types. E.g. Set<Provider<Foo>> is perfectly reasonable. */
+ checkFrameworkType();
+ // fall through
+
+ case SET:
+ case MAP:
+ bindingElementType().ifPresent(type -> checkKeyType(type));
+ break;
+
+ case SET_VALUES:
+ checkSetValuesType();
+ }
+ }
+
+ /**
+ * Adds an error if {@code keyType} is not a primitive, declared type, array, or type variable.
+ */
+ protected void checkKeyType(TypeMirror keyType) {
+ TypeKind kind = keyType.getKind();
+ if (kind.equals(VOID)) {
+ report.addError(bindingElements("must %s a value (not void)", bindingElementTypeVerb()));
+ } else if (!(kind.isPrimitive()
+ || kind.equals(DECLARED)
+ || kind.equals(ARRAY)
+ || kind.equals(TYPEVAR))) {
+ report.addError(badTypeMessage());
+ }
+ }
+
+ /**
+ * Adds an error if the type for an element with {@link ElementsIntoSet @ElementsIntoSet} or
+ * {@code SET_VALUES} is not a a {@code Set<T>} for a reasonable {@code T}.
+ */
+ // TODO(gak): should we allow "covariant return" for set values?
+ protected void checkSetValuesType() {
+ bindingElementType().ifPresent(keyType -> checkSetValuesType(keyType));
+ }
+
+ /** Adds an error if {@code type} is not a {@code Set<T>} for a reasonable {@code T}. */
+ protected final void checkSetValuesType(TypeMirror type) {
+ if (!SetType.isSet(type)) {
+ report.addError(elementsIntoSetNotASetMessage());
+ } else {
+ SetType setType = SetType.from(type);
+ if (setType.isRawType()) {
+ report.addError(elementsIntoSetRawSetMessage());
+ } else {
+ checkKeyType(setType.elementType());
+ }
+ }
+ }
+
+ /**
+ * Adds an error if the element has more than one {@linkplain Qualifier qualifier} annotation.
+ */
+ private void checkQualifiers() {
+ ImmutableSet<? extends AnnotationMirror> qualifiers = getQualifiers(element);
+ if (qualifiers.size() > 1) {
+ for (AnnotationMirror qualifier : qualifiers) {
+ report.addError(
+ bindingElements("may not use more than one @Qualifier"),
+ element,
+ qualifier);
+ }
+ }
+ }
+
+ /**
+ * Adds an error if an {@link IntoMap @IntoMap} element doesn't have exactly one {@link
+ * MapKey @MapKey} annotation, or if an element that is {@link IntoMap @IntoMap} has any.
+ */
+ private void checkMapKeys() {
+ if (!allowsMultibindings.allowsMultibindings()) {
+ return;
+ }
+ ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(element);
+ if (ContributionType.fromBindingElement(element).equals(ContributionType.MAP)) {
+ switch (mapKeys.size()) {
+ case 0:
+ report.addError(bindingElements("of type map must declare a map key"));
+ break;
+ case 1:
+ break;
+ default:
+ report.addError(bindingElements("may not have more than one map key"));
+ break;
+ }
+ } else if (!mapKeys.isEmpty()) {
+ report.addError(bindingElements("of non map type cannot declare a map key"));
+ }
+ }
+
+ /**
+ * Adds errors if:
+ *
+ * <ul>
+ * <li>the element doesn't allow {@linkplain MultibindingAnnotations multibinding annotations}
+ * and has any
+ * <li>the element does allow them but has more than one
+ * <li>the element has a multibinding annotation and its {@link Provides} or {@link Produces}
+ * annotation has a {@code type} parameter.
+ * </ul>
+ */
+ private void checkMultibindings() {
+ ImmutableSet<AnnotationMirror> multibindingAnnotations =
+ MultibindingAnnotations.forElement(element);
+
+ switch (allowsMultibindings) {
+ case NO_MULTIBINDINGS:
+ for (AnnotationMirror annotation : multibindingAnnotations) {
+ report.addError(
+ bindingElements("cannot have multibinding annotations"),
+ element,
+ annotation);
+ }
+ break;
+
+ case ALLOWS_MULTIBINDINGS:
+ if (multibindingAnnotations.size() > 1) {
+ for (AnnotationMirror annotation : multibindingAnnotations) {
+ report.addError(
+ bindingElements("cannot have more than one multibinding annotation"),
+ element,
+ annotation);
+ }
+ }
+ break;
+ }
+
+ // TODO(ronshapiro): move this into ProvidesMethodValidator
+ if (bindingAnnotation.equals(Provides.class)) {
+ AnnotationMirror bindingAnnotationMirror =
+ getAnnotationMirror(element, bindingAnnotation).get();
+ boolean usesProvidesType = false;
+ for (ExecutableElement member : bindingAnnotationMirror.getElementValues().keySet()) {
+ usesProvidesType |= member.getSimpleName().contentEquals("type");
+ }
+ if (usesProvidesType && !multibindingAnnotations.isEmpty()) {
+ report.addError(
+ "@Provides.type cannot be used with multibinding annotations", element);
+ }
+ }
+ }
+
+ /**
+ * Adds an error if the element has a scope but doesn't allow scoping, or if it has more than
+ * one {@linkplain Scope scope} annotation.
+ */
+ private void checkScopes() {
+ ImmutableSet<Scope> scopes = scopesOf(element);
+ String error = null;
+ switch (allowsScoping) {
+ case ALLOWS_SCOPING:
+ if (scopes.size() <= 1) {
+ return;
+ }
+ error = bindingElements("cannot use more than one @Scope");
+ break;
+ case NO_SCOPING:
+ error = bindingElements("cannot be scoped");
+ break;
+ }
+ verifyNotNull(error);
+ for (Scope scope : scopes) {
+ report.addError(error, element, scope.scopeAnnotation());
+ }
+ }
+
+ /**
+ * Adds an error if the {@link #bindingElementType() type} is a {@linkplain FrameworkTypes
+ * framework type}.
+ */
+ private void checkFrameworkType() {
+ if (bindingElementType().filter(FrameworkTypes::isFrameworkType).isPresent()) {
+ report.addError(bindingElements("must not %s framework types", bindingElementTypeVerb()));
+ }
+ }
+ }
+
+ /** Whether to check multibinding annotations. */
+ enum AllowsMultibindings {
+ /**
+ * This element disallows multibinding annotations, so don't bother checking for their validity.
+ * {@link MultibindingAnnotationsProcessingStep} will add errors if the element has any
+ * multibinding annotations.
+ */
+ NO_MULTIBINDINGS,
+
+ /** This element allows multibinding annotations, so validate them. */
+ ALLOWS_MULTIBINDINGS,
+ ;
+
+ private boolean allowsMultibindings() {
+ return this == ALLOWS_MULTIBINDINGS;
+ }
+ }
+
+ /** How to check scoping annotations. */
+ enum AllowsScoping {
+ /** This element disallows scoping, so check that no scope annotations are present. */
+ NO_SCOPING,
+
+ /** This element allows scoping, so validate that there's at most one scope annotation. */
+ ALLOWS_SCOPING,
+ ;
+ }
+}
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index 9ac6edc..65200f7 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -16,12 +16,14 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.lang.model.type.TypeMirror;
/** A factory of code expressions used to access a single request for a binding in a component. */
diff --git a/java/dagger/internal/codegen/BindingFactory.java b/java/dagger/internal/codegen/BindingFactory.java
index 5405bfd..564b412 100644
--- a/java/dagger/internal/codegen/BindingFactory.java
+++ b/java/dagger/internal/codegen/BindingFactory.java
@@ -26,7 +26,6 @@
import static dagger.internal.codegen.ComponentDescriptor.isComponentProductionMethod;
import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
import static dagger.internal.codegen.ContributionBinding.bindingKindForMultibindingKey;
-import static dagger.internal.codegen.DaggerElements.DECLARATION_ORDER;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
import static dagger.internal.codegen.MapKeys.getMapKey;
@@ -46,49 +45,40 @@
import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
import static javax.lang.model.element.ElementKind.METHOD;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.SetMultimap;
import dagger.Module;
import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
import dagger.internal.codegen.ProductionBinding.ProductionKind;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
import dagger.producers.Produced;
import dagger.producers.Producer;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
import java.util.Optional;
-import java.util.Set;
import java.util.function.BiFunction;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor6;
/** A factory for {@link Binding} objects. */
final class BindingFactory {
private final DaggerTypes types;
private final KeyFactory keyFactory;
private final DependencyRequestFactory dependencyRequestFactory;
+ private final InjectionSiteFactory injectionSiteFactory;
private final DaggerElements elements;
@Inject
@@ -96,11 +86,13 @@
DaggerTypes types,
DaggerElements elements,
KeyFactory keyFactory,
- DependencyRequestFactory dependencyRequestFactory) {
+ DependencyRequestFactory dependencyRequestFactory,
+ InjectionSiteFactory injectionSiteFactory) {
this.types = types;
this.elements = elements;
this.keyFactory = keyFactory;
this.dependencyRequestFactory = dependencyRequestFactory;
+ this.injectionSiteFactory = injectionSiteFactory;
}
/**
@@ -144,7 +136,7 @@
.bindingElement(constructorElement)
.key(key)
.provisionDependencies(provisionDependencies)
- .injectionSites(getInjectionSites(constructedType))
+ .injectionSites(injectionSiteFactory.getInjectionSites(constructedType))
.kind(INJECTION)
.scope(uniqueScopeOf(constructorElement.getEnclosingElement()));
@@ -214,7 +206,7 @@
builder.unresolved(create.apply(method, MoreElements.asType(method.getEnclosingElement())));
}
return builder
- .contributionType(ContributionType.fromBindingMethod(method))
+ .contributionType(ContributionType.fromBindingElement(method))
.bindingElement(method)
.contributingModule(contributedBy)
.key(key)
@@ -493,7 +485,8 @@
types.erasure(declaredType));
declaredType = resolved;
}
- ImmutableSortedSet<InjectionSite> injectionSites = getInjectionSites(declaredType);
+ ImmutableSortedSet<InjectionSite> injectionSites =
+ injectionSiteFactory.getInjectionSites(declaredType);
ImmutableSet<DependencyRequest> dependencies =
injectionSites
.stream()
@@ -512,115 +505,4 @@
: Optional.empty(),
injectionSites);
}
-
- private final ElementVisitor<Optional<InjectionSite>, DeclaredType> injectionSiteVisitor =
- new ElementKindVisitor6<Optional<InjectionSite>, DeclaredType>(Optional.empty()) {
- @Override
- public Optional<InjectionSite> visitExecutableAsMethod(
- ExecutableElement e, DeclaredType type) {
- return Optional.of(injectionSiteForInjectMethod(e, type));
- }
-
- @Override
- public Optional<InjectionSite> visitVariableAsField(VariableElement e, DeclaredType type) {
- return (isAnnotationPresent(e, Inject.class)
- && !e.getModifiers().contains(PRIVATE)
- && !e.getModifiers().contains(STATIC))
- ? Optional.of(injectionSiteForInjectField(e, type))
- : Optional.empty();
- }
- };
-
- private ImmutableSortedSet<InjectionSite> getInjectionSites(DeclaredType declaredType) {
- Set<InjectionSite> injectionSites = new HashSet<>();
- List<TypeElement> ancestors = new ArrayList<>();
- SetMultimap<String, ExecutableElement> overriddenMethodMap = LinkedHashMultimap.create();
- for (Optional<DeclaredType> currentType = Optional.of(declaredType);
- currentType.isPresent();
- currentType = types.nonObjectSuperclass(currentType.get())) {
- DeclaredType type = currentType.get();
- ancestors.add(MoreElements.asType(type.asElement()));
- for (Element enclosedElement : type.asElement().getEnclosedElements()) {
- Optional<InjectionSite> maybeInjectionSite =
- injectionSiteVisitor.visit(enclosedElement, type);
- if (maybeInjectionSite.isPresent()) {
- InjectionSite injectionSite = maybeInjectionSite.get();
- if (shouldBeInjected(injectionSite.element(), overriddenMethodMap)) {
- injectionSites.add(injectionSite);
- }
- if (injectionSite.kind().equals(InjectionSite.Kind.METHOD)) {
- ExecutableElement injectionSiteMethod =
- MoreElements.asExecutable(injectionSite.element());
- overriddenMethodMap.put(
- injectionSiteMethod.getSimpleName().toString(), injectionSiteMethod);
- }
- }
- }
- }
- return ImmutableSortedSet.copyOf(
- // supertypes before subtypes
- Comparator.comparing(
- (InjectionSite injectionSite) ->
- ancestors.indexOf(injectionSite.element().getEnclosingElement()))
- .reversed()
- // fields before methods
- .thenComparing(injectionSite -> injectionSite.element().getKind())
- // then sort by whichever element comes first in the parent
- // this isn't necessary, but makes the processor nice and predictable
- .thenComparing(InjectionSite::element, DECLARATION_ORDER),
- injectionSites);
- }
-
- private boolean shouldBeInjected(
- Element injectionSite, SetMultimap<String, ExecutableElement> overriddenMethodMap) {
- if (!isAnnotationPresent(injectionSite, Inject.class)
- || injectionSite.getModifiers().contains(PRIVATE)
- || injectionSite.getModifiers().contains(STATIC)) {
- return false;
- }
-
- if (injectionSite.getKind().isField()) { // Inject all fields (self and ancestors)
- return true;
- }
-
- // For each method with the same name belonging to any descendant class, return false if any
- // method has already overridden the injectionSite method. To decrease the number of methods
- // that are checked, we store the already injected methods in a SetMultimap and only
- // check the methods with the same name.
- ExecutableElement injectionSiteMethod = MoreElements.asExecutable(injectionSite);
- TypeElement injectionSiteType = MoreElements.asType(injectionSite.getEnclosingElement());
- for (ExecutableElement method :
- overriddenMethodMap.get(injectionSiteMethod.getSimpleName().toString())) {
- if (elements.overrides(method, injectionSiteMethod, injectionSiteType)) {
- return false;
- }
- }
- return true;
- }
-
- private InjectionSite injectionSiteForInjectMethod(
- ExecutableElement methodElement, DeclaredType containingType) {
- checkNotNull(methodElement);
- checkArgument(methodElement.getKind().equals(ElementKind.METHOD));
- ExecutableType resolved =
- MoreTypes.asExecutable(types.asMemberOf(containingType, methodElement));
- return new AutoValue_MembersInjectionBinding_InjectionSite(
- InjectionSite.Kind.METHOD,
- methodElement,
- dependencyRequestFactory.forRequiredResolvedVariables(
- methodElement.getParameters(), resolved.getParameterTypes()));
- }
-
- private InjectionSite injectionSiteForInjectField(
- VariableElement fieldElement, DeclaredType containingType) {
- checkNotNull(fieldElement);
- checkArgument(fieldElement.getKind().equals(ElementKind.FIELD));
- checkArgument(isAnnotationPresent(fieldElement, Inject.class));
- TypeMirror resolved = types.asMemberOf(containingType, fieldElement);
- return new AutoValue_MembersInjectionBinding_InjectionSite(
- InjectionSite.Kind.FIELD,
- fieldElement,
- ImmutableSet.of(
- dependencyRequestFactory.forRequiredResolvedVariable(fieldElement, resolved)));
- }
}
diff --git a/java/dagger/internal/codegen/BindingGraph.java b/java/dagger/internal/codegen/BindingGraph.java
index a02cee2..2f548b2 100644
--- a/java/dagger/internal/codegen/BindingGraph.java
+++ b/java/dagger/internal/codegen/BindingGraph.java
@@ -35,8 +35,10 @@
import dagger.model.Key;
import dagger.model.RequestKind;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
@@ -201,19 +203,19 @@
static BindingGraph create(
ComponentDescriptor componentDescriptor,
- ImmutableMap<Key, ResolvedBindings> resolvedContributionBindingsMap,
- ImmutableMap<Key, ResolvedBindings> resolvedMembersInjectionBindings,
- ImmutableList<BindingGraph> subgraphs,
- ImmutableSet<ModuleDescriptor> ownedModules,
+ Map<Key, ResolvedBindings> resolvedContributionBindingsMap,
+ Map<Key, ResolvedBindings> resolvedMembersInjectionBindings,
+ List<BindingGraph> subgraphs,
+ Set<ModuleDescriptor> ownedModules,
Optional<ExecutableElement> factoryMethod,
boolean isFullBindingGraph) {
checkForDuplicates(subgraphs);
return new AutoValue_BindingGraph(
componentDescriptor,
- resolvedContributionBindingsMap,
- resolvedMembersInjectionBindings,
- subgraphs,
- ownedModules,
+ ImmutableMap.copyOf(resolvedContributionBindingsMap),
+ ImmutableMap.copyOf(resolvedMembersInjectionBindings),
+ ImmutableList.copyOf(subgraphs),
+ ImmutableSet.copyOf(ownedModules),
factoryMethod,
isFullBindingGraph);
}
diff --git a/java/dagger/internal/codegen/BindingGraphConverter.java b/java/dagger/internal/codegen/BindingGraphConverter.java
index 28cf9a1..a2cc799 100644
--- a/java/dagger/internal/codegen/BindingGraphConverter.java
+++ b/java/dagger/internal/codegen/BindingGraphConverter.java
@@ -19,10 +19,9 @@
import static com.google.auto.common.MoreTypes.asTypeElement;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
import static dagger.internal.codegen.DaggerGraphs.unreachableNodes;
-import static dagger.internal.codegen.DaggerStreams.presentValues;
-import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.graph.MutableNetwork;
@@ -34,6 +33,7 @@
import dagger.model.BindingGraph.MissingBinding;
import dagger.model.BindingGraph.Node;
import dagger.model.BindingGraphProxies;
+import dagger.model.ComponentPath;
import dagger.model.DependencyRequest;
import javax.inject.Inject;
import javax.lang.model.element.ExecutableElement;
@@ -42,15 +42,11 @@
/** Converts {@link dagger.internal.codegen.BindingGraph}s to {@link dagger.model.BindingGraph}s. */
final class BindingGraphConverter {
-
private final BindingDeclarationFormatter bindingDeclarationFormatter;
- private final CompilerOptions compilerOptions;
@Inject
- BindingGraphConverter(
- BindingDeclarationFormatter bindingDeclarationFormatter, CompilerOptions compilerOptions) {
+ BindingGraphConverter(BindingDeclarationFormatter bindingDeclarationFormatter) {
this.bindingDeclarationFormatter = bindingDeclarationFormatter;
- this.compilerOptions = compilerOptions;
}
/**
@@ -83,15 +79,20 @@
}
private final class Traverser extends ComponentTreeTraverser {
-
private final MutableNetwork<Node, Edge> network =
NetworkBuilder.directed().allowsParallelEdges(true).allowsSelfLoops(true).build();
+ private final boolean isRootSubcomponent;
+ private final boolean isFullBindingGraph;
+ private final ComponentPath rootComponentPath;
private ComponentNode parentComponent;
private ComponentNode currentComponent;
Traverser(BindingGraph graph) {
- super(graph, compilerOptions);
+ super(graph);
+ rootComponentPath = ComponentPath.create(ImmutableList.of(graph.componentTypeElement()));
+ isRootSubcomponent = graph.componentDescriptor().isSubcomponent();
+ isFullBindingGraph = graph.isFullBindingGraph();
}
@Override
@@ -103,7 +104,6 @@
network.addNode(currentComponent);
for (ResolvedBindings resolvedBindings : graph.resolvedBindings()) {
- ImmutableSet<TypeElement> declaringModules = subcomponentDeclaringModules(resolvedBindings);
for (BindingNode binding : bindingNodes(resolvedBindings)) {
addBinding(binding);
if (binding.kind().equals(SUBCOMPONENT_CREATOR)
@@ -111,7 +111,8 @@
network.addEdge(
binding,
subcomponentNode(binding.key().type(), graph),
- new SubcomponentCreatorBindingEdgeImpl(declaringModules));
+ new SubcomponentCreatorBindingEdgeImpl(
+ resolvedBindings.subcomponentDeclarations()));
}
}
}
@@ -219,7 +220,12 @@
}
private MissingBinding missingBindingNode(ResolvedBindings dependencies) {
- return BindingGraphProxies.missingBindingNode(componentPath(), dependencies.key());
+ // TODO(b/117833324): Revisit whether limiting missing binding nodes to the root component is
+ // necessary to limit the amount of missing binding nodes in the network, or if perhaps *all*
+ // missing binding nodes should be structured this way.
+ return BindingGraphProxies.missingBindingNode(
+ isRootSubcomponent && !isFullBindingGraph ? rootComponentPath : componentPath(),
+ dependencies.key());
}
private ComponentNode subcomponentNode(TypeMirror subcomponentBuilderType, BindingGraph graph) {
@@ -229,15 +235,5 @@
return ComponentNodeImpl.create(
componentPath().childPath(subcomponent.typeElement()), subcomponent);
}
-
- private ImmutableSet<TypeElement> subcomponentDeclaringModules(
- ResolvedBindings resolvedBindings) {
- return resolvedBindings
- .subcomponentDeclarations()
- .stream()
- .map(SubcomponentDeclaration::contributingModule)
- .flatMap(presentValues())
- .collect(toImmutableSet());
- }
}
}
diff --git a/java/dagger/internal/codegen/BindingGraphFactory.java b/java/dagger/internal/codegen/BindingGraphFactory.java
index 311f9dd..d96da8a 100644
--- a/java/dagger/internal/codegen/BindingGraphFactory.java
+++ b/java/dagger/internal/codegen/BindingGraphFactory.java
@@ -40,11 +40,11 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import dagger.MembersInjector;
import dagger.Reusable;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.Scope;
@@ -903,17 +903,11 @@
* Returns all of the {@link ResolvedBindings} for {@link ContributionBinding}s from this and
* all ancestor resolvers, indexed by {@link ResolvedBindings#key()}.
*/
- ImmutableMap<Key, ResolvedBindings> getResolvedContributionBindings() {
- ImmutableMap.Builder<Key, ResolvedBindings> builder = ImmutableMap.builder();
- builder.putAll(resolvedContributionBindings);
- if (parentResolver.isPresent()) {
- ImmutableMap<Key, ResolvedBindings> parentBindings =
- parentResolver.get().getResolvedContributionBindings();
- Map<Key, ResolvedBindings> bindingsResolvedInParent =
- Maps.difference(parentBindings, resolvedContributionBindings).entriesOnlyOnLeft();
- builder.putAll(bindingsResolvedInParent);
- }
- return builder.build();
+ Map<Key, ResolvedBindings> getResolvedContributionBindings() {
+ Map<Key, ResolvedBindings> bindings = new LinkedHashMap<>();
+ parentResolver.ifPresent(parent -> bindings.putAll(parent.getResolvedContributionBindings()));
+ bindings.putAll(resolvedContributionBindings);
+ return bindings;
}
/**
diff --git a/java/dagger/internal/codegen/BindingGraphPlugins.java b/java/dagger/internal/codegen/BindingGraphPlugins.java
index ae4ef96..e2c3812 100644
--- a/java/dagger/internal/codegen/BindingGraphPlugins.java
+++ b/java/dagger/internal/codegen/BindingGraphPlugins.java
@@ -21,6 +21,8 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.spi.BindingGraphPlugin;
import java.util.Map;
import java.util.Set;
diff --git a/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java b/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java
new file mode 100644
index 0000000..129647f
--- /dev/null
+++ b/java/dagger/internal/codegen/BindingGraphStatisticsCollector.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.errorprone.util.ASTHelpers.getSymbol;
+import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotation;
+
+import com.google.errorprone.VisitorState;
+import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
+import com.google.errorprone.matchers.Description;
+import com.sun.source.tree.ClassTree;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.util.Context;
+import dagger.BindsInstance;
+import dagger.Component;
+import dagger.model.BindingGraph;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** A {@link BugChecker} that collects statistics derived from a {@link BindingGraph}. */
+public abstract class BindingGraphStatisticsCollector extends BugChecker
+ implements ClassTreeMatcher {
+ private BindingGraphConverter bindingGraphConverter;
+ private BindingGraphFactory bindingGraphFactory;
+ private ComponentDescriptorFactory componentDescriptorFactory;
+ private boolean isInjected;
+
+ @Singleton
+ @Component(modules = JavacPluginModule.class)
+ interface Injector {
+ void inject(BindingGraphStatisticsCollector collector);
+
+ @Component.Factory
+ interface Factory {
+ Injector create(@BindsInstance Context context);
+ }
+ }
+
+ // BugCheckers must have no-arg constructors, so we'll use method injection instead.
+ @Inject
+ void inject(
+ BindingGraphConverter bindingGraphConverter,
+ BindingGraphFactory bindingGraphFactory,
+ ComponentDescriptorFactory componentDescriptorFactory) {
+ this.bindingGraphConverter = bindingGraphConverter;
+ this.bindingGraphFactory = bindingGraphFactory;
+ this.componentDescriptorFactory = componentDescriptorFactory;
+ }
+
+ @Override
+ public final Description matchClass(ClassTree tree, VisitorState state) {
+ injectIfNecessary(state.context);
+
+ ClassSymbol symbol = getSymbol(tree);
+ rootComponentAnnotation(symbol)
+ .map(annotation -> createBindingGraph(symbol))
+ .ifPresent(graph -> visitBindingGraph(graph, state));
+
+ return Description.NO_MATCH;
+ }
+
+ private BindingGraph createBindingGraph(ClassSymbol component) {
+ return bindingGraphConverter.convert(
+ bindingGraphFactory.create(
+ componentDescriptorFactory.rootComponentDescriptor(component), false));
+ }
+
+ /** Visits a {@link BindingGraph} and emits stats to a {@link VisitorState}. */
+ protected abstract void visitBindingGraph(BindingGraph graph, VisitorState state);
+
+ private void injectIfNecessary(Context context) {
+ if (isInjected) {
+ return;
+ }
+ DaggerBindingGraphStatisticsCollector_Injector.factory().create(context).inject(this);
+ isInjected = true;
+ }
+}
diff --git a/java/dagger/internal/codegen/BindingMethodValidator.java b/java/dagger/internal/codegen/BindingMethodValidator.java
index 4b82979..21c05cc 100644
--- a/java/dagger/internal/codegen/BindingMethodValidator.java
+++ b/java/dagger/internal/codegen/BindingMethodValidator.java
@@ -16,43 +16,23 @@
package dagger.internal.codegen;
-import static com.google.common.base.Verify.verifyNotNull;
-import static dagger.internal.codegen.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
-import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
-import static dagger.internal.codegen.MapKeys.getMapKeys;
-import static dagger.internal.codegen.Scopes.scopesOf;
-import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import static java.util.stream.Collectors.joining;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.type.TypeKind.ARRAY;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.TYPEVAR;
-import static javax.lang.model.type.TypeKind.VOID;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.FormatMethod;
-import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper;
-import dagger.MapKey;
-import dagger.Provides;
-import dagger.model.Scope;
-import dagger.multibindings.ElementsIntoSet;
-import dagger.multibindings.IntoMap;
-import dagger.producers.Produces;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.lang.annotation.Annotation;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Map;
-import javax.inject.Qualifier;
-import javax.lang.model.element.AnnotationMirror;
+import java.util.Optional;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
/** A validator for methods that represent binding declarations. */
-abstract class BindingMethodValidator {
+abstract class BindingMethodValidator extends BindingElementValidator<ExecutableElement> {
private final DaggerElements elements;
private final DaggerTypes types;
@@ -61,9 +41,6 @@
private final ImmutableSet<? extends Class<? extends Annotation>> enclosingElementAnnotations;
private final Abstractness abstractness;
private final ExceptionSuperclass exceptionSuperclass;
- private final Map<ExecutableElement, ValidationReport<ExecutableElement>> cache = new HashMap<>();
- private final AllowsMultibindings allowsMultibindings;
- private final AllowsScoping allowsScoping;
/**
* Creates a validator object.
@@ -111,6 +88,7 @@
ExceptionSuperclass exceptionSuperclass,
AllowsMultibindings allowsMultibindings,
AllowsScoping allowsScoping) {
+ super(methodAnnotation, allowsMultibindings, allowsScoping);
this.elements = elements;
this.types = types;
this.methodAnnotation = methodAnnotation;
@@ -118,8 +96,6 @@
this.dependencyRequestValidator = dependencyRequestValidator;
this.abstractness = abstractness;
this.exceptionSuperclass = exceptionSuperclass;
- this.allowsMultibindings = allowsMultibindings;
- this.allowsScoping = allowsScoping;
}
/** The annotation that identifies binding methods validated by this object. */
@@ -134,314 +110,115 @@
*/
@FormatMethod
protected final String bindingMethods(String ruleFormat, Object... args) {
- return new Formatter()
- .format("@%s methods ", methodAnnotation.getSimpleName())
- .format(ruleFormat, args)
- .toString();
+ return bindingElements(ruleFormat, args);
}
- /** Returns a {@link ValidationReport} for {@code method}. */
- final ValidationReport<ExecutableElement> validate(ExecutableElement method) {
- return reentrantComputeIfAbsent(cache, method, this::validateUncached);
+ @Override
+ protected final String bindingElements() {
+ return String.format("@%s methods", methodAnnotation.getSimpleName());
}
- private ValidationReport<ExecutableElement> validateUncached(ExecutableElement m) {
- ValidationReport.Builder<ExecutableElement> report = ValidationReport.about(m);
- checkMethod(report);
- return report.build();
+ @Override
+ protected final String bindingElementTypeVerb() {
+ return "return";
}
- /** Checks the method for validity. Adds errors to {@code builder}. */
- @OverridingMethodsMustInvokeSuper
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- checkEnclosingElement(builder);
- checkTypeParameters(builder);
- checkNotPrivate(builder);
- checkAbstractness(builder);
- checkReturnType(builder);
- checkThrows(builder);
- checkQualifiers(builder);
- checkMapKeys(builder);
- checkMultibindings(builder);
- checkScopes(builder);
- checkParameters(builder);
- }
-
- /**
- * Adds an error if the method is not declared in a class or interface annotated with one of the
- * {@link #enclosingElementAnnotations}.
- */
- private void checkEnclosingElement(ValidationReport.Builder<ExecutableElement> builder) {
- if (!isAnyAnnotationPresent(
- builder.getSubject().getEnclosingElement(), enclosingElementAnnotations)) {
- builder.addError(
- bindingMethods(
- "can only be present within a @%s",
- enclosingElementAnnotations
- .stream()
- .map(Class::getSimpleName)
- .collect(joining(" or @"))));
+ /** Abstract validator for individual binding method elements. */
+ protected abstract class MethodValidator extends ElementValidator {
+ protected MethodValidator(ExecutableElement element) {
+ super(element);
}
- }
- /** Adds an error if the method is generic. */
- private void checkTypeParameters(ValidationReport.Builder<ExecutableElement> builder) {
- if (!builder.getSubject().getTypeParameters().isEmpty()) {
- builder.addError(bindingMethods("may not have type parameters"));
+ @Override
+ protected final Optional<TypeMirror> bindingElementType() {
+ return Optional.of(element.getReturnType());
}
- }
- /** Adds an error if the method is private. */
- private void checkNotPrivate(ValidationReport.Builder<ExecutableElement> builder) {
- if (builder.getSubject().getModifiers().contains(PRIVATE)) {
- builder.addError(bindingMethods("cannot be private"));
+ @Override
+ protected final void checkAdditionalProperties() {
+ checkEnclosingElement();
+ checkTypeParameters();
+ checkNotPrivate();
+ checkAbstractness();
+ checkThrows();
+ checkParameters();
+ checkAdditionalMethodProperties();
}
- }
- /** Adds an error if the method is abstract but must not be, or is not and must be. */
- private void checkAbstractness(ValidationReport.Builder<ExecutableElement> builder) {
- boolean isAbstract = builder.getSubject().getModifiers().contains(ABSTRACT);
- switch (abstractness) {
- case MUST_BE_ABSTRACT:
- if (!isAbstract) {
- builder.addError(bindingMethods("must be abstract"));
- }
- break;
+ /** Checks additional properties of the binding method. */
+ protected void checkAdditionalMethodProperties() {}
- case MUST_BE_CONCRETE:
- if (isAbstract) {
- builder.addError(bindingMethods("cannot be abstract"));
- }
- break;
-
- default:
- throw new AssertionError();
- }
- }
-
- /**
- * Adds an error if the return type is not appropriate for the method.
- *
- * <p>Adds an error if the method doesn't return a primitive, array, declared type, or type
- * variable.
- *
- * <p>If the method is not a multibinding contribution, adds an error if it returns a framework
- * type.
- *
- * <p>If the method is a {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES}
- * contribution, adds an error if the method doesn't return a {@code Set<T>} for some {@code T}
- */
- protected void checkReturnType(ValidationReport.Builder<ExecutableElement> builder) {
- switch (ContributionType.fromBindingMethod(builder.getSubject())) {
- case UNIQUE:
- /* Validate that a unique binding is not attempting to bind a framework type. This
- * validation is only appropriate for unique bindings because multibindings may collect
- * framework types. E.g. Set<Provider<Foo>> is perfectly reasonable. */
- checkFrameworkType(builder);
- // fall through
-
- case SET:
- case MAP:
- checkKeyType(builder, builder.getSubject().getReturnType());
- break;
-
- case SET_VALUES:
- checkSetValuesType(builder);
- break;
-
- default:
- throw new AssertionError();
- }
- }
-
- /**
- * Adds an error if {@code keyType} is not a primitive, declared type, array, or type variable.
- */
- protected void checkKeyType(
- ValidationReport.Builder<ExecutableElement> builder, TypeMirror keyType) {
- TypeKind kind = keyType.getKind();
- if (kind.equals(VOID)) {
- builder.addError(bindingMethods("must return a value (not void)"));
- } else if (!(kind.isPrimitive()
- || kind.equals(DECLARED)
- || kind.equals(ARRAY)
- || kind.equals(TYPEVAR))) {
- builder.addError(badReturnTypeMessage());
- }
- }
-
- /** The error message when a non-{@code void} binding method returns a bad type. */
- protected String badReturnTypeMessage() {
- return bindingMethods("must return a primitive, an array, a type variable, or a declared type");
- }
-
- /**
- * Adds an error if an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method
- * doesn't return a {@code Set<T>} for a reasonable {@code T}.
- */
- // TODO(gak): should we allow "covariant return" for set values?
- protected void checkSetValuesType(ValidationReport.Builder<ExecutableElement> builder) {
- checkSetValuesType(builder, builder.getSubject().getReturnType());
- }
-
- /** Adds an error if {@code type} is not a {@code Set<T>} for a reasonable {@code T}. */
- protected final void checkSetValuesType(
- ValidationReport.Builder<ExecutableElement> builder, TypeMirror type) {
- if (!SetType.isSet(type)) {
- builder.addError(badSetValuesTypeMessage());
- } else {
- SetType setType = SetType.from(type);
- if (setType.isRawType()) {
- builder.addError(bindingMethods("annotated with @ElementsIntoSet cannot return a raw Set"));
- } else {
- checkKeyType(builder, setType.elementType());
+ /**
+ * Adds an error if the method is not declared in a class or interface annotated with one of the
+ * {@link #enclosingElementAnnotations}.
+ */
+ private void checkEnclosingElement() {
+ if (!isAnyAnnotationPresent(
+ element.getEnclosingElement(), enclosingElementAnnotations)) {
+ report.addError(
+ bindingMethods(
+ "can only be present within a @%s",
+ enclosingElementAnnotations.stream()
+ .map(Class::getSimpleName)
+ .collect(joining(" or @"))));
}
}
- }
- /**
- * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
- * subtype of {@link Exception}.
- */
- private void checkThrows(ValidationReport.Builder<ExecutableElement> builder) {
- exceptionSuperclass.checkThrows(this, builder);
- }
-
- /** Adds an error if the method has more than one {@linkplain Qualifier qualifier} annotation. */
- protected void checkQualifiers(ValidationReport.Builder<ExecutableElement> builder) {
- ImmutableSet<? extends AnnotationMirror> qualifiers = getQualifiers(builder.getSubject());
- if (qualifiers.size() > 1) {
- for (AnnotationMirror qualifier : qualifiers) {
- builder.addError(
- bindingMethods("may not use more than one @Qualifier"),
- builder.getSubject(),
- qualifier);
+ /** Adds an error if the method is generic. */
+ private void checkTypeParameters() {
+ if (!element.getTypeParameters().isEmpty()) {
+ report.addError(bindingMethods("may not have type parameters"));
}
}
- }
- /**
- * Adds an error if an {@link IntoMap @IntoMap} or {@code MAP} method doesn't have exactly one
- * {@link MapKey @MapKey} annotation, or if a method that is neither {@link IntoMap @IntoMap} nor
- * {@code MAP} has any.
- */
- protected void checkMapKeys(ValidationReport.Builder<ExecutableElement> builder) {
- if (!allowsMultibindings.allowsMultibindings()) {
- return;
- }
- ImmutableSet<? extends AnnotationMirror> mapKeys = getMapKeys(builder.getSubject());
- if (ContributionType.fromBindingMethod(builder.getSubject()).equals(ContributionType.MAP)) {
- switch (mapKeys.size()) {
- case 0:
- builder.addError(bindingMethods("of type map must declare a map key"));
- break;
- case 1:
- break;
- default:
- builder.addError(bindingMethods("may not have more than one map key"));
- break;
+ /** Adds an error if the method is private. */
+ private void checkNotPrivate() {
+ if (element.getModifiers().contains(PRIVATE)) {
+ report.addError(bindingMethods("cannot be private"));
}
- } else if (!mapKeys.isEmpty()) {
- builder.addError(bindingMethods("of non map type cannot declare a map key"));
}
- }
- /**
- * Adds errors if the method doesn't allow {@linkplain MultibindingAnnotations multibinding
- * annotations} and has any, or if it does allow them but has more than one, or if it has a
- * multibinding annotation and its {@link Provides} or {@link Produces} annotation has a {@code
- * type} parameter.
- */
- protected void checkMultibindings(ValidationReport.Builder<ExecutableElement> builder) {
- ImmutableSet<AnnotationMirror> multibindingAnnotations =
- MultibindingAnnotations.forMethod(builder.getSubject());
-
- switch (allowsMultibindings) {
- case NO_MULTIBINDINGS:
- for (AnnotationMirror annotation : multibindingAnnotations) {
- builder.addError(
- bindingMethods("cannot have multibinding annotations"),
- builder.getSubject(),
- annotation);
- }
- break;
-
- case ALLOWS_MULTIBINDINGS:
- if (multibindingAnnotations.size() > 1) {
- for (AnnotationMirror annotation : multibindingAnnotations) {
- builder.addError(
- bindingMethods("cannot have more than one multibinding annotation"),
- builder.getSubject(),
- annotation);
+ /** Adds an error if the method is abstract but must not be, or is not and must be. */
+ private void checkAbstractness() {
+ boolean isAbstract = element.getModifiers().contains(ABSTRACT);
+ switch (abstractness) {
+ case MUST_BE_ABSTRACT:
+ if (!isAbstract) {
+ report.addError(bindingMethods("must be abstract"));
}
- }
- break;
+ break;
+
+ case MUST_BE_CONCRETE:
+ if (isAbstract) {
+ report.addError(bindingMethods("cannot be abstract"));
+ }
+ }
}
- AnnotationMirror bindingAnnotationMirror =
- getAnnotationMirror(builder.getSubject(), methodAnnotation).get();
- boolean usesProvidesType = false;
- for (ExecutableElement member : bindingAnnotationMirror.getElementValues().keySet()) {
- usesProvidesType |= member.getSimpleName().contentEquals("type");
+ /**
+ * Adds an error if the method declares throws anything but an {@link Error} or an appropriate
+ * subtype of {@link Exception}.
+ */
+ private void checkThrows() {
+ exceptionSuperclass.checkThrows(BindingMethodValidator.this, element, report);
}
- if (usesProvidesType && !multibindingAnnotations.isEmpty()) {
- builder.addError(
- "@Provides.type cannot be used with multibinding annotations", builder.getSubject());
- }
- }
- /** Adds an error if the method has more than one {@linkplain Scope scope} annotation. */
- private void checkScopes(ValidationReport.Builder<ExecutableElement> builder) {
- ImmutableSet<Scope> scopes = scopesOf(builder.getSubject());
- String error = null;
- switch (allowsScoping) {
- case ALLOWS_SCOPING:
- if (scopes.size() <= 1) {
- return;
- }
- error = bindingMethods("cannot use more than one @Scope");
- break;
- case NO_SCOPING:
- error = bindingMethods("cannot be scoped");
- break;
+ /** Adds errors for the method parameters. */
+ protected void checkParameters() {
+ for (VariableElement parameter : element.getParameters()) {
+ checkParameter(parameter);
+ }
}
- verifyNotNull(error);
- for (Scope scope : scopes) {
- builder.addError(error, builder.getSubject(), scope.scopeAnnotation());
+
+ /**
+ * Adds errors for a method parameter. This implementation reports an error if the parameter has
+ * more than one qualifier.
+ */
+ protected void checkParameter(VariableElement parameter) {
+ dependencyRequestValidator.validateDependencyRequest(report, parameter, parameter.asType());
}
}
- /** Adds errors for the method parameters. */
- protected void checkParameters(ValidationReport.Builder<ExecutableElement> builder) {
- for (VariableElement parameter : builder.getSubject().getParameters()) {
- checkParameter(builder, parameter);
- }
- }
-
- /**
- * Adds errors for a method parameter. This implementation reports an error if the parameter has
- * more than one qualifier.
- */
- protected void checkParameter(
- ValidationReport.Builder<ExecutableElement> builder, VariableElement parameter) {
- dependencyRequestValidator.validateDependencyRequest(builder, parameter, parameter.asType());
- }
-
- /** Adds an error if the method returns a {@linkplain FrameworkTypes framework type}. */
- protected void checkFrameworkType(ValidationReport.Builder<ExecutableElement> builder) {
- if (FrameworkTypes.isFrameworkType(builder.getSubject().getReturnType())) {
- builder.addError(bindingMethods("must not return framework types"));
- }
- }
-
- /**
- * The error message when an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method
- * returns a bad type.
- */
- protected String badSetValuesTypeMessage() {
- return bindingMethods("annotated with @ElementsIntoSet must return a Set");
- }
-
/** An abstract/concrete restriction on methods. */
protected enum Abstractness {
MUST_BE_ABSTRACT,
@@ -462,9 +239,11 @@
@Override
protected void checkThrows(
- BindingMethodValidator validator, ValidationReport.Builder<ExecutableElement> builder) {
- if (!builder.getSubject().getThrownTypes().isEmpty()) {
- builder.addError(validator.bindingMethods("may not throw"));
+ BindingMethodValidator validator,
+ ExecutableElement element,
+ ValidationReport.Builder<ExecutableElement> report) {
+ if (!element.getThrownTypes().isEmpty()) {
+ report.addError(validator.bindingMethods("may not throw"));
return;
}
}
@@ -505,13 +284,15 @@
* <p>This method is overridden in {@link #NO_EXCEPTIONS}.
*/
protected void checkThrows(
- BindingMethodValidator validator, ValidationReport.Builder<ExecutableElement> builder) {
+ BindingMethodValidator validator,
+ ExecutableElement element,
+ ValidationReport.Builder<ExecutableElement> report) {
TypeMirror exceptionSupertype = validator.elements.getTypeElement(superclass).asType();
TypeMirror errorType = validator.elements.getTypeElement(Error.class).asType();
- for (TypeMirror thrownType : builder.getSubject().getThrownTypes()) {
+ for (TypeMirror thrownType : element.getThrownTypes()) {
if (!validator.types.isSubtype(thrownType, exceptionSupertype)
&& !validator.types.isSubtype(thrownType, errorType)) {
- builder.addError(errorMessage(validator));
+ report.addError(errorMessage(validator));
break;
}
}
@@ -519,32 +300,4 @@
protected abstract String errorMessage(BindingMethodValidator validator);
}
-
- /** Whether to check multibinding annotations. */
- protected enum AllowsMultibindings {
- /**
- * This method disallows multibinding annotations, so don't bother checking for their validity.
- * {@link MultibindingAnnotationsProcessingStep} will add errors if the method has any
- * multibinding annotations.
- */
- NO_MULTIBINDINGS,
-
- /** This method allows multibinding annotations, so validate them. */
- ALLOWS_MULTIBINDINGS,
- ;
-
- private boolean allowsMultibindings() {
- return this == ALLOWS_MULTIBINDINGS;
- }
- }
-
- /** How to check scoping annotations. */
- protected enum AllowsScoping {
- /** This method disallows scope annotations, so check that none are present. */
- NO_SCOPING,
-
- /** This method allows scoping, so validate that there's at most one. */
- ALLOWS_SCOPING,
- ;
- }
}
diff --git a/java/dagger/internal/codegen/BindingRequest.java b/java/dagger/internal/codegen/BindingRequest.java
index 432e76f..27067aa 100644
--- a/java/dagger/internal/codegen/BindingRequest.java
+++ b/java/dagger/internal/codegen/BindingRequest.java
@@ -19,6 +19,10 @@
import static dagger.internal.codegen.RequestKinds.requestType;
import com.google.auto.value.AutoValue;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.BindingRequestProto;
+import dagger.internal.codegen.serialization.FrameworkTypeWrapper;
+import dagger.internal.codegen.serialization.RequestKindWrapper;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
@@ -105,4 +109,17 @@
}
return frameworkType().get().equals(FrameworkType.PRODUCER_NODE);
}
+
+ /** Creates a proto representation of this binding request. */
+ BindingRequestProto toProto() {
+ BindingRequestProto.Builder builder =
+ BindingRequestProto.newBuilder().setKey(KeyFactory.toProto(key()));
+ if (frameworkType().isPresent()) {
+ builder.setFrameworkType(
+ FrameworkTypeWrapper.FrameworkType.valueOf(frameworkType().get().name()));
+ } else {
+ builder.setRequestKind(RequestKindWrapper.RequestKind.valueOf(requestKind().get().name()));
+ }
+ return builder.build();
+ }
}
diff --git a/java/dagger/internal/codegen/BindsInstanceElementValidator.java b/java/dagger/internal/codegen/BindsInstanceElementValidator.java
new file mode 100644
index 0000000..9249c8e
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceElementValidator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import dagger.BindsInstance;
+import javax.lang.model.element.Element;
+
+abstract class BindsInstanceElementValidator<E extends Element> extends BindingElementValidator<E> {
+ BindsInstanceElementValidator() {
+ super(BindsInstance.class, AllowsMultibindings.NO_MULTIBINDINGS, AllowsScoping.NO_SCOPING);
+ }
+
+ @Override
+ protected final String bindingElements() {
+ // Even though @BindsInstance may be placed on methods, the subject of errors is the
+ // parameter
+ return "@BindsInstance parameters";
+ }
+
+ @Override
+ protected final String bindingElementTypeVerb() {
+ return "be";
+ }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceMethodValidator.java b/java/dagger/internal/codegen/BindsInstanceMethodValidator.java
new file mode 100644
index 0000000..1a491c7
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceMethodValidator.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.ComponentAnnotation.anyComponentAnnotation;
+import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+
+import com.google.auto.common.MoreElements;
+import java.util.List;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+final class BindsInstanceMethodValidator extends BindsInstanceElementValidator<ExecutableElement> {
+ @Inject
+ BindsInstanceMethodValidator() {}
+
+ @Override
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
+ }
+
+ private class Validator extends ElementValidator {
+ Validator(ExecutableElement element) {
+ super(element);
+ }
+
+ @Override
+ protected void checkAdditionalProperties() {
+ if (!element.getModifiers().contains(ABSTRACT)) {
+ report.addError("@BindsInstance methods must be abstract");
+ }
+ if (element.getParameters().size() != 1) {
+ report.addError(
+ "@BindsInstance methods should have exactly one parameter for the bound type");
+ }
+ TypeElement enclosingType = MoreElements.asType(element.getEnclosingElement());
+ moduleAnnotation(enclosingType)
+ .ifPresent(moduleAnnotation -> report.addError(didYouMeanBinds(moduleAnnotation)));
+ anyComponentAnnotation(enclosingType)
+ .ifPresent(
+ componentAnnotation ->
+ report.addError(
+ String.format(
+ "@BindsInstance methods should not be included in @%1$ss. "
+ + "Did you mean to put it in a @%1$s.Builder?",
+ componentAnnotation.simpleName())));
+ }
+
+ @Override
+ protected Optional<TypeMirror> bindingElementType() {
+ List<? extends VariableElement> parameters =
+ MoreElements.asExecutable(element).getParameters();
+ return parameters.size() == 1
+ ? Optional.of(getOnlyElement(parameters).asType())
+ : Optional.empty();
+ }
+ }
+
+ private static String didYouMeanBinds(ModuleAnnotation moduleAnnotation) {
+ return String.format(
+ "@BindsInstance methods should not be included in @%ss. Did you mean @Binds?",
+ moduleAnnotation.annotationClass().getSimpleName());
+ }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceParameterValidator.java b/java/dagger/internal/codegen/BindsInstanceParameterValidator.java
new file mode 100644
index 0000000..b2dc8d8
--- /dev/null
+++ b/java/dagger/internal/codegen/BindsInstanceParameterValidator.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static javax.lang.model.element.ElementKind.METHOD;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.type.TypeKind.DECLARED;
+import static javax.lang.model.type.TypeKind.TYPEVAR;
+
+import com.google.auto.common.MoreElements;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+final class BindsInstanceParameterValidator extends BindsInstanceElementValidator<VariableElement> {
+ @Inject
+ BindsInstanceParameterValidator() {}
+
+ @Override
+ protected ElementValidator elementValidator(VariableElement element) {
+ return new Validator(element);
+ }
+
+ private class Validator extends ElementValidator {
+ Validator(VariableElement element) {
+ super(element);
+ }
+
+ @Override
+ protected void checkAdditionalProperties() {
+ Element enclosing = element.getEnclosingElement();
+ if (!enclosing.getKind().equals(METHOD)) {
+ report.addError(
+ "@BindsInstance should only be applied to methods or parameters of methods");
+ return;
+ }
+
+ ExecutableElement method = MoreElements.asExecutable(enclosing);
+ if (!method.getModifiers().contains(ABSTRACT)) {
+ report.addError("@BindsInstance parameters may only be used in abstract methods");
+ }
+
+ TypeKind returnKind = method.getReturnType().getKind();
+ if (!(returnKind.equals(DECLARED) || returnKind.equals(TYPEVAR))) {
+ report.addError(
+ "@BindsInstance parameters may not be used in methods with a void, array or primitive "
+ + "return type");
+ }
+ }
+
+ @Override
+ protected Optional<TypeMirror> bindingElementType() {
+ return Optional.of(element.asType());
+ }
+ }
+}
diff --git a/java/dagger/internal/codegen/BindsInstanceProcessingStep.java b/java/dagger/internal/codegen/BindsInstanceProcessingStep.java
index 6ee2485..4c222a9 100644
--- a/java/dagger/internal/codegen/BindsInstanceProcessingStep.java
+++ b/java/dagger/internal/codegen/BindsInstanceProcessingStep.java
@@ -16,14 +16,6 @@
package dagger.internal.codegen;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.ComponentAnnotation.anyComponentAnnotation;
-import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
-import static javax.lang.model.element.ElementKind.METHOD;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-import static javax.lang.model.type.TypeKind.DECLARED;
-import static javax.lang.model.type.TypeKind.TYPEVAR;
-
import com.google.auto.common.MoreElements;
import com.google.common.collect.ImmutableSet;
import dagger.BindsInstance;
@@ -32,21 +24,24 @@
import javax.annotation.processing.Messager;
import javax.inject.Inject;
import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
/**
* Processing step that validates that the {@code BindsInstance} annotation is applied to the
* correct elements.
*/
final class BindsInstanceProcessingStep extends TypeCheckingProcessingStep<Element> {
+ private final BindsInstanceMethodValidator methodValidator;
+ private final BindsInstanceParameterValidator parameterValidator;
private final Messager messager;
@Inject
- BindsInstanceProcessingStep(Messager messager) {
+ BindsInstanceProcessingStep(
+ BindsInstanceMethodValidator methodValidator,
+ BindsInstanceParameterValidator parameterValidator,
+ Messager messager) {
super(element -> element);
+ this.methodValidator = methodValidator;
+ this.parameterValidator = parameterValidator;
this.messager = messager;
}
@@ -57,82 +52,15 @@
@Override
protected void process(Element element, ImmutableSet<Class<? extends Annotation>> annotations) {
- ValidationReport.Builder<Element> report = ValidationReport.about(element);
-
switch (element.getKind()) {
- case METHOD:
- ExecutableElement method = MoreElements.asExecutable(element);
- validateBindsInstanceMethod(method, report);
- break;
case PARAMETER:
- VariableElement parameter = MoreElements.asVariable(element);
- validateBindsInstanceParameterType(parameter, report);
- validateBindsInstanceParameterEnclosingMethod(parameter, report);
+ parameterValidator.validate(MoreElements.asVariable(element)).printMessagesTo(messager);
+ break;
+ case METHOD:
+ methodValidator.validate(MoreElements.asExecutable(element)).printMessagesTo(messager);
break;
default:
- // Shouldn't be possible given the target elements @BindsInstance allows.
- throw new AssertionError();
- }
-
- report.build().printMessagesTo(messager);
- }
-
- private void validateBindsInstanceMethod(
- ExecutableElement method, ValidationReport.Builder<Element> report) {
- if (!method.getModifiers().contains(ABSTRACT)) {
- report.addError("@BindsInstance methods must be abstract");
- }
- if (method.getParameters().size() != 1) {
- report.addError(
- "@BindsInstance methods should have exactly one parameter for the bound type");
- } else {
- validateBindsInstanceParameterType(getOnlyElement(method.getParameters()), report);
- }
- TypeElement enclosingType = MoreElements.asType(method.getEnclosingElement());
- moduleAnnotation(enclosingType)
- .ifPresent(moduleAnnotation -> report.addError(didYouMeanBinds(moduleAnnotation)));
- anyComponentAnnotation(enclosingType)
- .ifPresent(
- componentAnnotation ->
- report.addError(
- String.format(
- "@BindsInstance methods should not be included in @%1$ss. "
- + "Did you mean to put it in a @%1$s.Builder?",
- componentAnnotation.simpleName())));
- }
-
- private static String didYouMeanBinds(ModuleAnnotation moduleAnnotation) {
- return String.format(
- "@BindsInstance methods should not be included in @%ss. Did you mean @Binds?",
- moduleAnnotation.annotationClass().getSimpleName());
- }
-
- private void validateBindsInstanceParameterType(
- VariableElement parameter, ValidationReport.Builder<Element> report) {
- if (FrameworkTypes.isFrameworkType(parameter.asType())) {
- report.addError("@BindsInstance parameters may not be framework types", parameter);
- }
- }
-
- private void validateBindsInstanceParameterEnclosingMethod(
- VariableElement parameter, ValidationReport.Builder<Element> report) {
- Element enclosing = parameter.getEnclosingElement();
- if (!enclosing.getKind().equals(METHOD)) {
- report.addError(
- "@BindsInstance should only be applied to methods or parameters of methods");
- return;
- }
-
- ExecutableElement method = MoreElements.asExecutable(enclosing);
- if (!method.getModifiers().contains(ABSTRACT)) {
- report.addError("@BindsInstance parameters may only be used in abstract methods");
- }
-
- TypeKind returnKind = method.getReturnType().getKind();
- if (!(returnKind.equals(DECLARED) || returnKind.equals(TYPEVAR))) {
- report.addError(
- "@BindsInstance parameters may not be used in methods with a void, array or "
- + "primitive return type");
+ throw new AssertionError(element);
}
}
}
diff --git a/java/dagger/internal/codegen/BindsMethodValidator.java b/java/dagger/internal/codegen/BindsMethodValidator.java
index 1e017bc..e198c3a 100644
--- a/java/dagger/internal/codegen/BindsMethodValidator.java
+++ b/java/dagger/internal/codegen/BindsMethodValidator.java
@@ -16,24 +16,24 @@
package dagger.internal.codegen;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsScoping.ALLOWS_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.RUNTIME_EXCEPTION;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
import dagger.Binds;
import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.producers.ProducerModule;
import javax.inject.Inject;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
-/**
- * A validator for {@link Binds} methods.
- */
+/** A validator for {@link Binds} methods. */
final class BindsMethodValidator extends BindingMethodValidator {
private final DaggerTypes types;
private final BindsTypeChecker bindsTypeChecker;
@@ -58,48 +58,50 @@
}
@Override
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- super.checkMethod(builder);
- checkParameters(builder);
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
}
- @Override
- protected void checkParameters(ValidationReport.Builder<ExecutableElement> builder) {
- ExecutableElement method = builder.getSubject();
- if (method.getParameters().size() != 1) {
- builder.addError(
- bindingMethods(
- "must have exactly one parameter, whose type is assignable to the return type"));
- } else {
- super.checkParameters(builder);
- }
- }
-
- @Override
- protected void checkParameter(
- ValidationReport.Builder<ExecutableElement> builder, VariableElement parameter) {
- super.checkParameter(builder, parameter);
- ExecutableElement method = builder.getSubject();
- TypeMirror leftHandSide = boxIfNecessary(method.getReturnType());
- TypeMirror rightHandSide = parameter.asType();
- ContributionType contributionType = ContributionType.fromBindingMethod(method);
- if (contributionType.equals(ContributionType.SET_VALUES) && !SetType.isSet(leftHandSide)) {
- builder.addError(
- "@Binds @ElementsIntoSet methods must return a Set and take a Set parameter");
+ private class Validator extends MethodValidator {
+ Validator(ExecutableElement element) {
+ super(element);
}
- if (!bindsTypeChecker.isAssignable(rightHandSide, leftHandSide, contributionType)) {
- // TODO(ronshapiro): clarify this error message for @ElementsIntoSet cases, where the
- // right-hand-side might not be assignable to the left-hand-side, but still compatible with
- // Set.addAll(Collection<? extends E>)
- builder.addError("@Binds methods' parameter type must be assignable to the return type");
+ @Override
+ protected void checkParameters() {
+ if (element.getParameters().size() != 1) {
+ report.addError(
+ bindingMethods(
+ "must have exactly one parameter, whose type is assignable to the return type"));
+ } else {
+ super.checkParameters();
+ }
}
- }
- private TypeMirror boxIfNecessary(TypeMirror maybePrimitive) {
- if (maybePrimitive.getKind().isPrimitive()) {
- return types.boxedClass(MoreTypes.asPrimitiveType(maybePrimitive)).asType();
+ @Override
+ protected void checkParameter(VariableElement parameter) {
+ super.checkParameter(parameter);
+ TypeMirror leftHandSide = boxIfNecessary(element.getReturnType());
+ TypeMirror rightHandSide = parameter.asType();
+ ContributionType contributionType = ContributionType.fromBindingElement(element);
+ if (contributionType.equals(ContributionType.SET_VALUES) && !SetType.isSet(leftHandSide)) {
+ report.addError(
+ "@Binds @ElementsIntoSet methods must return a Set and take a Set parameter");
+ }
+
+ if (!bindsTypeChecker.isAssignable(rightHandSide, leftHandSide, contributionType)) {
+ // TODO(ronshapiro): clarify this error message for @ElementsIntoSet cases, where the
+ // right-hand-side might not be assignable to the left-hand-side, but still compatible with
+ // Set.addAll(Collection<? extends E>)
+ report.addError("@Binds methods' parameter type must be assignable to the return type");
+ }
}
- return maybePrimitive;
+
+ private TypeMirror boxIfNecessary(TypeMirror maybePrimitive) {
+ if (maybePrimitive.getKind().isPrimitive()) {
+ return types.boxedClass(MoreTypes.asPrimitiveType(maybePrimitive)).asType();
+ }
+ return maybePrimitive;
+ }
}
}
diff --git a/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java b/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java
index e8088d9..e1c9d73 100644
--- a/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java
+++ b/java/dagger/internal/codegen/BindsOptionalOfMethodValidator.java
@@ -16,9 +16,9 @@
package dagger.internal.codegen;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsMultibindings.NO_MULTIBINDINGS;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
import static dagger.internal.codegen.InjectionAnnotations.getQualifiers;
import static dagger.internal.codegen.InjectionAnnotations.injectedConstructors;
@@ -29,6 +29,8 @@
import com.google.common.collect.ImmutableSet;
import dagger.BindsOptionalOf;
import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.producers.ProducerModule;
import javax.inject.Inject;
import javax.lang.model.element.ExecutableElement;
@@ -58,29 +60,33 @@
}
@Override
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- super.checkMethod(builder);
- checkParameters(builder);
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
}
- @Override
- protected void checkKeyType(
- ValidationReport.Builder<ExecutableElement> builder, TypeMirror keyType) {
- super.checkKeyType(builder, keyType);
- if (isValidImplicitProvisionKey(
- getQualifiers(builder.getSubject()).stream().findFirst(), keyType, types)
- && !injectedConstructors(MoreElements.asType(MoreTypes.asDeclared(keyType).asElement()))
- .isEmpty()) {
- builder.addError(
- "@BindsOptionalOf methods cannot return unqualified types that have an @Inject-"
- + "annotated constructor because those are always present");
+ private class Validator extends MethodValidator {
+ Validator(ExecutableElement element) {
+ super(element);
}
- }
- @Override
- protected void checkParameters(ValidationReport.Builder<ExecutableElement> builder) {
- if (!builder.getSubject().getParameters().isEmpty()) {
- builder.addError("@BindsOptionalOf methods cannot have parameters");
+ @Override
+ protected void checkKeyType(TypeMirror keyType) {
+ super.checkKeyType(keyType);
+ if (isValidImplicitProvisionKey(
+ getQualifiers(element).stream().findFirst(), keyType, types)
+ && !injectedConstructors(MoreElements.asType(MoreTypes.asDeclared(keyType).asElement()))
+ .isEmpty()) {
+ report.addError(
+ "@BindsOptionalOf methods cannot return unqualified types that have an @Inject-"
+ + "annotated constructor because those are always present");
+ }
+ }
+
+ @Override
+ protected void checkParameters() {
+ if (!element.getParameters().isEmpty()) {
+ report.addError("@BindsOptionalOf methods cannot have parameters");
+ }
}
}
}
diff --git a/java/dagger/internal/codegen/BindsTypeChecker.java b/java/dagger/internal/codegen/BindsTypeChecker.java
index c00aa1b..acecc9e 100644
--- a/java/dagger/internal/codegen/BindsTypeChecker.java
+++ b/java/dagger/internal/codegen/BindsTypeChecker.java
@@ -21,6 +21,8 @@
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableList;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@@ -68,9 +70,8 @@
DeclaredType parameterizedMapType =
types.getDeclaredType(mapElement(), unboundedWildcard(), leftHandSide);
return methodParameterTypes(parameterizedMapType, "put").get(1);
- default:
- throw new AssertionError("Unknown contribution type: " + contributionType);
}
+ throw new AssertionError("Unknown contribution type: " + contributionType);
}
private ImmutableList<TypeMirror> methodParameterTypes(DeclaredType type, String methodName) {
diff --git a/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java b/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java
index 8a81017..a5e0219 100644
--- a/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java
+++ b/java/dagger/internal/codegen/ChildFactoryMethodEdgeImpl.java
@@ -16,7 +16,7 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.elementToString;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
import dagger.model.BindingGraph.ChildFactoryMethodEdge;
import javax.lang.model.element.ExecutableElement;
diff --git a/java/dagger/internal/codegen/CompilerOptions.java b/java/dagger/internal/codegen/CompilerOptions.java
index 85b276b..bc3cbf8 100644
--- a/java/dagger/internal/codegen/CompilerOptions.java
+++ b/java/dagger/internal/codegen/CompilerOptions.java
@@ -16,39 +16,12 @@
package dagger.internal.codegen;
-import static com.google.common.base.CaseFormat.LOWER_CAMEL;
-import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Sets.immutableEnumSet;
-import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.FeatureStatus.DISABLED;
-import static dagger.internal.codegen.FeatureStatus.ENABLED;
-import static dagger.internal.codegen.ValidationType.ERROR;
-import static dagger.internal.codegen.ValidationType.NONE;
-import static dagger.internal.codegen.ValidationType.WARNING;
-import static java.util.EnumSet.allOf;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Ascii;
-import com.google.common.collect.ImmutableSet;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import com.google.errorprone.annotations.CheckReturnValue;
import com.squareup.javapoet.AnnotationSpec;
import dagger.internal.GenerationOptions;
-import dagger.producers.Produces;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.stream.Stream;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.Processor;
+import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
/** A collection of options that dictate how the compiler will run. */
-@AutoValue
abstract class CompilerOptions {
abstract boolean usesProducers();
@@ -68,7 +41,7 @@
abstract Diagnostic.Kind nullableValidationKind();
- boolean doCheckForNulls() {
+ final boolean doCheckForNulls() {
return nullableValidationKind().equals(Diagnostic.Kind.ERROR);
}
@@ -93,360 +66,54 @@
abstract boolean aheadOfTimeSubcomponents();
+ /**
+ * Enables a testing configuration where all superclass {@link ComponentImplementation}s are
+ * derived from their serialized forms.
+ */
+ abstract boolean forceUseSerializedComponentImplementations();
+
+ /**
+ * If {@code true}, in {@link #aheadOfTimeSubcomponents()} mode, Dagger will emit metadata
+ * annotations to deserialize aspects of the {@link ComponentImplementation}.
+ *
+ * This should only be disabled in compile-testing tests that want to ignore the annotations when
+ * asserting on generated source.
+ */
+ abstract boolean emitModifiableMetadataAnnotations();
+
abstract boolean useGradleIncrementalProcessing();
- abstract ValidationType moduleBindingValidationType();
+ /**
+ * Returns the validation that should be done for the full binding graph for the element.
+ *
+ * @throws IllegalArgumentException if {@code element} is not a module or (sub)component
+ */
+ abstract ValidationType fullBindingGraphValidationType(TypeElement element);
abstract Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind();
abstract ValidationType explicitBindingConflictsWithInjectValidationType();
- static Builder builder() {
- return new AutoValue_CompilerOptions.Builder()
- .headerCompilation(false)
- .useGradleIncrementalProcessing(false);
- }
-
- static CompilerOptions create(ProcessingEnvironment processingEnv) {
- Builder builder = new AutoValue_CompilerOptions.Builder();
- for (Option option : concat(allOf(Feature.class), allOf(Validation.class))) {
- option.set(builder, processingEnv);
- }
- return builder.build();
- }
-
- abstract Builder toBuilder();
-
/**
* Creates a new {@link CompilerOptions} from the serialized {@link GenerationOptions} of a base
* component implementation.
*/
- CompilerOptions withGenerationOptions(GenerationOptions generationOptions) {
- return toBuilder().fastInit(generationOptions.fastInit()).build();
+ final CompilerOptions withGenerationOptions(GenerationOptions generationOptions) {
+ return new ForwardingCompilerOptions(this) {
+ @Override
+ public boolean fastInit() {
+ return generationOptions.fastInit();
+ }
+ };
}
/**
- * Returns an {@link GenerationOptions} annotation that serializes any options for this
- * compilation that should be reused in future compilations.
+ * Returns a {@link GenerationOptions} annotation that serializes any options for this compilation
+ * that should be reused in future compilations.
*/
- AnnotationSpec toGenerationOptionsAnnotation() {
+ final AnnotationSpec toGenerationOptionsAnnotation() {
return AnnotationSpec.builder(GenerationOptions.class)
.addMember("fastInit", "$L", fastInit())
.build();
}
-
- @AutoValue.Builder
- @CanIgnoreReturnValue
- interface Builder {
- Builder usesProducers(boolean usesProduces);
-
- Builder headerCompilation(boolean headerCompilation);
-
- Builder fastInit(boolean fastInit);
-
- Builder formatGeneratedSource(boolean formatGeneratedSource);
-
- Builder writeProducerNameInToken(boolean writeProducerNameInToken);
-
- Builder nullableValidationKind(Diagnostic.Kind kind);
-
- Builder privateMemberValidationKind(Diagnostic.Kind kind);
-
- Builder staticMemberValidationKind(Diagnostic.Kind kind);
-
- Builder ignorePrivateAndStaticInjectionForComponent(
- boolean ignorePrivateAndStaticInjectionForComponent);
-
- Builder scopeCycleValidationType(ValidationType type);
-
- Builder warnIfInjectionFactoryNotGeneratedUpstream(
- boolean warnIfInjectionFactoryNotGeneratedUpstream);
-
- Builder aheadOfTimeSubcomponents(boolean aheadOfTimeSubcomponents);
-
- Builder useGradleIncrementalProcessing(boolean enabled);
-
- Builder moduleBindingValidationType(ValidationType validationType);
-
- Builder moduleHasDifferentScopesDiagnosticKind(Diagnostic.Kind kind);
-
- Builder explicitBindingConflictsWithInjectValidationType(ValidationType validationType);
-
- @CheckReturnValue
- CompilerOptions build();
- }
-
- /** An option that can be set into {@link CompilerOptions}. */
- private interface Option<T extends Enum<T>> {
-
- /** Sets the appropriate property on a {@link CompilerOptions.Builder}. */
- void set(Builder builder, ProcessingEnvironment processingEnvironment);
-
- /**
- * {@code true} if {@link #toString()} represents a {@linkplain Processor#getSupportedOptions()
- * supported command line option}.
- */
- default boolean useCommandLineOption() {
- return true;
- }
-
- /** The default value for this option. */
- T defaultValue();
-
- /** The valid values for this option. */
- Set<T> validValues();
- }
-
- /** A feature that can be enabled or disabled. */
- private enum Feature implements Option<FeatureStatus> {
- HEADER_COMPILATION(Builder::headerCompilation) {
- @Override
- boolean isEnabled(ProcessingEnvironment processingEnvironment) {
- return processingEnvironment.getOptions().containsKey(toString());
- }
-
- @Override
- public String toString() {
- return "experimental_turbine_hjar";
- }
- },
-
- FAST_INIT(Builder::fastInit),
-
- EXPERIMENTAL_ANDROID_MODE((builder, ignoredValue) -> {}) {
- @Override
- public void set(Builder builder, ProcessingEnvironment processingEnvironment) {
- noLongerRecognizedWarning(processingEnvironment);
- }
- },
-
- FORMAT_GENERATED_SOURCE(Builder::formatGeneratedSource, ENABLED),
-
- WRITE_PRODUCER_NAME_IN_TOKEN(Builder::writeProducerNameInToken),
-
- WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM(
- Builder::warnIfInjectionFactoryNotGeneratedUpstream),
-
- IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT(
- Builder::ignorePrivateAndStaticInjectionForComponent),
-
- EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS(Builder::aheadOfTimeSubcomponents),
-
- FLOATING_BINDS_METHODS((builder, ignoredValue) -> {}) {
- @Override
- public void set(Builder builder, ProcessingEnvironment processingEnvironment) {
- noLongerRecognizedWarning(processingEnvironment);
- }
- },
-
- USE_GRADLE_INCREMENTAL_PROCESSING(Builder::useGradleIncrementalProcessing) {
- @Override
- boolean isEnabled(ProcessingEnvironment processingEnvironment) {
- return processingEnvironment.getOptions().containsKey(toString());
- }
-
- @Override
- public String toString() {
- return "dagger.gradle.incremental";
- }
- },
-
- USES_PRODUCERS(Builder::usesProducers) {
- @Override
- boolean isEnabled(ProcessingEnvironment processingEnvironment) {
- return processingEnvironment
- .getElementUtils()
- .getTypeElement(Produces.class.getCanonicalName())
- != null;
- }
-
- @Override
- public boolean useCommandLineOption() {
- return false;
- }
- },
- ;
-
- final OptionParser<FeatureStatus> parser = new OptionParser<>(this);
- final FeatureStatus defaultValue;
- final BiConsumer<Builder, Boolean> setter;
-
- Feature(BiConsumer<Builder, Boolean> setter) {
- this(setter, DISABLED);
- }
-
- Feature(BiConsumer<Builder, Boolean> setter, FeatureStatus defaultValue) {
- this.setter = setter;
- this.defaultValue = defaultValue;
- }
-
- @Override
- public FeatureStatus defaultValue() {
- return defaultValue;
- }
-
- @Override
- public Set<FeatureStatus> validValues() {
- return EnumSet.allOf(FeatureStatus.class);
- }
-
- @Override
- public void set(Builder builder, ProcessingEnvironment processingEnvironment) {
- setter.accept(builder, isEnabled(processingEnvironment));
- }
-
- boolean isEnabled(ProcessingEnvironment processingEnvironment) {
- return parser.parse(processingEnvironment).equals(ENABLED);
- }
-
- @Override
- public String toString() {
- return optionName(name());
- }
-
- void noLongerRecognizedWarning(ProcessingEnvironment processingEnvironment) {
- if (processingEnvironment.getOptions().containsKey(toString())) {
- processingEnvironment
- .getMessager()
- .printMessage(
- Diagnostic.Kind.WARNING,
- toString() + " is no longer a recognized option by Dagger");
- }
- }
-
- }
-
- /** The diagnostic kind or validation type for a kind of validation. */
- private enum Validation implements Option<ValidationType> {
- DISABLE_INTER_COMPONENT_SCOPE_VALIDATION(Builder::scopeCycleValidationType),
-
- NULLABLE_VALIDATION(kindSetter(Builder::nullableValidationKind), ERROR, WARNING) {
- },
-
- PRIVATE_MEMBER_VALIDATION(kindSetter(Builder::privateMemberValidationKind), ERROR, WARNING),
-
- STATIC_MEMBER_VALIDATION(kindSetter(Builder::staticMemberValidationKind), ERROR, WARNING),
-
- /** Whether to validate partial binding graphs associated with modules. */
- MODULE_BINDING_VALIDATION(Builder::moduleBindingValidationType, NONE, ERROR, WARNING),
-
- /**
- * How to report conflicting scoped bindings when validating partial binding graphs associated
- * with modules.
- */
- MODULE_HAS_DIFFERENT_SCOPES_VALIDATION(
- kindSetter(Builder::moduleHasDifferentScopesDiagnosticKind), ERROR, WARNING),
-
- /**
- * How to report that an explicit binding in a subcomponent conflicts with an {@code @Inject}
- * constructor used in an ancestor component.
- */
- EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(
- Builder::explicitBindingConflictsWithInjectValidationType, WARNING, ERROR, NONE),
- ;
-
- final OptionParser<ValidationType> parser = new OptionParser<>(this);
-
- static BiConsumer<Builder, ValidationType> kindSetter(
- BiConsumer<Builder, Diagnostic.Kind> setter) {
- return (builder, validationType) ->
- setter.accept(builder, validationType.diagnosticKind().get());
- }
-
- final ValidationType defaultType;
- final ImmutableSet<ValidationType> validTypes;
- final BiConsumer<Builder, ValidationType> setter;
-
- Validation(BiConsumer<Builder, ValidationType> setter) {
- this(setter, ERROR, WARNING, NONE);
- }
-
- Validation(
- BiConsumer<Builder, ValidationType> setter,
- ValidationType defaultType,
- ValidationType... moreValidTypes) {
- this.setter = setter;
- this.defaultType = defaultType;
- this.validTypes = immutableEnumSet(defaultType, moreValidTypes);
- }
-
- @Override
- public ValidationType defaultValue() {
- return defaultType;
- }
-
- @Override
- public Set<ValidationType> validValues() {
- return validTypes;
- }
-
- @Override
- public void set(Builder builder, ProcessingEnvironment processingEnvironment) {
- setter.accept(builder, parser.parse(processingEnvironment));
- }
-
- @Override
- public String toString() {
- return optionName(name());
- }
- }
-
- private static String optionName(String enumName) {
- return "dagger." + UPPER_UNDERSCORE.to(LOWER_CAMEL, enumName);
- }
-
- static ImmutableSet<String> supportedOptions() {
- return Stream.<Option<?>[]>of(Feature.values(), Validation.values())
- .flatMap(Arrays::stream)
- .filter(Option::useCommandLineOption)
- .map(Option::toString)
- .collect(toImmutableSet());
- }
-
- /** A parser for an {@link Option}. */
- private static class OptionParser<T extends Enum<T>> {
- private final Option<T> option;
-
- OptionParser(Option<T> option) {
- this.option = checkNotNull(option);
- }
-
- /**
- * Returns the value for this option as set on the command line, or the default value if not.
- */
- T parse(ProcessingEnvironment processingEnvironment) {
- String key = option.toString();
- Map<String, String> options = processingEnvironment.getOptions();
- if (options.containsKey(key)) {
- String stringValue = options.get(key);
- if (stringValue == null) {
- processingEnvironment
- .getMessager()
- .printMessage(Diagnostic.Kind.ERROR, "Processor option -A" + key + " needs a value");
- } else {
- try {
- T value = Enum.valueOf(valueClass(), Ascii.toUpperCase(stringValue));
- if (option.validValues().contains(value)) {
- return value;
- }
- } catch (IllegalArgumentException e) {
- // handled below
- }
- processingEnvironment
- .getMessager()
- .printMessage(
- Diagnostic.Kind.ERROR,
- String.format(
- "Processor option -A%s may only have the values %s "
- + "(case insensitive), found: %s",
- key, option.validValues(), stringValue));
- }
- }
- return option.defaultValue();
- }
-
- private Class<T> valueClass() {
- return option.defaultValue().getDeclaringClass();
- }
- }
}
diff --git a/java/dagger/internal/codegen/ComponentAnnotation.java b/java/dagger/internal/codegen/ComponentAnnotation.java
index 41cbabe..a8f2ece 100644
--- a/java/dagger/internal/codegen/ComponentAnnotation.java
+++ b/java/dagger/internal/codegen/ComponentAnnotation.java
@@ -19,10 +19,9 @@
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.MoreTypes.asTypeElements;
import static com.google.auto.common.MoreTypes.isTypeOf;
-import static com.google.common.collect.Sets.union;
-import static dagger.internal.codegen.DaggerElements.getAnyAnnotation;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
@@ -48,6 +47,21 @@
* for modules.
*/
abstract class ComponentAnnotation {
+ /** The root component annotation types. */
+ private static final ImmutableSet<Class<? extends Annotation>> ROOT_COMPONENT_ANNOTATIONS =
+ ImmutableSet.of(Component.class, ProductionComponent.class);
+
+ /** The subcomponent annotation types. */
+ private static final ImmutableSet<Class<? extends Annotation>> SUBCOMPONENT_ANNOTATIONS =
+ ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
+
+ /** All component annotation types. */
+ private static final ImmutableSet<Class<? extends Annotation>> ALL_COMPONENT_ANNOTATIONS =
+ ImmutableSet.<Class<? extends Annotation>>builder()
+ .addAll(ROOT_COMPONENT_ANNOTATIONS)
+ .addAll(SUBCOMPONENT_ANNOTATIONS)
+ .build();
+
/** The annotation itself. */
abstract AnnotationMirror annotation();
@@ -117,7 +131,7 @@
* one is present on {@code typeElement}.
*/
static Optional<ComponentAnnotation> rootComponentAnnotation(TypeElement typeElement) {
- return anyComponentAnnotation(typeElement, rootComponentAnnotations());
+ return anyComponentAnnotation(typeElement, ROOT_COMPONENT_ANNOTATIONS);
}
/**
@@ -125,7 +139,7 @@
* typeElement}.
*/
static Optional<ComponentAnnotation> subcomponentAnnotation(TypeElement typeElement) {
- return anyComponentAnnotation(typeElement, subcomponentAnnotations());
+ return anyComponentAnnotation(typeElement, SUBCOMPONENT_ANNOTATIONS);
}
/**
@@ -133,7 +147,7 @@
* on {@code typeElement}.
*/
static Optional<ComponentAnnotation> anyComponentAnnotation(TypeElement typeElement) {
- return anyComponentAnnotation(typeElement, allComponentAnnotations());
+ return anyComponentAnnotation(typeElement, ALL_COMPONENT_ANNOTATIONS);
}
private static Optional<ComponentAnnotation> anyComponentAnnotation(
@@ -143,7 +157,7 @@
/** Returns {@code true} if the argument is a component annotation. */
static boolean isComponentAnnotation(AnnotationMirror annotation) {
- return allComponentAnnotations().stream()
+ return ALL_COMPONENT_ANNOTATIONS.stream()
.anyMatch(annotationClass -> isTypeOf(annotationClass, annotation.getAnnotationType()));
}
@@ -177,17 +191,17 @@
/** The root component annotation types. */
static ImmutableSet<Class<? extends Annotation>> rootComponentAnnotations() {
- return ImmutableSet.of(Component.class, ProductionComponent.class);
+ return ROOT_COMPONENT_ANNOTATIONS;
}
/** The subcomponent annotation types. */
static ImmutableSet<Class<? extends Annotation>> subcomponentAnnotations() {
- return ImmutableSet.of(Subcomponent.class, ProductionSubcomponent.class);
+ return SUBCOMPONENT_ANNOTATIONS;
}
/** All component annotation types. */
static ImmutableSet<Class<? extends Annotation>> allComponentAnnotations() {
- return union(rootComponentAnnotations(), subcomponentAnnotations()).immutableCopy();
+ return ALL_COMPONENT_ANNOTATIONS;
}
/**
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index dd86b92..37cf1e8 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -19,17 +19,17 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Verify.verify;
-import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.Accessibility.isRawTypePubliclyAccessible;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
import static dagger.internal.codegen.BindingType.MEMBERS_INJECTION;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
import static dagger.internal.codegen.DelegateBindingExpression.isBindsScopeStrongerThanDependencyScope;
import static dagger.internal.codegen.MemberSelect.staticFactoryCreation;
import static dagger.internal.codegen.RequestKinds.isDerivedFromProvider;
-import static dagger.internal.codegen.TypeNames.DOUBLE_CHECK;
-import static dagger.internal.codegen.TypeNames.SINGLE_CHECK;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
+import static dagger.internal.codegen.javapoet.TypeNames.SINGLE_CHECK;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static dagger.model.BindingKind.DELEGATE;
import static dagger.model.BindingKind.MULTIBOUND_MAP;
import static dagger.model.BindingKind.MULTIBOUND_SET;
@@ -43,6 +43,9 @@
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
import dagger.internal.codegen.MethodBindingExpression.MethodImplementationStrategy;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.RequestKind;
import java.util.HashMap;
@@ -50,6 +53,7 @@
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Provider;
+import javax.lang.model.SourceVersion;
import javax.lang.model.type.TypeMirror;
/** A central repository of code expressions used to access any binding available to a component. */
@@ -66,6 +70,7 @@
private final OptionalFactories optionalFactories;
private final DaggerTypes types;
private final DaggerElements elements;
+ private final SourceVersion sourceVersion;
private final CompilerOptions compilerOptions;
private final MembersInjectionMethods membersInjectionMethods;
private final InnerSwitchingProviders innerSwitchingProviders;
@@ -81,6 +86,7 @@
OptionalFactories optionalFactories,
DaggerTypes types,
DaggerElements elements,
+ SourceVersion sourceVersion,
@GenerationCompilerOptions CompilerOptions compilerOptions) {
this.parent = parent;
this.graph = graph;
@@ -89,6 +95,7 @@
this.optionalFactories = checkNotNull(optionalFactories);
this.types = checkNotNull(types);
this.elements = checkNotNull(elements);
+ this.sourceVersion = checkNotNull(sourceVersion);
this.compilerOptions = checkNotNull(compilerOptions);
this.membersInjectionMethods =
new MembersInjectionMethods(componentImplementation, this, graph, elements, types);
@@ -273,10 +280,8 @@
case PRODUCTION:
return productionBindingExpression(resolvedBindings, request);
-
- default:
- throw new AssertionError(resolvedBindings);
}
+ throw new AssertionError(resolvedBindings);
}
/**
@@ -425,7 +430,7 @@
return producerFromProviderBindingExpression(resolvedBindings);
case FUTURE:
- return new ImmediateFutureBindingExpression(resolvedBindings, this, types);
+ return new ImmediateFutureBindingExpression(resolvedBindings, this, types, sourceVersion);
case MEMBERS_INJECTION:
throw new IllegalArgumentException();
@@ -568,7 +573,8 @@
resolvedBindings, componentImplementation, graph, this, types, elements));
case OPTIONAL:
- return Optional.of(new OptionalBindingExpression(resolvedBindings, this, types));
+ return Optional.of(
+ new OptionalBindingExpression(resolvedBindings, this, types, sourceVersion));
case BOUND_INSTANCE:
return Optional.of(
@@ -587,7 +593,8 @@
membersInjectionMethods,
componentRequirementExpressions,
types,
- elements));
+ elements,
+ sourceVersion));
case MEMBERS_INJECTOR:
return Optional.empty();
diff --git a/java/dagger/internal/codegen/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/ComponentCreatorDescriptor.java
index ae33514..f6ec7a2 100644
--- a/java/dagger/internal/codegen/ComponentCreatorDescriptor.java
+++ b/java/dagger/internal/codegen/ComponentCreatorDescriptor.java
@@ -33,6 +33,8 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import dagger.BindsInstance;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import java.util.List;
import javax.lang.model.element.Element;
diff --git a/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java b/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java
index 0778403..4f06b90 100644
--- a/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java
+++ b/java/dagger/internal/codegen/ComponentCreatorImplementationFactory.java
@@ -23,9 +23,9 @@
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.SourceFiles.simpleVariableName;
-import static dagger.internal.codegen.TypeSpecs.addSupertype;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
@@ -46,6 +46,9 @@
import com.squareup.javapoet.TypeSpec;
import dagger.internal.Preconditions;
import dagger.internal.codegen.ComponentRequirement.NullPolicy;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
@@ -68,7 +71,7 @@
/** Returns a new creator implementation for the given component, if necessary. */
Optional<ComponentCreatorImplementation> create(
- ComponentImplementation componentImplementation, BindingGraph graph) {
+ ComponentImplementation componentImplementation, Optional<BindingGraph> graph) {
if (!componentImplementation.componentDescriptor().hasCreator()) {
return Optional.empty();
}
@@ -167,15 +170,15 @@
}
private void setModifiers() {
- classBuilder.addModifiers(visibility());
+ visibility().ifPresent(classBuilder::addModifiers);
if (!componentImplementation.isNested()) {
classBuilder.addModifiers(STATIC);
}
classBuilder.addModifiers(componentImplementation.isAbstract() ? ABSTRACT : FINAL);
}
- /** Returns the visibility modifier the generated class should have. */
- protected abstract Modifier visibility();
+ /** Returns the visibility modifier the generated class should have, if any. */
+ protected abstract Optional<Modifier> visibility();
/** Sets the superclass being extended or interface being implemented for this creator. */
protected abstract void setSupertype();
@@ -253,7 +256,7 @@
.addAnnotation(Deprecated.class)
.addJavadoc(
"@deprecated This module is declared, but an instance is not used in the component. "
- + "This method is a no-op. For more, see https://google.github.io/dagger/unused-modules.\n")
+ + "This method is a no-op. For more, see https://dagger.dev/unused-modules.\n")
.addStatement("$T.checkNotNull($N)", Preconditions.class, parameter);
return maybeReturnThis(method);
}
@@ -378,12 +381,12 @@
/** Builder for a creator type defined by a {@code ComponentCreatorDescriptor}. */
private final class BuilderForCreatorDescriptor extends Builder {
final ComponentCreatorDescriptor creatorDescriptor;
- private final BindingGraph graph;
+ private final Optional<BindingGraph> graph;
BuilderForCreatorDescriptor(
ComponentImplementation componentImplementation,
ComponentCreatorDescriptor creatorDescriptor,
- BindingGraph graph) {
+ Optional<BindingGraph> graph) {
super(componentImplementation);
this.creatorDescriptor = creatorDescriptor;
this.graph = graph;
@@ -395,22 +398,21 @@
}
@Override
- protected Modifier visibility() {
+ protected Optional<Modifier> visibility() {
if (componentImplementation.isAbstract()) {
// The component creator class of a top-level component implementation in ahead-of-time
// subcomponents mode must be public, not protected, because the creator's subclass will
// be a sibling of the component subclass implementation, not nested.
- return componentImplementation.isNested() ? PROTECTED : PUBLIC;
+ return Optional.of(componentImplementation.isNested() ? PROTECTED : PUBLIC);
}
- return PRIVATE;
+ return Optional.of(PRIVATE);
}
@Override
protected void setSupertype() {
if (componentImplementation.baseCreatorImplementation().isPresent()) {
// If an abstract base implementation for this creator exists, extend that class.
- classBuilder.superclass(
- componentImplementation.baseCreatorImplementation().get().name());
+ classBuilder.superclass(componentImplementation.baseCreatorImplementation().get().name());
} else {
addSupertype(classBuilder, creatorDescriptor.typeElement());
}
@@ -476,7 +478,7 @@
* Returns whether the given {@code requirement} is for a module type owned by the component.
*/
private boolean isOwnedModule(ComponentRequirement requirement) {
- return graph.ownedModuleTypes().contains(requirement.typeElement());
+ return graph.map(g -> g.ownedModuleTypes().contains(requirement.typeElement())).orElse(true);
}
private boolean hasBaseCreatorImplementation() {
@@ -516,8 +518,12 @@
}
@Override
- protected Modifier visibility() {
- return PUBLIC;
+ protected Optional<Modifier> visibility() {
+ return componentImplementation
+ .componentDescriptor()
+ .typeElement()
+ .getModifiers()
+ .contains(PUBLIC) ? Optional.of(PUBLIC) : Optional.empty();
}
@Override
diff --git a/java/dagger/internal/codegen/ComponentCreatorValidator.java b/java/dagger/internal/codegen/ComponentCreatorValidator.java
index 4a80f94..c55dadd 100644
--- a/java/dagger/internal/codegen/ComponentCreatorValidator.java
+++ b/java/dagger/internal/codegen/ComponentCreatorValidator.java
@@ -30,6 +30,8 @@
import com.google.common.collect.ObjectArrays;
import dagger.BindsInstance;
import dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
@@ -59,329 +61,330 @@
ValidationReport.Builder<TypeElement> report = ValidationReport.about(type);
ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations = getCreatorAnnotations(type);
- if (creatorAnnotations.size() > 1) {
- String error =
- "May not have more than one component Builder or Factory annotation on a type: found "
- + creatorAnnotations;
- report.addError(error);
+ if (!validateOnlyOneCreatorAnnotation(creatorAnnotations, report)) {
return report.build();
}
- // creatorAnnotations should never be empty because the validate method should only ever be
- // called for types that have been found to have some creator annotation
- ComponentCreatorAnnotation creatorAnnotation = getOnlyElement(creatorAnnotations);
- ComponentCreatorMessages messages = ErrorMessages.creatorMessagesFor(creatorAnnotation);
-
- Element componentElement = type.getEnclosingElement();
- if (!isAnnotationPresent(componentElement, creatorAnnotation.componentAnnotation())) {
- report.addError(messages.mustBeInComponent());
- }
-
- // If the type isn't a class or interface, don't validate anything else since the rest of the
- // messages will be bogus.
- if (validateIsClassOrInterface(type, report, messages)) {
- validateTypeRequirements(type, report, messages);
- switch (creatorAnnotation.creatorKind()) {
- case FACTORY:
- validateFactory(type, report, componentElement, messages);
- break;
- case BUILDER:
- validateBuilder(type, report, componentElement, messages);
- }
- }
-
// Note: there's more validation in ComponentDescriptorValidator:
// - to make sure the setter methods/factory parameters mirror the deps
// - to make sure each type or key is set by only one method or parameter
-
- return report.build();
+ ElementValidator validator =
+ new ElementValidator(type, report, getOnlyElement(creatorAnnotations));
+ return validator.validate();
}
- /** Validates that the type is a class or interface type and returns true if it is. */
- private boolean validateIsClassOrInterface(
- TypeElement type,
- ValidationReport.Builder<TypeElement> report,
- ComponentCreatorMessages messages) {
- switch (type.getKind()) {
- case CLASS:
- validateConstructor(type, report, messages);
- return true;
- case INTERFACE:
- return true;
- default:
- report.addError(messages.mustBeClassOrInterface());
+ private boolean validateOnlyOneCreatorAnnotation(
+ ImmutableSet<ComponentCreatorAnnotation> creatorAnnotations,
+ ValidationReport.Builder<?> report) {
+ // creatorAnnotations should never be empty because this should only ever be called for
+ // types that have been found to have some creator annotation
+ if (creatorAnnotations.size() > 1) {
+ String error =
+ "May not have more than one component Factory or Builder annotation on a type"
+ + ": found "
+ + creatorAnnotations;
+ report.addError(error);
+ return false;
}
- return false;
+
+ return true;
}
- private void validateConstructor(
- TypeElement type,
- ValidationReport.Builder<TypeElement> report,
- ComponentCreatorMessages messages) {
- List<? extends Element> allElements = type.getEnclosedElements();
- List<ExecutableElement> constructors = ElementFilter.constructorsIn(allElements);
+ /**
+ * Validator for a single {@link TypeElement} that is annotated with a {@code Builder} or {@code
+ * Factory} annotation.
+ */
+ private final class ElementValidator {
+ private final TypeElement type;
+ private final Element component;
+ private final ValidationReport.Builder<TypeElement> report;
+ private final ComponentCreatorAnnotation annotation;
+ private final ComponentCreatorMessages messages;
- boolean valid = true;
- if (constructors.size() != 1) {
- valid = false;
- } else {
- ExecutableElement constructor = getOnlyElement(constructors);
- valid = constructor.getParameters().isEmpty()
- && !constructor.getModifiers().contains(PRIVATE);
+ private ElementValidator(
+ TypeElement type,
+ ValidationReport.Builder<TypeElement> report,
+ ComponentCreatorAnnotation annotation) {
+ this.type = type;
+ this.component = type.getEnclosingElement();
+ this.report = report;
+ this.annotation = annotation;
+ this.messages = ErrorMessages.creatorMessagesFor(annotation);
}
- if (!valid) {
- report.addError(messages.invalidConstructor());
- }
- }
+ /** Validates the creator type. */
+ final ValidationReport<TypeElement> validate() {
+ if (!isAnnotationPresent(component, annotation.componentAnnotation())) {
+ report.addError(messages.mustBeInComponent());
+ }
- /** Validates basic requirements about the type that are common to both creator kinds. */
- private void validateTypeRequirements(
- TypeElement type,
- ValidationReport.Builder<TypeElement> report,
- ComponentCreatorMessages messages) {
- if (!type.getTypeParameters().isEmpty()) {
- report.addError(messages.generics());
- }
+ // If the type isn't a class or interface, don't validate anything else since the rest of the
+ // messages will be bogus.
+ if (!validateIsClassOrInterface()) {
+ return report.build();
+ }
- Set<Modifier> modifiers = type.getModifiers();
- if (modifiers.contains(PRIVATE)) {
- report.addError(messages.isPrivate());
- }
- if (!modifiers.contains(STATIC)) {
- report.addError(messages.mustBeStatic());
- }
- // Note: Must be abstract, so no need to check for final.
- if (!modifiers.contains(ABSTRACT)) {
- report.addError(messages.mustBeAbstract());
- }
- }
-
- private void validateBuilder(
- TypeElement type,
- ValidationReport.Builder<TypeElement> report,
- Element componentElement,
- ComponentCreatorMessages messages) {
- ExecutableElement buildMethod = null;
- for (ExecutableElement method : elements.getUnimplementedMethods(type)) {
- TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
- switch (method.getParameters().size()) {
- case 0: // If this is potentially a build() method, validate it returns the correct type.
- if (validateFactoryMethodReturnType(
- report, type, componentElement, messages, method)) {
- if (buildMethod != null) {
- // If we found more than one build-like method, fail.
- error(
- report,
- method,
- messages.twoFactoryMethods(),
- messages.inheritedTwoFactoryMethods(),
- buildMethod);
- }
- }
- // We set the buildMethod regardless of the return type to reduce error spam.
- buildMethod = method;
+ validateTypeRequirements();
+ switch (annotation.creatorKind()) {
+ case FACTORY:
+ validateFactory();
break;
+ case BUILDER:
+ validateBuilder();
+ }
- case 1: // If this correctly had one parameter, make sure the return types are valid.
- validateSetterMethod(type, method, returnType, report, messages);
- break;
+ return report.build();
+ }
- default: // more than one parameter
- error(
- report,
- method,
- messages.setterMethodsMustTakeOneArg(),
- messages.inheritedSetterMethodsMustTakeOneArg());
- break;
+ /** Validates that the type is a class or interface type and returns true if it is. */
+ private boolean validateIsClassOrInterface() {
+ switch (type.getKind()) {
+ case CLASS:
+ validateConstructor();
+ return true;
+ case INTERFACE:
+ return true;
+ default:
+ report.addError(messages.mustBeClassOrInterface());
+ }
+ return false;
+ }
+
+ private void validateConstructor() {
+ List<? extends Element> allElements = type.getEnclosedElements();
+ List<ExecutableElement> constructors = ElementFilter.constructorsIn(allElements);
+
+ boolean valid = true;
+ if (constructors.size() != 1) {
+ valid = false;
+ } else {
+ ExecutableElement constructor = getOnlyElement(constructors);
+ valid =
+ constructor.getParameters().isEmpty() && !constructor.getModifiers().contains(PRIVATE);
+ }
+
+ if (!valid) {
+ report.addError(messages.invalidConstructor());
}
}
- if (buildMethod == null) {
- report.addError(messages.missingFactoryMethod());
- } else {
- validateNotGeneric(buildMethod, report, messages);
- }
- }
+ /** Validates basic requirements about the type that are common to both creator kinds. */
+ private void validateTypeRequirements() {
+ if (!type.getTypeParameters().isEmpty()) {
+ report.addError(messages.generics());
+ }
- private void validateSetterMethod(
- TypeElement type,
- ExecutableElement method,
- TypeMirror returnType,
- ValidationReport.Builder<TypeElement> report,
- ComponentCreatorMessages messages) {
- if (returnType.getKind() != TypeKind.VOID && !types.isSubtype(type.asType(), returnType)) {
- error(
- report,
- method,
- messages.setterMethodsMustReturnVoidOrBuilder(),
- messages.inheritedSetterMethodsMustReturnVoidOrBuilder());
+ Set<Modifier> modifiers = type.getModifiers();
+ if (modifiers.contains(PRIVATE)) {
+ report.addError(messages.isPrivate());
+ }
+ if (!modifiers.contains(STATIC)) {
+ report.addError(messages.mustBeStatic());
+ }
+ // Note: Must be abstract, so no need to check for final.
+ if (!modifiers.contains(ABSTRACT)) {
+ report.addError(messages.mustBeAbstract());
+ }
}
- validateNotGeneric(method, report, messages);
+ private void validateBuilder() {
+ ExecutableElement buildMethod = null;
+ for (ExecutableElement method : elements.getUnimplementedMethods(type)) {
+ switch (method.getParameters().size()) {
+ case 0: // If this is potentially a build() method, validate it returns the correct type.
+ if (validateFactoryMethodReturnType(method)) {
+ if (buildMethod != null) {
+ // If we found more than one build-like method, fail.
+ error(
+ method,
+ messages.twoFactoryMethods(),
+ messages.inheritedTwoFactoryMethods(),
+ buildMethod);
+ }
+ }
+ // We set the buildMethod regardless of the return type to reduce error spam.
+ buildMethod = method;
+ break;
- VariableElement parameter = method.getParameters().get(0);
+ case 1: // If this correctly had one parameter, make sure the return types are valid.
+ validateSetterMethod(method);
+ break;
- boolean methodIsBindsInstance = isAnnotationPresent(method, BindsInstance.class);
- boolean parameterIsBindsInstance = isAnnotationPresent(parameter, BindsInstance.class);
- boolean bindsInstance = methodIsBindsInstance || parameterIsBindsInstance;
+ default: // more than one parameter
+ error(
+ method,
+ messages.setterMethodsMustTakeOneArg(),
+ messages.inheritedSetterMethodsMustTakeOneArg());
+ break;
+ }
+ }
- if (methodIsBindsInstance && parameterIsBindsInstance) {
- error(
- report,
- method,
- messages.bindsInstanceNotAllowedOnBothSetterMethodAndParameter(),
- messages.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter());
- }
-
- if (!bindsInstance && parameter.asType().getKind().isPrimitive()) {
- error(
- report,
- method,
- messages.nonBindsInstanceParametersMayNotBePrimitives(),
- messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
- }
- }
-
- private void validateFactory(
- TypeElement type,
- ValidationReport.Builder<TypeElement> report,
- Element componentElement,
- ComponentCreatorMessages messages) {
- ImmutableList<ExecutableElement> abstractMethods =
- elements.getUnimplementedMethods(type).asList();
- switch (abstractMethods.size()) {
- case 0:
+ if (buildMethod == null) {
report.addError(messages.missingFactoryMethod());
- return;
- case 1:
- break; // good
- default:
- error(
- report,
- abstractMethods.get(1),
- messages.twoFactoryMethods(),
- messages.inheritedTwoFactoryMethods(),
- abstractMethods.get(0));
- return;
+ } else {
+ validateNotGeneric(buildMethod);
+ }
}
- ExecutableElement method = getOnlyElement(abstractMethods);
- validateNotGeneric(method, report, messages);
-
- if (!validateFactoryMethodReturnType(report, type, componentElement, messages, method)) {
- // If we can't determine that the single method is a valid factory method, don't bother
- // validating its parameters.
- return;
- }
-
- for (VariableElement parameter : method.getParameters()) {
- if (!isAnnotationPresent(parameter, BindsInstance.class)
- && parameter.asType().getKind().isPrimitive()) {
+ private void validateSetterMethod(ExecutableElement method) {
+ TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
+ if (returnType.getKind() != TypeKind.VOID && !types.isSubtype(type.asType(), returnType)) {
error(
- report,
+ method,
+ messages.setterMethodsMustReturnVoidOrBuilder(),
+ messages.inheritedSetterMethodsMustReturnVoidOrBuilder());
+ }
+
+ validateNotGeneric(method);
+
+ VariableElement parameter = method.getParameters().get(0);
+
+ boolean methodIsBindsInstance = isAnnotationPresent(method, BindsInstance.class);
+ boolean parameterIsBindsInstance = isAnnotationPresent(parameter, BindsInstance.class);
+ boolean bindsInstance = methodIsBindsInstance || parameterIsBindsInstance;
+
+ if (methodIsBindsInstance && parameterIsBindsInstance) {
+ error(
+ method,
+ messages.bindsInstanceNotAllowedOnBothSetterMethodAndParameter(),
+ messages.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter());
+ }
+
+ if (!bindsInstance && parameter.asType().getKind().isPrimitive()) {
+ error(
method,
messages.nonBindsInstanceParametersMayNotBePrimitives(),
messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
}
}
- }
- /**
- * Validates that the factory method that actually returns a new component instance. Returns true
- * if the return type was valid.
- */
- private boolean validateFactoryMethodReturnType(
- ValidationReport.Builder<TypeElement> report,
- TypeElement type,
- Element componentElement,
- ComponentCreatorMessages messages,
- ExecutableElement method) {
- TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
+ private void validateFactory() {
+ ImmutableList<ExecutableElement> abstractMethods =
+ elements.getUnimplementedMethods(type).asList();
+ switch (abstractMethods.size()) {
+ case 0:
+ report.addError(messages.missingFactoryMethod());
+ return;
+ case 1:
+ break; // good
+ default:
+ error(
+ abstractMethods.get(1),
+ messages.twoFactoryMethods(),
+ messages.inheritedTwoFactoryMethods(),
+ abstractMethods.get(0));
+ return;
+ }
- if (!types.isSubtype(componentElement.asType(), returnType)) {
- error(
- report,
- method,
- messages.factoryMethodMustReturnComponentType(),
- messages.inheritedFactoryMethodMustReturnComponentType());
- return false;
+ validateFactoryMethod(getOnlyElement(abstractMethods));
}
- if (isAnnotationPresent(method, BindsInstance.class)) {
- error(
- report,
- method,
- messages.factoryMethodMayNotBeAnnotatedWithBindsInstance(),
- messages.inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance());
- return false;
- }
+ /** Validates that the given {@code method} is a valid component factory method. */
+ private void validateFactoryMethod(ExecutableElement method) {
+ validateNotGeneric(method);
- TypeElement componentType = MoreElements.asType(componentElement);
- if (!types.isSameType(componentType.asType(), returnType)) {
- ImmutableSet<ExecutableElement> methodsOnlyInComponent =
- methodsOnlyInComponent(componentType);
- if (!methodsOnlyInComponent.isEmpty()) {
- report.addWarning(
- messages.factoryMethodReturnsSupertypeWithMissingMethods(
- componentType, report.getSubject(), returnType, method, methodsOnlyInComponent),
- method);
+ if (!validateFactoryMethodReturnType(method)) {
+ // If we can't determine that the single method is a valid factory method, don't bother
+ // validating its parameters.
+ return;
+ }
+
+ for (VariableElement parameter : method.getParameters()) {
+ if (!isAnnotationPresent(parameter, BindsInstance.class)
+ && parameter.asType().getKind().isPrimitive()) {
+ error(
+ method,
+ messages.nonBindsInstanceParametersMayNotBePrimitives(),
+ messages.inheritedNonBindsInstanceParametersMayNotBePrimitives());
+ }
}
}
- return true;
- }
- /**
- * Generates one of two error messages. If the method is enclosed in the subject, we target the
- * error to the method itself. Otherwise we target the error to the subject and list the method as
- * an argument. (Otherwise we have no way of knowing if the method is being compiled in this pass
- * too, so javac might not be able to pinpoint it's line of code.)
- */
- /*
- * For Component.Builder, the prototypical example would be if someone had:
- * libfoo: interface SharedBuilder { void badSetter(A a, B b); }
- * libbar: BarComponent { BarBuilder extends SharedBuilder } }
- * ... the compiler only validates BarBuilder when compiling libbar, but it fails because
- * of libfoo's SharedBuilder (which could have been compiled in a previous pass).
- * So we can't point to SharedBuilder#badSetter as the subject of the BarBuilder validation
- * failure.
- *
- * This check is a little more strict than necessary -- ideally we'd check if method's enclosing
- * class was included in this compile run. But that's hard, and this is close enough.
- */
- private static void error(
- ValidationReport.Builder<TypeElement> report,
- ExecutableElement method,
- String enclosedError,
- String inheritedError,
- Object... extraArgs) {
- if (method.getEnclosingElement().equals(report.getSubject())) {
- report.addError(String.format(enclosedError, extraArgs), method);
- } else {
- report.addError(String.format(inheritedError, ObjectArrays.concat(extraArgs, method)));
+ /**
+ * Validates that the factory method that actually returns a new component instance. Returns
+ * true if the return type was valid.
+ */
+ private boolean validateFactoryMethodReturnType(ExecutableElement method) {
+ TypeMirror returnType = types.resolveExecutableType(method, type.asType()).getReturnType();
+
+ if (!types.isSubtype(component.asType(), returnType)) {
+ error(
+ method,
+ messages.factoryMethodMustReturnComponentType(),
+ messages.inheritedFactoryMethodMustReturnComponentType());
+ return false;
+ }
+
+ if (isAnnotationPresent(method, BindsInstance.class)) {
+ error(
+ method,
+ messages.factoryMethodMayNotBeAnnotatedWithBindsInstance(),
+ messages.inheritedFactoryMethodMayNotBeAnnotatedWithBindsInstance());
+ return false;
+ }
+
+ TypeElement componentType = MoreElements.asType(component);
+ if (!types.isSameType(componentType.asType(), returnType)) {
+ ImmutableSet<ExecutableElement> methodsOnlyInComponent =
+ methodsOnlyInComponent(componentType);
+ if (!methodsOnlyInComponent.isEmpty()) {
+ report.addWarning(
+ messages.factoryMethodReturnsSupertypeWithMissingMethods(
+ componentType, type, returnType, method, methodsOnlyInComponent),
+ method);
+ }
+ }
+ return true;
}
- }
- private void validateNotGeneric(
- ExecutableElement method,
- ValidationReport.Builder<TypeElement> report,
- ComponentCreatorMessages messages) {
- if (!method.getTypeParameters().isEmpty()) {
- error(
- report,
- method,
- messages.methodsMayNotHaveTypeParameters(),
- messages.inheritedMethodsMayNotHaveTypeParameters());
+ /**
+ * Generates one of two error messages. If the method is enclosed in the subject, we target the
+ * error to the method itself. Otherwise we target the error to the subject and list the method
+ * as an argument. (Otherwise we have no way of knowing if the method is being compiled in this
+ * pass too, so javac might not be able to pinpoint it's line of code.)
+ */
+ /*
+ * For Component.Builder, the prototypical example would be if someone had:
+ * libfoo: interface SharedBuilder { void badSetter(A a, B b); }
+ * libbar: BarComponent { BarBuilder extends SharedBuilder } }
+ * ... the compiler only validates BarBuilder when compiling libbar, but it fails because
+ * of libfoo's SharedBuilder (which could have been compiled in a previous pass).
+ * So we can't point to SharedBuilder#badSetter as the subject of the BarBuilder validation
+ * failure.
+ *
+ * This check is a little more strict than necessary -- ideally we'd check if method's enclosing
+ * class was included in this compile run. But that's hard, and this is close enough.
+ */
+ private void error(
+ ExecutableElement method,
+ String enclosedError,
+ String inheritedError,
+ Object... extraArgs) {
+ if (method.getEnclosingElement().equals(type)) {
+ report.addError(String.format(enclosedError, extraArgs), method);
+ } else {
+ report.addError(String.format(inheritedError, ObjectArrays.concat(extraArgs, method)));
+ }
}
- }
- /**
- * Returns all methods defind in {@code componentType} which are not inherited from a supertype.
- */
- private ImmutableSet<ExecutableElement> methodsOnlyInComponent(TypeElement componentType) {
- // TODO(ronshapiro): Ideally this shouldn't return methods which are redeclared from a
- // supertype, but do not change the return type. We don't have a good/simple way of checking
- // that, and it doesn't seem likely, so the warning won't be too bad.
- return ImmutableSet.copyOf(methodsIn(componentType.getEnclosedElements()));
+ /** Validates that the given {@code method} is not generic. * */
+ private void validateNotGeneric(ExecutableElement method) {
+ if (!method.getTypeParameters().isEmpty()) {
+ error(
+ method,
+ messages.methodsMayNotHaveTypeParameters(),
+ messages.inheritedMethodsMayNotHaveTypeParameters());
+ }
+ }
+
+ /**
+ * Returns all methods defind in {@code componentType} which are not inherited from a supertype.
+ */
+ private ImmutableSet<ExecutableElement> methodsOnlyInComponent(TypeElement componentType) {
+ // TODO(ronshapiro): Ideally this shouldn't return methods which are redeclared from a
+ // supertype, but do not change the return type. We don't have a good/simple way of checking
+ // that, and it doesn't seem likely, so the warning won't be too bad.
+ return ImmutableSet.copyOf(methodsIn(componentType.getEnclosedElements()));
+ }
}
}
diff --git a/java/dagger/internal/codegen/ComponentDescriptor.java b/java/dagger/internal/codegen/ComponentDescriptor.java
index de979df..769cc4c 100644
--- a/java/dagger/internal/codegen/ComponentDescriptor.java
+++ b/java/dagger/internal/codegen/ComponentDescriptor.java
@@ -21,7 +21,7 @@
import static com.google.common.base.Preconditions.checkState;
import static dagger.internal.codegen.DaggerStreams.toImmutableMap;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.DaggerTypes.isFutureType;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.type.TypeKind.VOID;
@@ -32,11 +32,14 @@
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import dagger.Component;
import dagger.Module;
import dagger.Subcomponent;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.Scope;
import dagger.producers.CancellationPolicy;
@@ -194,6 +197,12 @@
abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
childComponentsDeclaredByFactoryMethods();
+ /** Returns a map of {@link #childComponents()} indexed by {@link #typeElement()}. */
+ @Memoized
+ ImmutableMap<TypeElement, ComponentDescriptor> childComponentsByElement() {
+ return Maps.uniqueIndex(childComponents(), ComponentDescriptor::typeElement);
+ }
+
/** Returns the factory method that declares a child component. */
final Optional<ComponentMethodDescriptor> getFactoryMethodForChildComponent(
ComponentDescriptor childComponent) {
diff --git a/java/dagger/internal/codegen/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/ComponentDescriptorFactory.java
index e120ade..7d87eac 100644
--- a/java/dagger/internal/codegen/ComponentDescriptorFactory.java
+++ b/java/dagger/internal/codegen/ComponentDescriptorFactory.java
@@ -38,6 +38,8 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Scope;
import java.util.Optional;
import java.util.function.Function;
@@ -110,7 +112,6 @@
private ComponentDescriptor create(
TypeElement typeElement, ComponentAnnotation componentAnnotation) {
- DeclaredType declaredComponentType = MoreTypes.asDeclared(typeElement.asType());
ImmutableSet<ComponentRequirement> componentDependencies =
componentAnnotation.dependencyTypes().stream()
.map(ComponentRequirement::forDependency)
diff --git a/java/dagger/internal/codegen/ComponentDescriptorValidator.java b/java/dagger/internal/codegen/ComponentDescriptorValidator.java
index ad8499c..8f85b3a 100644
--- a/java/dagger/internal/codegen/ComponentDescriptorValidator.java
+++ b/java/dagger/internal/codegen/ComponentDescriptorValidator.java
@@ -43,6 +43,8 @@
import com.google.common.collect.Sets;
import dagger.internal.codegen.ComponentRequirement.NullPolicy;
import dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Scope;
import java.util.ArrayDeque;
import java.util.Collection;
@@ -68,7 +70,7 @@
* Reports errors in the component hierarchy.
*
* <ul>
- * <li>Validates scope hierarchy of component dependencies and subcompoennts.
+ * <li>Validates scope hierarchy of component dependencies and subcomponents.
* <li>Reports errors if there are component dependency cycles.
* <li>Reports errors if any abstract modules have non-abstract instance binding methods.
* <li>Validates component creator types.
diff --git a/java/dagger/internal/codegen/ComponentGenerator.java b/java/dagger/internal/codegen/ComponentGenerator.java
index dad54b7..330ec2d 100644
--- a/java/dagger/internal/codegen/ComponentGenerator.java
+++ b/java/dagger/internal/codegen/ComponentGenerator.java
@@ -22,6 +22,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
import dagger.Component;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Optional;
import javax.annotation.processing.Filer;
import javax.inject.Inject;
diff --git a/java/dagger/internal/codegen/ComponentHjarProcessingStep.java b/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
index a8d6869..47857ca 100644
--- a/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
+++ b/java/dagger/internal/codegen/ComponentHjarProcessingStep.java
@@ -24,7 +24,7 @@
import static dagger.internal.codegen.ComponentAnnotation.rootComponentAnnotations;
import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
import static dagger.internal.codegen.ComponentGenerator.componentName;
-import static dagger.internal.codegen.TypeSpecs.addSupertype;
+import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
@@ -42,6 +42,8 @@
import com.squareup.javapoet.TypeSpec;
import dagger.BindsInstance;
import dagger.internal.codegen.ComponentValidator.ComponentValidationReport;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.producers.internal.CancellationListener;
import java.lang.annotation.Annotation;
import java.util.Optional;
@@ -139,8 +141,12 @@
ClassName generatedTypeName, ComponentDescriptor componentDescriptor) {
TypeSpec.Builder generatedComponent =
TypeSpec.classBuilder(generatedTypeName)
- .addModifiers(PUBLIC, FINAL)
+ .addModifiers(FINAL)
.addMethod(privateConstructor());
+ if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
+ generatedComponent.addModifiers(PUBLIC);
+ }
+
TypeElement componentElement = componentDescriptor.typeElement();
addSupertype(generatedComponent, componentElement);
@@ -156,8 +162,12 @@
} else {
TypeSpec.Builder builder =
TypeSpec.classBuilder("Builder")
- .addModifiers(PUBLIC, STATIC, FINAL)
+ .addModifiers(STATIC, FINAL)
.addMethod(privateConstructor());
+ if (componentDescriptor.typeElement().getModifiers().contains(PUBLIC)) {
+ builder.addModifiers(PUBLIC);
+ }
+
ClassName builderClassName = generatedTypeName.nestedClass("Builder");
builderMethodReturnType = builderClassName;
creatorKind = BUILDER;
diff --git a/java/dagger/internal/codegen/ComponentImplementation.java b/java/dagger/internal/codegen/ComponentImplementation.java
index d435e30..340da14 100644
--- a/java/dagger/internal/codegen/ComponentImplementation.java
+++ b/java/dagger/internal/codegen/ComponentImplementation.java
@@ -23,8 +23,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.serialization.ProtoSerialization.toAnnotationValue;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
@@ -32,10 +33,10 @@
import com.google.auto.value.AutoValue;
import com.google.common.base.Supplier;
-import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
@@ -47,12 +48,15 @@
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.ConfigureInitializationParameters;
+import dagger.internal.ModifiableBinding;
+import dagger.internal.ModifiableModule;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.TypeSpecs;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -158,8 +162,7 @@
/** Creates a new {@link ConfigureInitializationMethod}. */
static ConfigureInitializationMethod create(
MethodSpec spec, ImmutableSet<ComponentRequirement> parameters) {
- return new AutoValue_ComponentImplementation_ConfigureInitializationMethod(
- spec, parameters);
+ return new AutoValue_ComponentImplementation_ConfigureInitializationMethod(spec, parameters);
}
/** The spec for the method. */
@@ -172,8 +175,9 @@
abstract ImmutableSet<ComponentRequirement> parameters();
}
+ private final CompilerOptions compilerOptions;
private final ComponentDescriptor componentDescriptor;
- private final BindingGraph graph;
+ private final Optional<BindingGraph> graph;
private final ClassName name;
private final NestingKind nestingKind;
private final boolean isAbstract;
@@ -181,7 +185,7 @@
private Optional<ComponentCreatorImplementation> creatorImplementation;
private final Map<TypeElement, ComponentImplementation> childImplementations = new HashMap<>();
private final TypeSpec.Builder component;
- private final SubcomponentNames subcomponentNames;
+ private final Optional<SubcomponentNames> subcomponentNames;
private final UniqueNameSet componentFieldNames = new UniqueNameSet();
private final UniqueNameSet componentMethodNames = new UniqueNameSet();
private final List<CodeBlock> initializations = new ArrayList<>();
@@ -199,26 +203,29 @@
private final List<Supplier<TypeSpec>> switchingProviderSupplier = new ArrayList<>();
private final ModifiableBindingMethods modifiableBindingMethods = new ModifiableBindingMethods();
private final SetMultimap<BindingRequest, Key> multibindingContributionsMade =
- HashMultimap.create();
+ LinkedHashMultimap.create();
private Optional<ConfigureInitializationMethod> configureInitializationMethod = Optional.empty();
private final Map<ComponentRequirement, String> modifiableModuleMethods = new LinkedHashMap<>();
private ComponentImplementation(
ComponentDescriptor componentDescriptor,
- BindingGraph graph,
+ Optional<BindingGraph> graph,
ClassName name,
NestingKind nestingKind,
Optional<ComponentImplementation> superclassImplementation,
- SubcomponentNames subcomponentNames,
- Modifier... modifiers) {
+ Optional<SubcomponentNames> subcomponentNames,
+ CompilerOptions compilerOptions,
+ ImmutableSet<Modifier> modifiers) {
checkName(name, nestingKind);
+ this.compilerOptions = compilerOptions;
this.componentDescriptor = componentDescriptor;
this.graph = graph;
this.name = name;
this.nestingKind = nestingKind;
- this.isAbstract = Arrays.asList(modifiers).contains(ABSTRACT);
+ this.isAbstract = modifiers.contains(ABSTRACT);
this.superclassImplementation = superclassImplementation;
- this.component = classBuilder(name).addModifiers(modifiers);
+ this.component = classBuilder(name);
+ modifiers.forEach(component::addModifiers);
this.subcomponentNames = subcomponentNames;
}
@@ -226,16 +233,28 @@
static ComponentImplementation topLevelComponentImplementation(
BindingGraph graph,
ClassName name,
- SubcomponentNames subcomponentNames) {
+ SubcomponentNames subcomponentNames,
+ CompilerOptions compilerOptions) {
return new ComponentImplementation(
graph.componentDescriptor(),
- graph,
+ Optional.of(graph),
name,
NestingKind.TOP_LEVEL,
Optional.empty(), // superclass implementation
- subcomponentNames,
- PUBLIC,
- graph.componentDescriptor().isSubcomponent() ? ABSTRACT : FINAL);
+ Optional.of(subcomponentNames),
+ compilerOptions,
+ topLevelComponentImplementationModifiers(graph));
+ }
+
+ private static ImmutableSet<Modifier> topLevelComponentImplementationModifiers(
+ BindingGraph graph) {
+ ImmutableSet.Builder<Modifier> modifiers = ImmutableSet.builder();
+ if (graph.componentTypeElement().getModifiers().contains(PUBLIC)
+ || graph.componentDescriptor().isSubcomponent()) {
+ // TODO(ronshapiro): perhaps all generated components should be non-public?
+ modifiers.add(PUBLIC);
+ }
+ return modifiers.add(graph.componentDescriptor().isSubcomponent() ? ABSTRACT : FINAL).build();
}
/** Returns a component implementation that is a child of the current implementation. */
@@ -245,12 +264,35 @@
Modifier... modifiers) {
return new ComponentImplementation(
graph.componentDescriptor(),
- graph,
+ Optional.of(graph),
getSubcomponentName(graph.componentDescriptor()),
NestingKind.MEMBER,
superclassImplementation,
subcomponentNames,
- modifiers);
+ compilerOptions,
+ ImmutableSet.copyOf(modifiers));
+ }
+
+ /**
+ * Returns a component implementation that models a previously compiled class. This {@link
+ * ComponentImplementation} is not used for code generation itself; it is used to determine what
+ * methods need to be implemented in a subclass implementation.
+ */
+ static ComponentImplementation forDeserializedComponent(
+ ComponentDescriptor componentDescriptor,
+ ClassName name,
+ NestingKind nestingKind,
+ Optional<ComponentImplementation> superclassImplementation,
+ CompilerOptions compilerOptions) {
+ return new ComponentImplementation(
+ componentDescriptor,
+ Optional.empty(),
+ name,
+ nestingKind,
+ superclassImplementation,
+ Optional.empty(),
+ compilerOptions,
+ ImmutableSet.of(PUBLIC, ABSTRACT));
}
// TODO(dpb): Just determine the nesting kind from the name.
@@ -271,9 +313,22 @@
}
}
+ /**
+ * Returns {@code true} if this component implementation represents a component that has already
+ * been compiled. If this returns true, the implementation will have no {@link #graph
+ * BindingGraph}.
+ */
+ boolean isDeserializedImplementation() {
+ return !graph.isPresent();
+ }
+
+ // TODO(ronshapiro): see if we can remove this method and instead inject it in the objects that
+ // need it.
/** Returns the binding graph for the component being generated. */
BindingGraph graph() {
- return graph;
+ checkState(!isDeserializedImplementation(),
+ "A BindingGraph is not available for deserialized component implementations.");
+ return graph.get();
}
/** Returns the descriptor for the component being generated. */
@@ -362,7 +417,22 @@
*/
void setConfigureInitializationMethod(ConfigureInitializationMethod method) {
configureInitializationMethod = Optional.of(method);
- addMethod(MethodSpecKind.CONFIGURE_INITIALIZATION_METHOD, method.spec());
+ addMethod(
+ MethodSpecKind.CONFIGURE_INITIALIZATION_METHOD,
+ addConfigureInitializationMetadata(method));
+ }
+
+ private MethodSpec addConfigureInitializationMetadata(ConfigureInitializationMethod method) {
+ if (!shouldEmitModifiableMetadataAnnotations()) {
+ return method.spec();
+ }
+ AnnotationSpec.Builder annotation =
+ AnnotationSpec.builder(ConfigureInitializationParameters.class);
+ for (ComponentRequirement parameter : method.parameters()) {
+ annotation.addMember("value", toAnnotationValue(parameter.toProto()));
+ }
+
+ return method.spec().toBuilder().addAnnotation(annotation.build()).build();
}
void setCreatorImplementation(Optional<ComponentCreatorImplementation> creatorImplementation) {
@@ -403,7 +473,7 @@
*/
ClassName getCreatorName() {
return isNested()
- ? name.peerClass(subcomponentNames.getCreatorName(componentDescriptor()))
+ ? name.peerClass(subcomponentNames().getCreatorName(componentDescriptor()))
: name.nestedClass(creatorKind().typeName());
}
@@ -414,7 +484,7 @@
"%s is not a child component of %s",
childDescriptor.typeElement(),
componentDescriptor().typeElement());
- return name.nestedClass(subcomponentNames.get(childDescriptor) + "Impl");
+ return name.nestedClass(subcomponentNames().get(childDescriptor) + "Impl");
}
/**
@@ -422,7 +492,14 @@
* {@link Key}.
*/
String getSubcomponentCreatorSimpleName(Key key) {
- return subcomponentNames.getCreatorName(key);
+ return subcomponentNames().getCreatorName(key);
+ }
+
+ private SubcomponentNames subcomponentNames() {
+ checkState(
+ subcomponentNames.isPresent(),
+ "SubcomponentNames is not available for deserialized component implementations.");
+ return subcomponentNames.get();
}
/** Returns the child implementation. */
@@ -482,37 +559,94 @@
TypeMirror returnType,
MethodSpec methodSpec,
boolean finalized) {
- modifiableBindingMethods.addNewModifiableMethod(
- type, request, returnType, methodSpec, finalized);
- methodSpecsMap.put(MethodSpecKind.MODIFIABLE_BINDING_METHOD, methodSpec);
+ addModifiableMethod(
+ MethodSpecKind.MODIFIABLE_BINDING_METHOD, type, request, returnType, methodSpec, finalized);
}
/**
- * Registers a known method as encapsulating a modifiable binding without adding the method to the
- * current component. This is relevant when a method of a different type, such as a component
- * method, encapsulates a modifiable binding.
+ * Adds a component method that is modifiable to the component. In this case, the method
+ * represents an encapsulation of a modifiable binding between implementations of a subcomponent.
+ * This is only relevant for ahead-of-time subcomponents.
*/
- void registerModifiableBindingMethod(
+ void addModifiableComponentMethod(
ModifiableBindingType type,
BindingRequest request,
TypeMirror returnType,
MethodSpec methodSpec,
boolean finalized) {
- modifiableBindingMethods.addNewModifiableMethod(
+ addModifiableMethod(
+ MethodSpecKind.COMPONENT_METHOD, type, request, returnType, methodSpec, finalized);
+ }
+
+ private void addModifiableMethod(
+ MethodSpecKind methodKind,
+ ModifiableBindingType type,
+ BindingRequest request,
+ TypeMirror returnType,
+ MethodSpec methodSpec,
+ boolean finalized) {
+ modifiableBindingMethods.addModifiableMethod(
type, request, returnType, methodSpec, finalized);
+ methodSpecsMap.put(methodKind, withModifiableBindingMetadata(methodSpec, type, request));
}
/** Adds the implementation for the given {@link ModifiableBindingMethod} to the component. */
void addImplementedModifiableBindingMethod(ModifiableBindingMethod method) {
modifiableBindingMethods.addReimplementedMethod(method);
- methodSpecsMap.put(MethodSpecKind.MODIFIABLE_BINDING_METHOD, method.methodSpec());
+ methodSpecsMap.put(
+ MethodSpecKind.MODIFIABLE_BINDING_METHOD,
+ withModifiableBindingMetadata(method.methodSpec(), method.type(), method.request()));
+ }
+
+ private MethodSpec withModifiableBindingMetadata(
+ MethodSpec method, ModifiableBindingType type, BindingRequest request) {
+ if (!shouldEmitModifiableMetadataAnnotations()) {
+ return method;
+ }
+ AnnotationSpec.Builder metadata =
+ AnnotationSpec.builder(ModifiableBinding.class)
+ .addMember("modifiableBindingType", "$S", type.name())
+ .addMember("bindingRequest", toAnnotationValue(request.toProto()));
+ for (Key multibindingContribution : multibindingContributionsMade.get(request)) {
+ metadata.addMember(
+ "multibindingContributions",
+ toAnnotationValue(KeyFactory.toProto(multibindingContribution)));
+ }
+ return method.toBuilder().addAnnotation(metadata.build()).build();
}
/** Add's a modifiable module method to this implementation. */
void addModifiableModuleMethod(ComponentRequirement module, MethodSpec method) {
+ registerModifiableModuleMethod(module, method.name);
+ methodSpecsMap.put(
+ MethodSpecKind.MODIFIABLE_BINDING_METHOD, withModifiableModuleMetadata(module, method));
+ }
+
+ /** Registers a modifiable module method with {@code name} for {@code module}. */
+ void registerModifiableModuleMethod(ComponentRequirement module, String name) {
checkArgument(module.kind().isModule());
- checkState(modifiableModuleMethods.put(module, method.name) == null);
- methodSpecsMap.put(MethodSpecKind.MODIFIABLE_BINDING_METHOD, method);
+ checkState(modifiableModuleMethods.put(module, name) == null);
+ }
+
+ private MethodSpec withModifiableModuleMetadata(ComponentRequirement module, MethodSpec method) {
+ if (!shouldEmitModifiableMetadataAnnotations()) {
+ return method;
+ }
+ return method
+ .toBuilder()
+ .addAnnotation(
+ AnnotationSpec.builder(ModifiableModule.class)
+ .addMember("value", toAnnotationValue(module.toProto()))
+ .build())
+ .build();
+ }
+
+ /**
+ * Returns {@code true} if the generated component should include metadata annotations with
+ * information to deserialize this {@link ComponentImplementation} in future compilations.
+ */
+ boolean shouldEmitModifiableMetadataAnnotations() {
+ return isAbstract && compilerOptions.emitModifiableMetadataAnnotations();
}
/** Adds the given type to the component. */
@@ -645,8 +779,7 @@
Optional<ComponentImplementation> currentSuperImplementation = superclassImplementation;
Set<Key> cancelledKeysFromSuperclass = new HashSet<>();
while (currentSuperImplementation.isPresent()) {
- cancelledKeysFromSuperclass.addAll(
- currentSuperImplementation.get().cancellableProducerKeys);
+ cancelledKeysFromSuperclass.addAll(currentSuperImplementation.get().cancellableProducerKeys);
currentSuperImplementation = currentSuperImplementation.get().superclassImplementation;
}
return Sets.difference(cancellableProducerKeys, cancelledKeysFromSuperclass)
@@ -757,13 +890,23 @@
// We register a multibinding as implemented each time we request the multibinding expression,
// so only modify the set of contributions once.
if (!multibindingContributionsMade.containsKey(bindingRequest)) {
- multibindingContributionsMade.putAll(
+ registerImplementedMultibindingKeys(
bindingRequest,
multibinding.dependencies().stream().map(DependencyRequest::key).collect(toList()));
}
}
/**
+ * Registers the multibinding contributions represented by {@code keys} as having been implemented
+ * in this component. Multibindings are modifiable across subcomponent implementations and this
+ * allows us to know whether a contribution has been made by a superclass implementation. This is
+ * only relevant for ahead-of-time subcomponents.
+ */
+ void registerImplementedMultibindingKeys(BindingRequest bindingRequest, Iterable<Key> keys) {
+ multibindingContributionsMade.putAll(bindingRequest, keys);
+ }
+
+ /**
* Returns the set of multibinding contributions associated with all superclass implementations of
* a multibinding.
*/
diff --git a/java/dagger/internal/codegen/ComponentImplementationBuilder.java b/java/dagger/internal/codegen/ComponentImplementationBuilder.java
index 19cf55b..7579ac9 100644
--- a/java/dagger/internal/codegen/ComponentImplementationBuilder.java
+++ b/java/dagger/internal/codegen/ComponentImplementationBuilder.java
@@ -23,10 +23,7 @@
import static com.google.common.base.Predicates.in;
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.CodeBlocks.parameterNames;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.ComponentCreatorKind.BUILDER;
import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.BUILDER_METHOD;
import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.CANCELLATION_LISTENER_METHOD;
@@ -37,6 +34,9 @@
import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.COMPONENT_CREATOR;
import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.SUBCOMPONENT;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.CodeBlocks.parameterNames;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
import static dagger.producers.CancellationPolicy.Propagation.PROPAGATE;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
@@ -55,16 +55,22 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
+import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.ComponentDefinitionType;
import dagger.internal.Preconditions;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ComponentImplementation.ConfigureInitializationMethod;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import dagger.producers.internal.CancellationListener;
import dagger.producers.internal.Producers;
@@ -116,7 +122,7 @@
setSupertype();
componentImplementation.setCreatorImplementation(
componentCreatorImplementationFactory.create(
- componentImplementation, componentImplementation.graph()));
+ componentImplementation, Optional.of(componentImplementation.graph())));
componentImplementation
.creatorImplementation()
.map(ComponentCreatorImplementation::spec)
@@ -149,6 +155,13 @@
componentImplementation.addAnnotation(compilerOptions.toGenerationOptionsAnnotation());
}
+ if (componentImplementation.shouldEmitModifiableMetadataAnnotations()) {
+ componentImplementation.addAnnotation(
+ AnnotationSpec.builder(ComponentDefinitionType.class)
+ .addMember("value", "$T.class", graph.componentTypeElement())
+ .build());
+ }
+
done = true;
return componentImplementation;
}
@@ -207,16 +220,11 @@
componentImplementation.addMethod(
COMPONENT_METHOD, implementedComponentMethod.toBuilder().addModifiers(FINAL).build());
} else {
- // If the binding for the component method is modifiable, register it as such.
- ModifiableBindingType modifiableBindingType =
- bindingExpressions
- .modifiableBindingExpressions()
- .registerComponentMethodIfModifiable(methodDescriptor, implementedComponentMethod);
-
- // If the method should be implemented in this component, implement it.
- if (modifiableBindingType.hasBaseClassImplementation()) {
- componentImplementation.addMethod(COMPONENT_METHOD, implementedComponentMethod);
- }
+ // TODO(b/117833324): Can this class be the one to interface with ComponentImplementation
+ // instead of having it go through ModifiableBindingExpressions?
+ bindingExpressions
+ .modifiableBindingExpressions()
+ .addPossiblyModifiableComponentMethod(methodDescriptor, implementedComponentMethod);
}
}
diff --git a/java/dagger/internal/codegen/ComponentImplementationFactory.java b/java/dagger/internal/codegen/ComponentImplementationFactory.java
index 5ecdac0..9578ece 100644
--- a/java/dagger/internal/codegen/ComponentImplementationFactory.java
+++ b/java/dagger/internal/codegen/ComponentImplementationFactory.java
@@ -19,10 +19,15 @@
import static com.google.common.base.Preconditions.checkState;
import static dagger.internal.codegen.ComponentGenerator.componentName;
import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static javax.tools.Diagnostic.Kind.WARNING;
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.serialization.ProtoSerialization.InconsistentSerializedProtoException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
+import javax.annotation.processing.Messager;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.lang.model.element.TypeElement;
@@ -35,17 +40,27 @@
private final CompilerOptions compilerOptions;
private final BindingGraphFactory bindingGraphFactory;
private final TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder;
+ private final DeserializedComponentImplementationBuilder
+ deserializedComponentImplementationBuilder;
+ private final DaggerElements elements;
+ private final Messager messager;
@Inject
ComponentImplementationFactory(
KeyFactory keyFactory,
CompilerOptions compilerOptions,
BindingGraphFactory bindingGraphFactory,
- TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder) {
+ TopLevelImplementationComponent.Builder topLevelImplementationComponentBuilder,
+ DeserializedComponentImplementationBuilder deserializedComponentImplementationBuilder,
+ DaggerElements elements,
+ Messager messager) {
this.keyFactory = keyFactory;
this.compilerOptions = compilerOptions;
this.bindingGraphFactory = bindingGraphFactory;
this.topLevelImplementationComponentBuilder = topLevelImplementationComponentBuilder;
+ this.deserializedComponentImplementationBuilder = deserializedComponentImplementationBuilder;
+ this.elements = elements;
+ this.messager = messager;
}
/**
@@ -66,7 +81,9 @@
ComponentImplementation.topLevelComponentImplementation(
bindingGraph,
componentName(bindingGraph.componentTypeElement()),
- new SubcomponentNames(bindingGraph, keyFactory));
+ new SubcomponentNames(bindingGraph, keyFactory),
+ compilerOptions);
+
// TODO(dpb): explore using optional bindings for the "parent" bindings
CurrentImplementationSubcomponent currentImplementationSubcomponent =
topLevelImplementationComponentBuilder
@@ -109,6 +126,28 @@
}
}
+ if (compilerOptions.emitModifiableMetadataAnnotations()) {
+ ClassName childSuperclassName = componentName(child.typeElement());
+ TypeElement generatedChildSuperclassImplementation =
+ elements.getTypeElement(childSuperclassName);
+ if (generatedChildSuperclassImplementation != null) {
+ try {
+ return deserializedComponentImplementationBuilder.create(
+ child, generatedChildSuperclassImplementation);
+ } catch (InconsistentSerializedProtoException e) {
+ messager.printMessage(
+ WARNING,
+ String.format(
+ "%s was compiled with a different version of Dagger than the version in this "
+ + "compilation. To ensure the validity of Dagger's generated code, compile "
+ + "all Dagger code with the same version.",
+ child.typeElement().getQualifiedName()));
+ }
+ } else if (compilerOptions.forceUseSerializedComponentImplementations()) {
+ throw new TypeNotPresentException(childSuperclassName.toString(), null);
+ }
+ }
+
// Otherwise, the superclass implementation is top-level, so we must recreate the
// implementation object for the base implementation of the child by truncating the binding
// graph at the child.
diff --git a/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
index 552a0b2..e98d595 100644
--- a/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
@@ -18,6 +18,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.javapoet.Expression;
/** A binding expression for the instance of the component itself, i.e. {@code this}. */
final class ComponentInstanceBindingExpression extends SimpleInvocationBindingExpression {
diff --git a/java/dagger/internal/codegen/ComponentMethodBindingExpression.java b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
index f9e0b5a..7e7bbd8 100644
--- a/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
@@ -21,6 +21,8 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.lang.model.type.TypeMirror;
/**
diff --git a/java/dagger/internal/codegen/ComponentProcessingStep.java b/java/dagger/internal/codegen/ComponentProcessingStep.java
index 32d7d91..645c94f 100644
--- a/java/dagger/internal/codegen/ComponentProcessingStep.java
+++ b/java/dagger/internal/codegen/ComponentProcessingStep.java
@@ -23,6 +23,7 @@
import static dagger.internal.codegen.ComponentCreatorAnnotation.allCreatorAnnotations;
import static dagger.internal.codegen.ComponentCreatorAnnotation.rootComponentCreatorAnnotations;
import static dagger.internal.codegen.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
+import static dagger.internal.codegen.ValidationType.NONE;
import static java.util.Collections.disjoint;
import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
@@ -134,6 +135,9 @@
if (!isValid(componentDescriptor)) {
return;
}
+ if (!isFullBindingGraphValid(componentDescriptor)) {
+ return;
+ }
BindingGraph bindingGraph = bindingGraphFactory.create(componentDescriptor, false);
if (isValid(bindingGraph)) {
generateComponent(bindingGraph);
@@ -141,7 +145,8 @@
}
private void processSubcomponent(TypeElement subcomponent) {
- if (!compilerOptions.aheadOfTimeSubcomponents()) {
+ if (!compilerOptions.aheadOfTimeSubcomponents()
+ && compilerOptions.fullBindingGraphValidationType(subcomponent).equals(NONE)) {
return;
}
if (!isSubcomponentValid(subcomponent)) {
@@ -150,9 +155,14 @@
ComponentDescriptor subcomponentDescriptor =
componentDescriptorFactory.subcomponentDescriptor(subcomponent);
// TODO(dpb): ComponentDescriptorValidator for subcomponents, as we do for root components.
- BindingGraph bindingGraph = bindingGraphFactory.create(subcomponentDescriptor, false);
- if (isValid(bindingGraph)) {
- generateComponent(bindingGraph);
+ if (!isFullBindingGraphValid(subcomponentDescriptor)) {
+ return;
+ }
+ if (compilerOptions.aheadOfTimeSubcomponents()) {
+ BindingGraph bindingGraph = bindingGraphFactory.create(subcomponentDescriptor, false);
+ if (isValid(bindingGraph)) {
+ generateComponent(bindingGraph);
+ }
}
}
@@ -220,10 +230,17 @@
return false;
}
ValidationReport<?> subcomponentReport = reportsBySubcomponent.get(subcomponentElement);
- if (subcomponentReport != null && !subcomponentReport.isClean()) {
- return false;
+ return subcomponentReport == null || subcomponentReport.isClean();
+ }
+
+ private boolean isFullBindingGraphValid(ComponentDescriptor componentDescriptor) {
+ if (compilerOptions
+ .fullBindingGraphValidationType(componentDescriptor.typeElement())
+ .equals(NONE)) {
+ return true;
}
- return true;
+ BindingGraph fullBindingGraph = bindingGraphFactory.create(componentDescriptor, true);
+ return isValid(fullBindingGraph);
}
private boolean isValid(ComponentDescriptor componentDescriptor) {
diff --git a/java/dagger/internal/codegen/ComponentProcessor.java b/java/dagger/internal/codegen/ComponentProcessor.java
index 6b137b3..541a4ab 100644
--- a/java/dagger/internal/codegen/ComponentProcessor.java
+++ b/java/dagger/internal/codegen/ComponentProcessor.java
@@ -16,6 +16,8 @@
package dagger.internal.codegen;
+import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.DYNAMIC;
+
import com.google.auto.common.BasicAnnotationProcessor;
import com.google.auto.service.AutoService;
import com.google.common.annotations.VisibleForTesting;
@@ -38,6 +40,7 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.lang.model.SourceVersion;
+import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
/**
* The annotation processor responsible for generating the classes that drive the Dagger 2.0
@@ -45,6 +48,7 @@
*
* <p>TODO(gak): give this some better documentation
*/
+@IncrementalAnnotationProcessor(DYNAMIC)
@AutoService(Processor.class)
public class ComponentProcessor extends BasicAnnotationProcessor {
private final Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins;
@@ -92,7 +96,7 @@
@Override
public Set<String> getSupportedOptions() {
ImmutableSet.Builder<String> options = ImmutableSet.builder();
- options.addAll(CompilerOptions.supportedOptions());
+ options.addAll(ProcessingEnvironmentCompilerOptions.supportedOptions());
options.addAll(bindingGraphPlugins.allSupportedOptions());
if (compilerOptions.useGradleIncrementalProcessing()) {
options.add("org.gradle.annotation.processing.isolating");
diff --git a/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java b/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java
index 723673b..b8c6049 100644
--- a/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java
+++ b/java/dagger/internal/codegen/ComponentProvisionBindingExpression.java
@@ -21,6 +21,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.Preconditions;
+import dagger.internal.codegen.javapoet.Expression;
/** A binding expression for component provision methods. */
final class ComponentProvisionBindingExpression extends SimpleInvocationBindingExpression {
diff --git a/java/dagger/internal/codegen/ComponentRequirement.java b/java/dagger/internal/codegen/ComponentRequirement.java
index 924ed95..3bed5da 100644
--- a/java/dagger/internal/codegen/ComponentRequirement.java
+++ b/java/dagger/internal/codegen/ComponentRequirement.java
@@ -19,9 +19,9 @@
import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
import static dagger.internal.codegen.SourceFiles.simpleVariableName;
import static dagger.internal.codegen.Util.componentCanMakeNewInstances;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.STATIC;
@@ -34,6 +34,10 @@
import dagger.Binds;
import dagger.BindsOptionalOf;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.ComponentRequirementProto;
+import dagger.internal.codegen.serialization.ComponentRequirementProto.BoundInstanceRequirement;
import dagger.model.BindingKind;
import dagger.model.Key;
import dagger.multibindings.Multibinds;
@@ -183,6 +187,29 @@
return ParameterSpec.builder(TypeName.get(type()), variableName()).build();
}
+ /** Creates a proto representation of this requirement. */
+ ComponentRequirementProto toProto() {
+ switch (kind()) {
+ case DEPENDENCY:
+ return ComponentRequirementProto.newBuilder()
+ .setDependency(TypeProtoConverter.toProto(type()))
+ .build();
+ case MODULE:
+ return ComponentRequirementProto.newBuilder()
+ .setModule(TypeProtoConverter.toProto(type()))
+ .build();
+ case BOUND_INSTANCE:
+ return ComponentRequirementProto.newBuilder()
+ .setBoundInstance(
+ BoundInstanceRequirement.newBuilder()
+ .setKey(KeyFactory.toProto(key().get()))
+ .setNullable(overrideNullPolicy().equals(Optional.of(NullPolicy.ALLOW)))
+ .setVariableName(variableName()))
+ .build();
+ }
+ throw new AssertionError(this);
+ }
+
static ComponentRequirement forDependency(TypeMirror type) {
return new AutoValue_ComponentRequirement(
Kind.DEPENDENCY,
diff --git a/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java b/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java
index e0cdd5a..d6aa053 100644
--- a/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java
+++ b/java/dagger/internal/codegen/ComponentRequirementBindingExpression.java
@@ -17,6 +17,7 @@
package dagger.internal.codegen;
import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
/**
* A binding expression for instances bound with {@link dagger.BindsInstance} and instances of
diff --git a/java/dagger/internal/codegen/ComponentRequirementExpressions.java b/java/dagger/internal/codegen/ComponentRequirementExpressions.java
index 779a7b5..4ab58c9 100644
--- a/java/dagger/internal/codegen/ComponentRequirementExpressions.java
+++ b/java/dagger/internal/codegen/ComponentRequirementExpressions.java
@@ -36,6 +36,7 @@
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/ComponentTreeTraverser.java b/java/dagger/internal/codegen/ComponentTreeTraverser.java
index 545ec99..cc1efd2 100644
--- a/java/dagger/internal/codegen/ComponentTreeTraverser.java
+++ b/java/dagger/internal/codegen/ComponentTreeTraverser.java
@@ -16,7 +16,6 @@
package dagger.internal.codegen;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Verify.verify;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
@@ -47,12 +46,7 @@
private final Deque<ComponentPath> componentPaths = new ArrayDeque<>();
/** Constructs a traverser for a root (component, not subcomponent) binding graph. */
- public ComponentTreeTraverser(BindingGraph rootGraph, CompilerOptions compilerOptions) {
- checkArgument(
- !rootGraph.componentDescriptor().isSubcomponent()
- || compilerOptions.aheadOfTimeSubcomponents(),
- "only root graphs can be traversed, not %s",
- rootGraph.componentTypeElement().getQualifiedName());
+ public ComponentTreeTraverser(BindingGraph rootGraph) {
bindingGraphPath.add(rootGraph);
componentPaths.add(ComponentPath.create(ImmutableList.of(rootGraph.componentTypeElement())));
}
diff --git a/java/dagger/internal/codegen/ComponentValidator.java b/java/dagger/internal/codegen/ComponentValidator.java
index 7285dac..7739915 100644
--- a/java/dagger/internal/codegen/ComponentValidator.java
+++ b/java/dagger/internal/codegen/ComponentValidator.java
@@ -33,13 +33,13 @@
import static dagger.internal.codegen.ComponentKind.annotationsFor;
import static dagger.internal.codegen.ConfigurationAnnotations.enclosedAnnotatedTypes;
import static dagger.internal.codegen.ConfigurationAnnotations.getTransitiveModules;
-import static dagger.internal.codegen.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.DaggerElements.getAnyAnnotation;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages.builderMethodRequiresNoArgs;
import static dagger.internal.codegen.ErrorMessages.ComponentCreatorMessages.moreThanOneRefToSubcomponent;
import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
import static java.util.Comparator.comparing;
import static javax.lang.model.element.ElementKind.CLASS;
import static javax.lang.model.element.ElementKind.INTERFACE;
@@ -59,6 +59,8 @@
import com.google.common.collect.Sets;
import dagger.Component;
import dagger.Reusable;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.producers.CancellationPolicy;
@@ -78,7 +80,9 @@
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.SimpleTypeVisitor6;
+import javax.lang.model.util.SimpleTypeVisitor8;
/**
* Performs superficial validation of the contract of the {@link Component} and {@link
@@ -482,35 +486,27 @@
private static <T extends Element> void validateComponentDependencies(
ValidationReport.Builder<T> report, Iterable<TypeMirror> types) {
- validateTypesAreDeclared(report, types, "component dependency");
for (TypeMirror type : types) {
- if (moduleAnnotation(MoreTypes.asTypeElement(type)).isPresent()) {
- report.addError(
- String.format("%s is a module, which cannot be a component dependency", type));
- }
+ type.accept(CHECK_DEPENDENCY_TYPES, report);
}
}
- private static <T extends Element> void validateTypesAreDeclared(
- final ValidationReport.Builder<T> report, Iterable<TypeMirror> types, final String typeName) {
- for (TypeMirror type : types) {
- type.accept(
- new SimpleTypeVisitor6<Void, Void>() {
- @Override
- protected Void defaultAction(TypeMirror e, Void aVoid) {
- report.addError(String.format("%s is not a valid %s type", e, typeName));
- return null;
- }
+ private static final TypeVisitor<Void, ValidationReport.Builder<?>> CHECK_DEPENDENCY_TYPES =
+ new SimpleTypeVisitor8<Void, ValidationReport.Builder<?>>() {
+ @Override
+ protected Void defaultAction(TypeMirror type, ValidationReport.Builder<?> report) {
+ report.addError(type + " is not a valid component dependency type");
+ return null;
+ }
- @Override
- public Void visitDeclared(DeclaredType t, Void aVoid) {
- // Declared types are valid
- return null;
- }
- },
- null);
- }
- }
+ @Override
+ public Void visitDeclared(DeclaredType type, ValidationReport.Builder<?> report) {
+ if (moduleAnnotation(MoreTypes.asTypeElement(type)).isPresent()) {
+ report.addError(type + " is a module, which cannot be a component dependency");
+ }
+ return null;
+ }
+ };
private static Optional<AnnotationMirror> checkForAnnotations(
TypeMirror type, final Set<? extends Class<? extends Annotation>> annotations) {
diff --git a/java/dagger/internal/codegen/ConfigurationAnnotations.java b/java/dagger/internal/codegen/ConfigurationAnnotations.java
index eee7c8b..a9bba29 100644
--- a/java/dagger/internal/codegen/ConfigurationAnnotations.java
+++ b/java/dagger/internal/codegen/ConfigurationAnnotations.java
@@ -21,9 +21,9 @@
import static com.google.common.collect.Iterables.consumingIterable;
import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotation;
import static dagger.internal.codegen.ComponentCreatorAnnotation.subcomponentCreatorAnnotations;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
import static dagger.internal.codegen.MoreAnnotationMirrors.getTypeListValue;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import static javax.lang.model.util.ElementFilter.typesIn;
import com.google.auto.common.MoreElements;
@@ -34,6 +34,8 @@
import com.google.common.collect.Sets;
import dagger.Component;
import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.lang.annotation.Annotation;
import java.util.ArrayDeque;
import java.util.List;
diff --git a/java/dagger/internal/codegen/ContributionBinding.java b/java/dagger/internal/codegen/ContributionBinding.java
index 4da1e44..0958bc8 100644
--- a/java/dagger/internal/codegen/ContributionBinding.java
+++ b/java/dagger/internal/codegen/ContributionBinding.java
@@ -68,7 +68,7 @@
}
/** If {@link #bindingElement()} is a method that returns a primitive type, returns that type. */
- Optional<TypeMirror> contributedPrimitiveType() {
+ final Optional<TypeMirror> contributedPrimitiveType() {
return bindingElement()
.filter(bindingElement -> bindingElement instanceof ExecutableElement)
.map(bindingElement -> MoreElements.asExecutable(bindingElement).getReturnType())
@@ -102,7 +102,7 @@
*
* <p>All other bindings use the {@link FactoryCreationStrategy#CLASS_CONSTRUCTOR} strategy.
*/
- FactoryCreationStrategy factoryCreationStrategy() {
+ final FactoryCreationStrategy factoryCreationStrategy() {
switch (kind()) {
case DELEGATE:
return DELEGATE;
@@ -133,9 +133,8 @@
case SET_VALUES:
case UNIQUE:
return key().type();
- default:
- throw new AssertionError();
}
+ throw new AssertionError();
}
final boolean isSyntheticMultibinding() {
diff --git a/java/dagger/internal/codegen/ContributionType.java b/java/dagger/internal/codegen/ContributionType.java
index e3f8e37..66b5289 100644
--- a/java/dagger/internal/codegen/ContributionType.java
+++ b/java/dagger/internal/codegen/ContributionType.java
@@ -22,7 +22,7 @@
import dagger.multibindings.ElementsIntoSet;
import dagger.multibindings.IntoMap;
import dagger.multibindings.IntoSet;
-import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Element;
/** Whether a binding or declaration is for a unique contribution or a map or set multibinding. */
enum ContributionType {
@@ -49,16 +49,17 @@
}
/**
- * The contribution type from a binding method annotations. Presumes a well-formed binding method
- * (at most one of @IntoSet, @IntoMap, @ElementsIntoSet and @Provides.type). {@link
- * ProvidesMethodValidator} and {@link ProducesMethodValidator} validate correctness on their own.
+ * The contribution type from a binding element's annotations. Presumes a well-formed binding
+ * element (at most one of @IntoSet, @IntoMap, @ElementsIntoSet and @Provides.type). {@link
+ * BindingMethodValidator} and {@link BindsInstanceProcessingStep} validate correctness on their
+ * own.
*/
- static ContributionType fromBindingMethod(ExecutableElement method) {
- if (isAnnotationPresent(method, IntoMap.class)) {
+ static ContributionType fromBindingElement(Element element) {
+ if (isAnnotationPresent(element, IntoMap.class)) {
return ContributionType.MAP;
- } else if (isAnnotationPresent(method, IntoSet.class)) {
+ } else if (isAnnotationPresent(element, IntoSet.class)) {
return ContributionType.SET;
- } else if (isAnnotationPresent(method, ElementsIntoSet.class)) {
+ } else if (isAnnotationPresent(element, ElementsIntoSet.class)) {
return ContributionType.SET_VALUES;
}
return ContributionType.UNIQUE;
diff --git a/java/dagger/internal/codegen/DaggerKythePlugin.java b/java/dagger/internal/codegen/DaggerKythePlugin.java
index 238a50a..5a685ef 100644
--- a/java/dagger/internal/codegen/DaggerKythePlugin.java
+++ b/java/dagger/internal/codegen/DaggerKythePlugin.java
@@ -20,7 +20,7 @@
package dagger.internal.codegen;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import com.google.auto.service.AutoService;
import com.google.common.collect.Iterables;
diff --git a/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java b/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java
index 502b921..c41cf2c 100644
--- a/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java
+++ b/java/dagger/internal/codegen/DeferredModifiableBindingExpression.java
@@ -20,6 +20,7 @@
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/DelegateBindingExpression.java b/java/dagger/internal/codegen/DelegateBindingExpression.java
index 8f1ed0c..8cdf6d1 100644
--- a/java/dagger/internal/codegen/DelegateBindingExpression.java
+++ b/java/dagger/internal/codegen/DelegateBindingExpression.java
@@ -19,12 +19,15 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
import static dagger.internal.codegen.RequestKinds.requestType;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static dagger.model.BindingKind.DELEGATE;
import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.RequestKind;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/DelegateDeclaration.java b/java/dagger/internal/codegen/DelegateDeclaration.java
index 2dbff78..67991de 100644
--- a/java/dagger/internal/codegen/DelegateDeclaration.java
+++ b/java/dagger/internal/codegen/DelegateDeclaration.java
@@ -28,6 +28,7 @@
import com.google.common.collect.Iterables;
import dagger.Binds;
import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import java.util.Optional;
import javax.inject.Inject;
@@ -79,7 +80,7 @@
Iterables.getOnlyElement(bindsMethod.getParameters()),
Iterables.getOnlyElement(resolvedMethod.getParameterTypes()));
return new AutoValue_DelegateDeclaration(
- ContributionType.fromBindingMethod(bindsMethod),
+ ContributionType.fromBindingElement(bindsMethod),
keyFactory.forBindsMethod(bindsMethod, contributingModule),
Optional.<Element>of(bindsMethod),
Optional.of(contributingModule),
diff --git a/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
index 5d5f463..7524cdf 100644
--- a/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
+++ b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
@@ -22,6 +22,8 @@
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.model.DependencyRequest;
/** A framework instance creation expression for a {@link dagger.Binds @Binds} binding. */
final class DelegatingFrameworkInstanceCreationExpression
@@ -42,12 +44,13 @@
@Override
public CodeBlock creationExpression() {
- FrameworkDependency frameworkDependency = getOnlyElement(binding.frameworkDependencies());
+ DependencyRequest dependency = getOnlyElement(binding.dependencies());
return CodeBlocks.cast(
componentBindingExpressions
.getDependencyExpression(
- bindingRequest(frameworkDependency), componentImplementation.name())
+ bindingRequest(dependency.key(), binding.frameworkType()),
+ componentImplementation.name())
.codeBlock(),
- frameworkDependency.frameworkClass());
+ binding.frameworkType().frameworkClass());
}
}
diff --git a/java/dagger/internal/codegen/DependencyEdgeImpl.java b/java/dagger/internal/codegen/DependencyEdgeImpl.java
index b777251..64b0845 100644
--- a/java/dagger/internal/codegen/DependencyEdgeImpl.java
+++ b/java/dagger/internal/codegen/DependencyEdgeImpl.java
@@ -45,7 +45,7 @@
String string =
dependencyRequest
.requestElement()
- .map(DaggerElements::elementToString)
+ .map(ElementFormatter::elementToString)
.orElseGet(
() ->
"synthetic request for "
diff --git a/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
index c934059..b42f9c4 100644
--- a/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
+++ b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
@@ -19,8 +19,8 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static dagger.internal.codegen.TypeNames.dependencyMethodProducerOf;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.dependencyMethodProducerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
diff --git a/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
index ca050e6..8532481 100644
--- a/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
@@ -21,7 +21,7 @@
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
diff --git a/java/dagger/internal/codegen/DependencyRequestFactory.java b/java/dagger/internal/codegen/DependencyRequestFactory.java
index a66edd0..3ad12e2 100644
--- a/java/dagger/internal/codegen/DependencyRequestFactory.java
+++ b/java/dagger/internal/codegen/DependencyRequestFactory.java
@@ -34,6 +34,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import dagger.Lazy;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
@@ -122,9 +123,8 @@
case UNIQUE:
throw new IllegalArgumentException(
"multibindingContribution must be a multibinding: " + multibindingContribution);
- default:
- throw new AssertionError(multibindingContribution.toString());
}
+ throw new AssertionError(multibindingContribution.toString());
}
DependencyRequest forRequiredResolvedVariable(
diff --git a/java/dagger/internal/codegen/DependencyRequestFormatter.java b/java/dagger/internal/codegen/DependencyRequestFormatter.java
index 357cca1..25becaf 100644
--- a/java/dagger/internal/codegen/DependencyRequestFormatter.java
+++ b/java/dagger/internal/codegen/DependencyRequestFormatter.java
@@ -16,11 +16,12 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.elementToString;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
import static dagger.internal.codegen.RequestKinds.requestType;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.producers.Produces;
import java.util.Optional;
@@ -143,8 +144,8 @@
return "injected";
case PRODUCED:
- default:
- throw new AssertionError("illegal request kind for method: " + request);
+ break;
}
+ throw new AssertionError("illegal request kind for method: " + request);
}
}
diff --git a/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java
index b67e1d0..4f2f622 100644
--- a/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/DerivedFromFrameworkInstanceBindingExpression.java
@@ -22,6 +22,8 @@
import com.squareup.javapoet.ClassName;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import dagger.model.RequestKind;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java b/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java
new file mode 100644
index 0000000..45e99a8
--- /dev/null
+++ b/java/dagger/internal/codegen/DeserializedComponentImplementationBuilder.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
+import static com.google.auto.common.MoreElements.getAnnotationMirror;
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.serialization.ProtoSerialization.fromAnnotationValue;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static javax.lang.model.util.ElementFilter.typesIn;
+
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.ComponentDefinitionType;
+import dagger.internal.ConfigureInitializationParameters;
+import dagger.internal.ModifiableBinding;
+import dagger.internal.ModifiableModule;
+import dagger.internal.codegen.ComponentImplementation.ConfigureInitializationMethod;
+import dagger.internal.codegen.serialization.BindingRequestProto;
+import dagger.internal.codegen.serialization.ComponentRequirementProto;
+import dagger.internal.codegen.serialization.FrameworkTypeWrapper;
+import dagger.internal.codegen.serialization.KeyProto;
+import dagger.model.Key;
+import dagger.model.RequestKind;
+import java.util.Optional;
+import javax.inject.Inject;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Reconstructs {@link ComponentImplementation}s that have already been compiled. Uses metadata
+ * annotations on the generated type and it's methods to reconstitute the equivalent {@link
+ * ComponentImplementation} state.
+ */
+final class DeserializedComponentImplementationBuilder {
+ private final CompilerOptions compilerOptions;
+ private final ComponentCreatorImplementationFactory componentCreatorImplementationFactory;
+ private final TypeProtoConverter typeProtoConverter;
+ private final KeyFactory keyFactory;
+
+ @Inject
+ DeserializedComponentImplementationBuilder(
+ CompilerOptions compilerOptions,
+ ComponentCreatorImplementationFactory componentCreatorImplementationFactory,
+ TypeProtoConverter typeProtoConverter,
+ KeyFactory keyFactory) {
+ this.compilerOptions = compilerOptions;
+ this.componentCreatorImplementationFactory = componentCreatorImplementationFactory;
+ this.typeProtoConverter = typeProtoConverter;
+ this.keyFactory = keyFactory;
+ }
+
+ /** Creates a new {@link ComponentImplementation} from a compiled component. */
+ ComponentImplementation create(ComponentDescriptor component, TypeElement generatedComponent) {
+ Optional<ComponentImplementation> superclassImplementation =
+ deserializedSuperclassImplementation(
+ component, MoreTypes.asTypeElement(generatedComponent.getSuperclass()));
+
+ ComponentImplementation componentImplementation =
+ ComponentImplementation.forDeserializedComponent(
+ component,
+ ClassName.get(generatedComponent),
+ generatedComponent.getNestingKind(),
+ superclassImplementation,
+ compilerOptions);
+
+ componentImplementation.setCreatorImplementation(
+ superclassImplementation.isPresent()
+ ? Optional.empty()
+ : componentCreatorImplementationFactory.create(
+ componentImplementation, Optional.empty()));
+
+ // TODO(b/117833324): Consider omitting superclass implementations, so that only one instance of
+ // ComponentImplementation needs to be created (in most cases, we don't care about nested levels
+ // of superclass implementations, except for the base implementation). If that's possible, use
+ // getLocalAndInheritedMethods instead of getEnclosedElements() here.
+ for (ExecutableElement method : methodsIn(generatedComponent.getEnclosedElements())) {
+ getAnnotationMirror(method, ModifiableBinding.class)
+ .asSet()
+ .forEach(
+ annotation ->
+ addModifiableBindingMethod(componentImplementation, method, annotation));
+
+ getAnnotationMirror(method, ModifiableModule.class)
+ .asSet()
+ .forEach(
+ annotation -> addModifiableModuleMethod(componentImplementation, method, annotation));
+
+ getAnnotationMirror(method, ConfigureInitializationParameters.class)
+ .asSet()
+ .forEach(
+ annotation ->
+ setConfigureInitializationMethod(componentImplementation, method, annotation));
+ }
+
+ for (TypeElement nestedType : typesIn(generatedComponent.getEnclosedElements())) {
+ addChildImplementation(component, componentImplementation, nestedType);
+ }
+
+ return componentImplementation;
+ }
+
+ private Optional<ComponentImplementation> deserializedSuperclassImplementation(
+ ComponentDescriptor component, TypeElement superclassElement) {
+ return isAnnotationPresent(superclassElement, ComponentDefinitionType.class)
+ ? Optional.of(create(component, superclassElement))
+ : Optional.empty();
+ }
+
+ private void addModifiableBindingMethod(
+ ComponentImplementation componentImplementation,
+ ExecutableElement method,
+ AnnotationMirror metadataAnnotation) {
+ ModifiableBindingType modifiableBindingType =
+ ModifiableBindingType.valueOf(
+ getAnnotationValue(metadataAnnotation, "modifiableBindingType").getValue().toString());
+
+ BindingRequest request =
+ parseBindingRequest(getAnnotationValue(metadataAnnotation, "bindingRequest"));
+
+ ImmutableList<Key> multibindingContributions =
+ asAnnotationValues(getAnnotationValue(metadataAnnotation, "multibindingContributions"))
+ .stream()
+ .map(this::parseKey)
+ .collect(toImmutableList());
+
+ componentImplementation.addModifiableBindingMethod(
+ modifiableBindingType,
+ request,
+ method.getReturnType(),
+ methodDeclaration(method),
+ method.getModifiers().contains(FINAL));
+ componentImplementation.registerImplementedMultibindingKeys(request, multibindingContributions);
+ }
+
+ private BindingRequest fromProto(BindingRequestProto bindingRequest) {
+ Key key = keyFactory.fromProto(bindingRequest.getKey());
+ return bindingRequest.getFrameworkType().equals(FrameworkTypeWrapper.FrameworkType.UNKNOWN)
+ ? bindingRequest(key, RequestKind.valueOf(bindingRequest.getRequestKind().name()))
+ : bindingRequest(key, FrameworkType.valueOf(bindingRequest.getFrameworkType().name()));
+ }
+
+ /**
+ * Returns a {@link MethodSpec} for a {@link
+ * dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod}. The method contents
+ * are not relevant since this represents a method that has already been compiled.
+ *
+ * <p>Ideally this could be {@code MethodSpec.overriding(method).build()}, but that doesn't work
+ * for {@code final} methods
+ */
+ private MethodSpec methodDeclaration(ExecutableElement method) {
+ return methodBuilder(method.getSimpleName().toString())
+ .addModifiers(method.getModifiers())
+ .returns(TypeName.get(method.getReturnType()))
+ .build();
+ }
+
+ private void addModifiableModuleMethod(
+ ComponentImplementation componentImplementation,
+ ExecutableElement method,
+ AnnotationMirror metadataAnnotation) {
+ ComponentRequirement moduleRequirement =
+ parseComponentRequirement(getAnnotationValue(metadataAnnotation, "value"));
+ componentImplementation.registerModifiableModuleMethod(
+ moduleRequirement, method.getSimpleName().toString());
+ }
+
+ private void setConfigureInitializationMethod(
+ ComponentImplementation componentImplementation,
+ ExecutableElement method,
+ AnnotationMirror metadataAnnotation) {
+ ImmutableSet<ComponentRequirement> parameters =
+ asAnnotationValues(getAnnotationValue(metadataAnnotation, "value")).stream()
+ .map(this::parseComponentRequirement)
+ .collect(toImmutableSet());
+
+ componentImplementation.setConfigureInitializationMethod(
+ ConfigureInitializationMethod.create(MethodSpec.overriding(method).build(), parameters));
+ }
+
+ private void addChildImplementation(
+ ComponentDescriptor component,
+ ComponentImplementation componentImplementation,
+ TypeElement nestedType) {
+ getAnnotationMirror(nestedType, ComponentDefinitionType.class)
+ .transform(annotation -> (TypeMirror) getAnnotationValue(annotation, "value").getValue())
+ .transform(MoreTypes::asTypeElement)
+ .asSet()
+ .forEach(
+ componentDefinitionType -> {
+ ComponentDescriptor child =
+ component.childComponentsByElement().get(componentDefinitionType);
+ componentImplementation.addChild(child, create(child, nestedType));
+ });
+ }
+
+ private Key parseKey(AnnotationValue annotationValue) {
+ return keyFactory.fromProto(
+ fromAnnotationValue(annotationValue, KeyProto.getDefaultInstance()));
+ }
+
+ private BindingRequest parseBindingRequest(AnnotationValue annotationValue) {
+ return fromProto(
+ fromAnnotationValue(annotationValue, BindingRequestProto.getDefaultInstance()));
+ }
+
+ private ComponentRequirement parseComponentRequirement(AnnotationValue annotationValue) {
+ return fromProto(
+ fromAnnotationValue(annotationValue, ComponentRequirementProto.getDefaultInstance()));
+ }
+
+ private ComponentRequirement fromProto(ComponentRequirementProto proto) {
+ switch (proto.getRequirementCase()) {
+ case MODULE:
+ return ComponentRequirement.forModule(typeProtoConverter.fromProto(proto.getModule()));
+ case DEPENDENCY:
+ return ComponentRequirement.forDependency(
+ typeProtoConverter.fromProto(proto.getDependency()));
+ case BOUND_INSTANCE:
+ return ComponentRequirement.forBoundInstance(
+ keyFactory.fromProto(proto.getBoundInstance().getKey()),
+ proto.getBoundInstance().getNullable(),
+ proto.getBoundInstance().getVariableName());
+ case REQUIREMENT_NOT_SET:
+ // fall through
+ }
+ throw new AssertionError(proto);
+ }
+}
diff --git a/java/dagger/internal/codegen/DiagnosticReporterFactory.java b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
index ada013b..f657cee 100644
--- a/java/dagger/internal/codegen/DiagnosticReporterFactory.java
+++ b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
@@ -24,17 +24,16 @@
import static com.google.common.collect.Iterables.indexOf;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.asList;
-import static dagger.internal.codegen.DaggerElements.DECLARATION_ORDER;
-import static dagger.internal.codegen.DaggerElements.closestEnclosingTypeElement;
-import static dagger.internal.codegen.DaggerElements.elementEncloses;
-import static dagger.internal.codegen.DaggerElements.elementFormatter;
-import static dagger.internal.codegen.DaggerElements.elementToString;
import static dagger.internal.codegen.DaggerGraphs.shortestPath;
import static dagger.internal.codegen.DaggerStreams.instancesOf;
import static dagger.internal.codegen.DaggerStreams.presentValues;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
+import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
+import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
import static java.util.Collections.min;
import static java.util.Comparator.comparing;
import static java.util.Comparator.comparingInt;
@@ -50,6 +49,7 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Table;
import com.google.errorprone.annotations.FormatMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingGraph;
import dagger.model.BindingGraph.ChildFactoryMethodEdge;
import dagger.model.BindingGraph.ComponentNode;
@@ -77,6 +77,7 @@
private final DaggerTypes types;
private final Messager messager;
private final DependencyRequestFormatter dependencyRequestFormatter;
+ private final ElementFormatter elementFormatter;
private final CompilerOptions compilerOptions;
@Inject
@@ -84,10 +85,12 @@
DaggerTypes types,
Messager messager,
DependencyRequestFormatter dependencyRequestFormatter,
+ ElementFormatter elementFormatter,
CompilerOptions compilerOptions) {
this.types = types;
this.messager = messager;
this.dependencyRequestFormatter = dependencyRequestFormatter;
+ this.elementFormatter = elementFormatter;
this.compilerOptions = compilerOptions;
}
@@ -233,12 +236,14 @@
Diagnostic.Kind diagnosticKind,
CharSequence message,
@NullableDecl Element elementToReport) {
- if (graph.isModuleBindingGraph()) {
- if (compilerOptions.moduleBindingValidationType().equals(NONE)) {
+ if (graph.isFullBindingGraph()) {
+ ValidationType validationType =
+ compilerOptions.fullBindingGraphValidationType(rootComponent);
+ if (validationType.equals(NONE)) {
return;
}
if (diagnosticKind.equals(ERROR)) {
- diagnosticKind = compilerOptions.moduleBindingValidationType().diagnosticKind().get();
+ diagnosticKind = validationType.diagnosticKind().get();
}
}
reportedDiagnosticKinds.add(diagnosticKind);
@@ -296,12 +301,12 @@
@Override
public String toString() {
StringBuilder message =
- graph.isModuleBindingGraph()
+ graph.isFullBindingGraph()
? new StringBuilder()
: new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
- // Print the dependency trace unless it's a module binding graph
- if (!graph.isModuleBindingGraph()) {
+ // Print the dependency trace unless it's a full binding graph
+ if (!graph.isFullBindingGraph()) {
dependencyTrace.forEach(
edge ->
dependencyRequestFormatter.appendFormatLine(message, edge.dependencyRequest()));
@@ -316,7 +321,7 @@
// if printing entry points, skip entry points and the traced request
.filter(
request ->
- graph.isModuleBindingGraph()
+ graph.isFullBindingGraph()
|| (!request.isEntryPoint() && !isTracedRequest(request)))
.map(request -> request.dependencyRequest().requestElement())
.flatMap(presentValues())
@@ -324,14 +329,14 @@
if (!requestsToPrint.isEmpty()) {
message
.append("\nIt is")
- .append(graph.isModuleBindingGraph() ? " " : " also ")
+ .append(graph.isFullBindingGraph() ? " " : " also ")
.append("requested at:");
- elementFormatter().formatIndentedList(message, requestsToPrint, 1);
+ elementFormatter.formatIndentedList(message, requestsToPrint, 1);
}
- // Print the remaining entry points, showing which component they're in, unless we're in a
- // module binding graph
- if (!graph.isModuleBindingGraph() && entryPoints.size() > 1) {
+ // Print the remaining entry points, showing which component they're in, unless it's a full
+ // binding graph
+ if (!graph.isFullBindingGraph() && entryPoints.size() > 1) {
message.append("\nThe following other entry points also depend on it:");
entryPointFormatter.formatIndentedList(
message,
diff --git a/java/dagger/internal/codegen/DuplicateBindingsValidator.java b/java/dagger/internal/codegen/DuplicateBindingsValidator.java
index c1515e5..3eed45f 100644
--- a/java/dagger/internal/codegen/DuplicateBindingsValidator.java
+++ b/java/dagger/internal/codegen/DuplicateBindingsValidator.java
@@ -206,7 +206,7 @@
.append(formatWithComponentPath(explicitBinding))
.append(
"\nThis condition was never validated before, and will soon be an error. "
- + "See https://google.github.io/dagger/conflicting-inject.");
+ + "See https://dagger.dev/conflicting-inject.");
diagnosticReporter.reportBinding(diagnosticKind, explicitBinding, message.toString());
}
diff --git a/java/dagger/internal/codegen/ElementFormatter.java b/java/dagger/internal/codegen/ElementFormatter.java
new file mode 100644
index 0000000..40d7606
--- /dev/null
+++ b/java/dagger/internal/codegen/ElementFormatter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.auto.common.MoreElements.asExecutable;
+import static java.util.stream.Collectors.joining;
+
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/**
+ * Formats elements into a useful string representation.
+ *
+ * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
+ *
+ * <p>Parameters are given with their enclosing executable, with other parameters elided.
+ */
+final class ElementFormatter extends Formatter<Element> {
+ @Inject
+ ElementFormatter() {}
+
+ @Override
+ public String format(Element element) {
+ return elementToString(element);
+ }
+
+ /**
+ * Returns a useful string form for an element.
+ *
+ * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
+ *
+ * <p>Parameters are given with their enclosing executable, with other parameters elided.
+ */
+ static String elementToString(Element element) {
+ return element.accept(ELEMENT_TO_STRING, null);
+ }
+
+ private static final ElementVisitor<String, Void> ELEMENT_TO_STRING =
+ new ElementKindVisitor8<String, Void>() {
+ @Override
+ public String visitExecutable(ExecutableElement executableElement, Void aVoid) {
+ return enclosingTypeAndMemberName(executableElement)
+ .append(
+ executableElement.getParameters().stream()
+ .map(parameter -> parameter.asType().toString())
+ .collect(joining(", ", "(", ")")))
+ .toString();
+ }
+
+ @Override
+ public String visitVariableAsParameter(VariableElement parameter, Void aVoid) {
+ ExecutableElement methodOrConstructor = asExecutable(parameter.getEnclosingElement());
+ return enclosingTypeAndMemberName(methodOrConstructor)
+ .append('(')
+ .append(
+ formatArgumentInList(
+ methodOrConstructor.getParameters().indexOf(parameter),
+ methodOrConstructor.getParameters().size(),
+ parameter.getSimpleName()))
+ .append(')')
+ .toString();
+ }
+
+ @Override
+ public String visitVariableAsField(VariableElement field, Void aVoid) {
+ return enclosingTypeAndMemberName(field).toString();
+ }
+
+ @Override
+ public String visitType(TypeElement type, Void aVoid) {
+ return type.getQualifiedName().toString();
+ }
+
+ @Override
+ protected String defaultAction(Element element, Void aVoid) {
+ throw new UnsupportedOperationException(
+ "Can't determine string for " + element.getKind() + " element " + element);
+ }
+
+ private StringBuilder enclosingTypeAndMemberName(Element element) {
+ StringBuilder name = new StringBuilder(element.getEnclosingElement().accept(this, null));
+ if (!element.getSimpleName().contentEquals("<init>")) {
+ name.append('.').append(element.getSimpleName());
+ }
+ return name;
+ }
+ };
+}
diff --git a/java/dagger/internal/codegen/FactoryGenerator.java b/java/dagger/internal/codegen/FactoryGenerator.java
index 3961311..d367bc5 100644
--- a/java/dagger/internal/codegen/FactoryGenerator.java
+++ b/java/dagger/internal/codegen/FactoryGenerator.java
@@ -17,13 +17,10 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Maps.transformValues;
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.DELEGATE;
import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
@@ -33,7 +30,11 @@
import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.TypeNames.factoryOf;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.factoryOf;
import static dagger.model.BindingKind.PROVISION;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
@@ -54,6 +55,9 @@
import dagger.internal.Preconditions;
import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
import dagger.internal.codegen.InjectionMethods.ProvisionMethod;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.List;
import java.util.Optional;
@@ -161,15 +165,13 @@
if (binding.requiresModuleInstance()) {
uniqueFieldNames.claim("module");
}
- ImmutableMap.Builder<Key, FieldSpec> fields = ImmutableMap.builder();
- generateBindingFieldsForDependencies(binding)
- .forEach(
- (key, frameworkField) -> {
- TypeName type = frameworkField.type();
- String name = uniqueFieldNames.getUniqueName(frameworkField.name());
- fields.put(key, FieldSpec.builder(type, name, PRIVATE, FINAL).build());
- });
- return fields.build();
+ return ImmutableMap.copyOf(
+ transformValues(
+ generateBindingFieldsForDependencies(binding),
+ field ->
+ FieldSpec.builder(
+ field.type(), uniqueFieldNames.getUniqueName(field.name()), PRIVATE, FINAL)
+ .build()));
}
private void addCreateMethod(ProvisionBinding binding, TypeSpec.Builder factoryBuilder) {
diff --git a/java/dagger/internal/codegen/ForwardingCompilerOptions.java b/java/dagger/internal/codegen/ForwardingCompilerOptions.java
new file mode 100644
index 0000000..4a1deda
--- /dev/null
+++ b/java/dagger/internal/codegen/ForwardingCompilerOptions.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+/** A {@link CompilerOptions} object that delegates to another one. */
+class ForwardingCompilerOptions extends CompilerOptions {
+
+ private final CompilerOptions delegate;
+
+ ForwardingCompilerOptions(CompilerOptions delegate) {
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ boolean usesProducers() {
+ return delegate.usesProducers();
+ }
+
+ @Override
+ boolean fastInit() {
+ return delegate.fastInit();
+ }
+
+ @Override
+ boolean formatGeneratedSource() {
+ return delegate.formatGeneratedSource();
+ }
+
+ @Override
+ boolean writeProducerNameInToken() {
+ return delegate.writeProducerNameInToken();
+ }
+
+ @Override
+ Diagnostic.Kind nullableValidationKind() {
+ return delegate.nullableValidationKind();
+ }
+
+ @Override
+ Diagnostic.Kind privateMemberValidationKind() {
+ return delegate.privateMemberValidationKind();
+ }
+
+ @Override
+ Diagnostic.Kind staticMemberValidationKind() {
+ return delegate.staticMemberValidationKind();
+ }
+
+ @Override
+ boolean ignorePrivateAndStaticInjectionForComponent() {
+ return delegate.ignorePrivateAndStaticInjectionForComponent();
+ }
+
+ @Override
+ ValidationType scopeCycleValidationType() {
+ return delegate.scopeCycleValidationType();
+ }
+
+ @Override
+ boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+ return delegate.warnIfInjectionFactoryNotGeneratedUpstream();
+ }
+
+ @Override
+ boolean headerCompilation() {
+ return delegate.headerCompilation();
+ }
+
+ @Override
+ boolean aheadOfTimeSubcomponents() {
+ return delegate.aheadOfTimeSubcomponents();
+ }
+
+ @Override
+ boolean forceUseSerializedComponentImplementations() {
+ return delegate.forceUseSerializedComponentImplementations();
+ }
+
+ @Override
+ boolean emitModifiableMetadataAnnotations() {
+ return delegate.emitModifiableMetadataAnnotations();
+ }
+
+ @Override
+ boolean useGradleIncrementalProcessing() {
+ return delegate.useGradleIncrementalProcessing();
+ }
+
+ @Override
+ ValidationType fullBindingGraphValidationType(TypeElement element) {
+ return delegate.fullBindingGraphValidationType(element);
+ }
+
+ @Override
+ Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+ return delegate.moduleHasDifferentScopesDiagnosticKind();
+ }
+
+ @Override
+ ValidationType explicitBindingConflictsWithInjectValidationType() {
+ return delegate.explicitBindingConflictsWithInjectValidationType();
+ }
+}
diff --git a/java/dagger/internal/codegen/FrameworkFieldInitializer.java b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
index b69e3b2..a3de083 100644
--- a/java/dagger/internal/codegen/FrameworkFieldInitializer.java
+++ b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
@@ -17,8 +17,8 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.FRAMEWORK_FIELD;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
import static javax.lang.model.element.Modifier.PRIVATE;
import com.squareup.javapoet.ClassName;
@@ -26,6 +26,8 @@
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.TypeName;
import dagger.internal.DelegateFactory;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.TypeNames;
import dagger.producers.internal.DelegateProducer;
import java.util.Optional;
@@ -121,9 +123,6 @@
case DELEGATED:
case INITIALIZED:
break;
-
- default:
- throw new AssertionError("Unhandled initialization state: " + fieldInitializationState);
}
}
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
index 870aef9..6f62d66 100644
--- a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -17,11 +17,14 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/FrameworkType.java b/java/dagger/internal/codegen/FrameworkType.java
index 0e279fc..f4e3779 100644
--- a/java/dagger/internal/codegen/FrameworkType.java
+++ b/java/dagger/internal/codegen/FrameworkType.java
@@ -29,6 +29,8 @@
import dagger.Lazy;
import dagger.internal.DoubleCheck;
import dagger.internal.ProviderOfLazy;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.RequestKind;
import dagger.producers.Produced;
diff --git a/java/dagger/internal/codegen/GenerationOptionsModule.java b/java/dagger/internal/codegen/GenerationOptionsModule.java
index 9820d4f..aa3c461 100644
--- a/java/dagger/internal/codegen/GenerationOptionsModule.java
+++ b/java/dagger/internal/codegen/GenerationOptionsModule.java
@@ -19,6 +19,7 @@
import dagger.Module;
import dagger.Provides;
import dagger.internal.GenerationOptions;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Optional;
/** Adds bindings for serializing and rereading {@link GenerationOptions}. */
diff --git a/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java b/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java
index d4e0820..69b107c 100644
--- a/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java
+++ b/java/dagger/internal/codegen/ImmediateFutureBindingExpression.java
@@ -23,21 +23,27 @@
import com.google.common.util.concurrent.ListenableFuture;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import dagger.model.RequestKind;
+import javax.lang.model.SourceVersion;
final class ImmediateFutureBindingExpression extends BindingExpression {
private final ComponentBindingExpressions componentBindingExpressions;
private final DaggerTypes types;
+ private final SourceVersion sourceVersion;
private final Key key;
ImmediateFutureBindingExpression(
ResolvedBindings resolvedBindings,
ComponentBindingExpressions componentBindingExpressions,
- DaggerTypes types) {
+ DaggerTypes types,
+ SourceVersion sourceVersion) {
this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
this.types = checkNotNull(types);
+ this.sourceVersion = checkNotNull(sourceVersion);
this.key = resolvedBindings.key();
}
@@ -52,14 +58,16 @@
Expression expression =
componentBindingExpressions.getDependencyExpression(
bindingRequest(key, RequestKind.INSTANCE), requestingClass);
- // Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
- // cast.
- //
- // For example, javac7 cannot detect that Futures.immediateFuture(ImmutableSet.of("T"))
- // can safely be assigned to ListenableFuture<Set<T>>.
- if (!types.isSameType(expression.type(), key.type())) {
- return CodeBlock.of(
- "($T) $L", types.accessibleType(key.type(), requestingClass), expression.codeBlock());
+ if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+ // Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
+ // cast.
+ //
+ // For example, javac7 cannot detect that Futures.immediateFuture(ImmutableSet.of("T"))
+ // can safely be assigned to ListenableFuture<Set<T>>.
+ if (!types.isSameType(expression.type(), key.type())) {
+ return CodeBlock.of(
+ "($T) $L", types.accessibleType(key.type(), requestingClass), expression.codeBlock());
+ }
}
return expression.codeBlock();
}
diff --git a/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java b/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java
index 878c4ec..19c4d19 100644
--- a/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java
+++ b/java/dagger/internal/codegen/InaccessibleMapKeyProxyGenerator.java
@@ -24,6 +24,8 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
import javax.annotation.processing.Filer;
import javax.inject.Inject;
diff --git a/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java b/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java
index 7bbbd07..d649e46 100644
--- a/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java
+++ b/java/dagger/internal/codegen/IncompatiblyScopedBindingsValidator.java
@@ -16,9 +16,9 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.closestEnclosingTypeElement;
import static dagger.internal.codegen.Formatter.INDENT;
import static dagger.internal.codegen.Scopes.getReadableSource;
+import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
import static dagger.model.BindingKind.INJECTION;
import static java.util.stream.Collectors.joining;
import static javax.tools.Diagnostic.Kind.ERROR;
@@ -70,9 +70,11 @@
ComponentNode componentNode =
bindingGraph.componentNode(binding.componentPath()).get();
if (!componentNode.scopes().contains(scope)) {
- // @Inject bindings in full binding graphs will appear at the properly scoped
- // ancestor component, so ignore them here.
- if (binding.kind().equals(INJECTION) && bindingGraph.isFullBindingGraph()) {
+ // @Inject bindings in module or subcomponent binding graphs will appear at the
+ // properly scoped ancestor component, so ignore them here.
+ if (binding.kind().equals(INJECTION)
+ && (bindingGraph.rootComponentNode().isSubcomponent()
+ || !bindingGraph.rootComponentNode().isRealComponent())) {
return;
}
incompatibleBindings.put(componentNode, binding);
diff --git a/java/dagger/internal/codegen/InjectBindingRegistryImpl.java b/java/dagger/internal/codegen/InjectBindingRegistryImpl.java
index 3771a8e..45dc391 100644
--- a/java/dagger/internal/codegen/InjectBindingRegistryImpl.java
+++ b/java/dagger/internal/codegen/InjectBindingRegistryImpl.java
@@ -35,6 +35,8 @@
import dagger.Component;
import dagger.MembersInjector;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.ArrayDeque;
import java.util.Deque;
diff --git a/java/dagger/internal/codegen/InjectValidator.java b/java/dagger/internal/codegen/InjectValidator.java
index 949d0c5..d3c4ce8 100644
--- a/java/dagger/internal/codegen/InjectValidator.java
+++ b/java/dagger/internal/codegen/InjectValidator.java
@@ -29,7 +29,9 @@
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.ValidationReport.Builder;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Scope;
import java.util.Optional;
import java.util.Set;
@@ -307,7 +309,8 @@
return false;
}
- private void checkInjectIntoPrivateClass(Element element, Builder<TypeElement> builder) {
+ private void checkInjectIntoPrivateClass(
+ Element element, ValidationReport.Builder<TypeElement> builder) {
if (!Accessibility.isElementAccessibleFromOwnPackage(
DaggerElements.closestEnclosingTypeElement(element))) {
builder.addItem(
diff --git a/java/dagger/internal/codegen/InjectionMethod.java b/java/dagger/internal/codegen/InjectionMethod.java
index b739088..2785b18 100644
--- a/java/dagger/internal/codegen/InjectionMethod.java
+++ b/java/dagger/internal/codegen/InjectionMethod.java
@@ -18,8 +18,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.Accessibility.isRawTypePubliclyAccessible;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
@@ -34,6 +34,8 @@
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.List;
import java.util.Optional;
import javax.lang.model.element.ExecutableElement;
diff --git a/java/dagger/internal/codegen/InjectionMethods.java b/java/dagger/internal/codegen/InjectionMethods.java
index e0fecc0..d61aaa5 100644
--- a/java/dagger/internal/codegen/InjectionMethods.java
+++ b/java/dagger/internal/codegen/InjectionMethods.java
@@ -19,18 +19,18 @@
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.UPPER_CAMEL;
import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.Accessibility.isElementAccessibleFrom;
-import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.Accessibility.isRawTypePubliclyAccessible;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.CodeBlocks.toConcatenatedCodeBlock;
import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.FactoryGenerator.checkNotNullProvidesMethod;
import static dagger.internal.codegen.RequestKinds.requestTypeName;
import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.TypeNames.rawTypeName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toConcatenatedCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
+import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isRawTypePubliclyAccessible;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.STATIC;
import static javax.lang.model.type.TypeKind.VOID;
@@ -43,6 +43,9 @@
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import dagger.model.RequestKind;
import java.util.ArrayList;
@@ -261,9 +264,8 @@
MoreElements.asVariable(injectionSite.element()),
methodName,
elements);
- default:
- throw new AssertionError(injectionSite);
}
+ throw new AssertionError(injectionSite);
}
/**
@@ -513,7 +515,7 @@
injectionMethod
.methodBodyBuilder()
.add(checkNotNullPolicy.checkForNull(proxyInvocation.build()))
- .add(";");
+ .add(";\n");
return injectionMethod.build();
}
diff --git a/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
index fdb225f..2d2e8cb 100644
--- a/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
@@ -22,6 +22,7 @@
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.CodeBlocks;
import javax.inject.Provider;
/**
diff --git a/java/dagger/internal/codegen/InjectionSiteFactory.java b/java/dagger/internal/codegen/InjectionSiteFactory.java
new file mode 100644
index 0000000..d09f91d
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionSiteFactory.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2017 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.auto.common.MoreElements.isAnnotationPresent;
+import static dagger.internal.codegen.MembersInjectionBinding.InjectionSite.Kind.METHOD;
+import static dagger.internal.codegen.langmodel.DaggerElements.DECLARATION_ORDER;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.SetMultimap;
+import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementKindVisitor8;
+
+/** A factory for {@link Binding} objects. */
+final class InjectionSiteFactory {
+ private final ElementVisitor<Optional<InjectionSite>, DeclaredType> injectionSiteVisitor =
+ new ElementKindVisitor8<Optional<InjectionSite>, DeclaredType>(Optional.empty()) {
+ @Override
+ public Optional<InjectionSite> visitExecutableAsMethod(
+ ExecutableElement method, DeclaredType type) {
+ ExecutableType resolved = MoreTypes.asExecutable(types.asMemberOf(type, method));
+ return Optional.of(
+ InjectionSite.method(
+ method,
+ dependencyRequestFactory.forRequiredResolvedVariables(
+ method.getParameters(), resolved.getParameterTypes())));
+ }
+
+ @Override
+ public Optional<InjectionSite> visitVariableAsField(
+ VariableElement field, DeclaredType type) {
+ if (!isAnnotationPresent(field, Inject.class)
+ || field.getModifiers().contains(PRIVATE)
+ || field.getModifiers().contains(STATIC)) {
+ return Optional.empty();
+ }
+ TypeMirror resolved = types.asMemberOf(type, field);
+ return Optional.of(
+ InjectionSite.field(
+ field, dependencyRequestFactory.forRequiredResolvedVariable(field, resolved)));
+ }
+ };
+
+ private final DaggerTypes types;
+ private final DaggerElements elements;
+ private final DependencyRequestFactory dependencyRequestFactory;
+
+ @Inject
+ InjectionSiteFactory(
+ DaggerTypes types,
+ DaggerElements elements,
+ DependencyRequestFactory dependencyRequestFactory) {
+ this.types = types;
+ this.elements = elements;
+ this.dependencyRequestFactory = dependencyRequestFactory;
+ }
+
+ /** Returns the injection sites for a type. */
+ ImmutableSortedSet<InjectionSite> getInjectionSites(DeclaredType declaredType) {
+ Set<InjectionSite> injectionSites = new HashSet<>();
+ List<TypeElement> ancestors = new ArrayList<>();
+ SetMultimap<String, ExecutableElement> overriddenMethodMap = LinkedHashMultimap.create();
+ for (Optional<DeclaredType> currentType = Optional.of(declaredType);
+ currentType.isPresent();
+ currentType = types.nonObjectSuperclass(currentType.get())) {
+ DeclaredType type = currentType.get();
+ ancestors.add(MoreElements.asType(type.asElement()));
+ for (Element enclosedElement : type.asElement().getEnclosedElements()) {
+ Optional<InjectionSite> maybeInjectionSite =
+ injectionSiteVisitor.visit(enclosedElement, type);
+ if (maybeInjectionSite.isPresent()) {
+ InjectionSite injectionSite = maybeInjectionSite.get();
+ if (shouldBeInjected(injectionSite.element(), overriddenMethodMap)) {
+ injectionSites.add(injectionSite);
+ }
+ if (injectionSite.kind().equals(METHOD)) {
+ ExecutableElement injectionSiteMethod =
+ MoreElements.asExecutable(injectionSite.element());
+ overriddenMethodMap.put(
+ injectionSiteMethod.getSimpleName().toString(), injectionSiteMethod);
+ }
+ }
+ }
+ }
+ return ImmutableSortedSet.copyOf(
+ // supertypes before subtypes
+ Comparator.comparing(
+ (InjectionSite injectionSite) ->
+ ancestors.indexOf(injectionSite.element().getEnclosingElement()))
+ .reversed()
+ // fields before methods
+ .thenComparing(injectionSite -> injectionSite.element().getKind())
+ // then sort by whichever element comes first in the parent
+ // this isn't necessary, but makes the processor nice and predictable
+ .thenComparing(InjectionSite::element, DECLARATION_ORDER),
+ injectionSites);
+ }
+
+ private boolean shouldBeInjected(
+ Element injectionSite, SetMultimap<String, ExecutableElement> overriddenMethodMap) {
+ if (!isAnnotationPresent(injectionSite, Inject.class)
+ || injectionSite.getModifiers().contains(PRIVATE)
+ || injectionSite.getModifiers().contains(STATIC)) {
+ return false;
+ }
+
+ if (injectionSite.getKind().isField()) { // Inject all fields (self and ancestors)
+ return true;
+ }
+
+ // For each method with the same name belonging to any descendant class, return false if any
+ // method has already overridden the injectionSite method. To decrease the number of methods
+ // that are checked, we store the already injected methods in a SetMultimap and only
+ // check the methods with the same name.
+ ExecutableElement injectionSiteMethod = MoreElements.asExecutable(injectionSite);
+ TypeElement injectionSiteType = MoreElements.asType(injectionSite.getEnclosingElement());
+ for (ExecutableElement method :
+ overriddenMethodMap.get(injectionSiteMethod.getSimpleName().toString())) {
+ if (elements.overrides(method, injectionSiteMethod, injectionSiteType)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/java/dagger/internal/codegen/InnerSwitchingProviders.java b/java/dagger/internal/codegen/InnerSwitchingProviders.java
index 91c1317..74c4366 100644
--- a/java/dagger/internal/codegen/InnerSwitchingProviders.java
+++ b/java/dagger/internal/codegen/InnerSwitchingProviders.java
@@ -26,6 +26,8 @@
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import javax.inject.Provider;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/JavacPluginModule.java b/java/dagger/internal/codegen/JavacPluginModule.java
index 44f11fd..bc5b66e 100644
--- a/java/dagger/internal/codegen/JavacPluginModule.java
+++ b/java/dagger/internal/codegen/JavacPluginModule.java
@@ -25,11 +25,14 @@
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.annotation.processing.Messager;
import javax.inject.Inject;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
@@ -41,21 +44,97 @@
abstract class JavacPluginModule {
@Provides
static CompilerOptions compilerOptions() {
- return CompilerOptions.builder()
- .usesProducers(true)
- .writeProducerNameInToken(true)
- .nullableValidationKind(NOTE)
- .privateMemberValidationKind(NOTE)
- .staticMemberValidationKind(NOTE)
- .ignorePrivateAndStaticInjectionForComponent(false)
- .scopeCycleValidationType(NONE)
- .warnIfInjectionFactoryNotGeneratedUpstream(false)
- .fastInit(false)
- .aheadOfTimeSubcomponents(false)
- .moduleBindingValidationType(NONE)
- .moduleHasDifferentScopesDiagnosticKind(NOTE)
- .explicitBindingConflictsWithInjectValidationType(NONE)
- .build();
+ return new CompilerOptions() {
+ @Override
+ boolean usesProducers() {
+ return true;
+ }
+
+ @Override
+ boolean fastInit() {
+ return false;
+ }
+
+ @Override
+ boolean formatGeneratedSource() {
+ return false;
+ }
+
+ @Override
+ boolean writeProducerNameInToken() {
+ return true;
+ }
+
+ @Override
+ Diagnostic.Kind nullableValidationKind() {
+ return NOTE;
+ }
+
+ @Override
+ Diagnostic.Kind privateMemberValidationKind() {
+ return NOTE;
+ }
+
+ @Override
+ Diagnostic.Kind staticMemberValidationKind() {
+ return NOTE;
+ }
+
+ @Override
+ boolean ignorePrivateAndStaticInjectionForComponent() {
+ return false;
+ }
+
+ @Override
+ ValidationType scopeCycleValidationType() {
+ return NONE;
+ }
+
+ @Override
+ boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+ return false;
+ }
+
+ @Override
+ boolean headerCompilation() {
+ return false;
+ }
+
+ @Override
+ boolean aheadOfTimeSubcomponents() {
+ return false;
+ }
+
+ @Override
+ boolean forceUseSerializedComponentImplementations() {
+ return false;
+ }
+
+ @Override
+ boolean emitModifiableMetadataAnnotations() {
+ return false;
+ }
+
+ @Override
+ boolean useGradleIncrementalProcessing() {
+ return false;
+ }
+
+ @Override
+ ValidationType fullBindingGraphValidationType(TypeElement element) {
+ return NONE;
+ }
+
+ @Override
+ Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+ return NOTE;
+ }
+
+ @Override
+ ValidationType explicitBindingConflictsWithInjectValidationType() {
+ return NONE;
+ }
+ };
}
@Binds
diff --git a/java/dagger/internal/codegen/KeyFactory.java b/java/dagger/internal/codegen/KeyFactory.java
index 633c306..b6ac27f 100644
--- a/java/dagger/internal/codegen/KeyFactory.java
+++ b/java/dagger/internal/codegen/KeyFactory.java
@@ -23,13 +23,13 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.DaggerTypes.isFutureType;
import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
import static dagger.internal.codegen.MapKeys.getMapKey;
import static dagger.internal.codegen.MapKeys.mapKeyType;
import static dagger.internal.codegen.Optionals.firstPresent;
import static dagger.internal.codegen.RequestKinds.extractKeyType;
import static dagger.internal.codegen.RequestKinds.getRequestKind;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
import static java.util.Arrays.asList;
import static javax.lang.model.element.ElementKind.METHOD;
@@ -37,6 +37,9 @@
import com.google.common.collect.ImmutableSet;
import dagger.Binds;
import dagger.BindsOptionalOf;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.KeyProto;
import dagger.model.Key;
import dagger.model.Key.MultibindingContributionIdentifier;
import dagger.model.RequestKind;
@@ -65,11 +68,19 @@
final class KeyFactory {
private final DaggerTypes types;
private final DaggerElements elements;
+ private final TypeProtoConverter typeProtoConverter;
+ private final AnnotationProtoConverter annotationProtoConverter;
@Inject
- KeyFactory(DaggerTypes types, DaggerElements elements) {
+ KeyFactory(
+ DaggerTypes types,
+ DaggerElements elements,
+ TypeProtoConverter typeProtoConverter,
+ AnnotationProtoConverter annotationProtoConverter) {
this.types = checkNotNull(types);
this.elements = checkNotNull(elements);
+ this.typeProtoConverter = typeProtoConverter;
+ this.annotationProtoConverter = annotationProtoConverter;
}
private TypeMirror boxPrimitives(TypeMirror type) {
@@ -148,7 +159,7 @@
ExecutableType methodType =
MoreTypes.asExecutable(
types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), method));
- ContributionType contributionType = ContributionType.fromBindingMethod(method);
+ ContributionType contributionType = ContributionType.fromBindingElement(method);
TypeMirror returnType = methodType.getReturnType();
if (frameworkType.isPresent()
&& frameworkType.get().equals(elements.getTypeElement(Producer.class))
@@ -213,15 +224,14 @@
// TODO(gak): do we want to allow people to use "covariant return" here?
checkArgument(SetType.isSet(returnType));
return returnType;
- default:
- throw new AssertionError();
}
+ throw new AssertionError();
}
/**
* Returns the key for a binding associated with a {@link DelegateDeclaration}.
*
- * If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map<K, V>} key
+ * <p>If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map<K, V>} key
* from {@link DelegateDeclaration#key()} to {@code Map<K, FrameworkType<V>>}. If {@code
* delegateDeclaration} is not a map contribution, its key is returned.
*/
@@ -424,4 +434,36 @@
.type(extractKeyType(getRequestKind(optionalValueType), optionalValueType))
.build());
}
+
+ /** Translates a {@link Key} to a proto representation. */
+ static KeyProto toProto(Key key) {
+ KeyProto.Builder builder =
+ KeyProto.newBuilder().setType(TypeProtoConverter.toProto(key.type()));
+ key.qualifier().map(AnnotationProtoConverter::toProto).ifPresent(builder::setQualifier);
+ key.multibindingContributionIdentifier()
+ .ifPresent(
+ mci ->
+ builder
+ .getMultibindingContributionIdentifierBuilder()
+ .setModule(mci.module())
+ .setBindingElement(mci.bindingElement()));
+ return builder.build();
+ }
+
+ /** Creates a {@link Key} from its proto representation. */
+ Key fromProto(KeyProto key) {
+ Key.Builder builder = Key.builder(typeProtoConverter.fromProto(key.getType()));
+ if (key.hasQualifier()) {
+ builder.qualifier(annotationProtoConverter.fromProto(key.getQualifier()));
+ }
+ if (key.hasMultibindingContributionIdentifier()) {
+ KeyProto.MultibindingContributionIdentifier multibindingContributionIdentifier =
+ key.getMultibindingContributionIdentifier();
+ builder.multibindingContributionIdentifier(
+ new MultibindingContributionIdentifier(
+ multibindingContributionIdentifier.getBindingElement(),
+ multibindingContributionIdentifier.getModule()));
+ }
+ return builder.build();
+ }
}
diff --git a/java/dagger/internal/codegen/Keys.java b/java/dagger/internal/codegen/Keys.java
index 274d244..670fda7 100644
--- a/java/dagger/internal/codegen/Keys.java
+++ b/java/dagger/internal/codegen/Keys.java
@@ -18,6 +18,7 @@
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.Optional;
import javax.lang.model.element.AnnotationMirror;
diff --git a/java/dagger/internal/codegen/META-INF/gradle/incremental.annotation.processors b/java/dagger/internal/codegen/META-INF/gradle/incremental.annotation.processors
deleted file mode 100644
index db550fe..0000000
--- a/java/dagger/internal/codegen/META-INF/gradle/incremental.annotation.processors
+++ /dev/null
@@ -1 +0,0 @@
-dagger.internal.codegen.ComponentProcessor,dynamic
diff --git a/java/dagger/internal/codegen/MapBindingExpression.java b/java/dagger/internal/codegen/MapBindingExpression.java
index 9d4fdf0..526c493 100644
--- a/java/dagger/internal/codegen/MapBindingExpression.java
+++ b/java/dagger/internal/codegen/MapBindingExpression.java
@@ -18,10 +18,10 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.MapKeys.getMapKeyExpression;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static dagger.model.BindingKind.MULTIBOUND_MAP;
import static javax.lang.model.util.ElementFilter.methodsIn;
@@ -30,6 +30,9 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.MapBuilder;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingKind;
import dagger.model.DependencyRequest;
import java.util.Collections;
diff --git a/java/dagger/internal/codegen/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
index 0fff44b..187b792 100644
--- a/java/dagger/internal/codegen/MapFactoryCreationExpression.java
+++ b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
@@ -20,9 +20,10 @@
import static dagger.internal.codegen.MapKeys.getMapKeyExpression;
import static dagger.internal.codegen.SourceFiles.mapFactoryClassName;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.model.DependencyRequest;
import dagger.producers.Produced;
import dagger.producers.Producer;
import javax.inject.Provider;
@@ -67,19 +68,18 @@
builder.add("<$T, $T>", mapType.keyType(), valueType);
}
- ImmutableList<FrameworkDependency> frameworkDependencies = binding.frameworkDependencies();
- builder.add("builder($L)", frameworkDependencies.size());
+ builder.add("builder($L)", binding.dependencies().size());
superContributions()
.ifPresent(superContributions -> builder.add(".putAll($L)", superContributions));
- for (FrameworkDependency frameworkDependency : frameworkDependenciesToImplement()) {
+ for (DependencyRequest dependency : dependenciesToImplement()) {
ContributionBinding contributionBinding =
- graph.contributionBindings().get(frameworkDependency.key()).contributionBinding();
+ graph.contributionBindings().get(dependency.key()).contributionBinding();
builder.add(
".put($L, $L)",
getMapKeyExpression(contributionBinding, componentImplementation.name(), elements),
- multibindingDependencyExpression(frameworkDependency));
+ multibindingDependencyExpression(dependency));
}
builder.add(".build()");
diff --git a/java/dagger/internal/codegen/MapKeyAccessibility.java b/java/dagger/internal/codegen/MapKeyAccessibility.java
index fe52e3b..ce27877 100644
--- a/java/dagger/internal/codegen/MapKeyAccessibility.java
+++ b/java/dagger/internal/codegen/MapKeyAccessibility.java
@@ -16,8 +16,9 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
+import dagger.internal.codegen.langmodel.Accessibility;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
diff --git a/java/dagger/internal/codegen/MapKeyProcessingStep.java b/java/dagger/internal/codegen/MapKeyProcessingStep.java
index 6e5dc10..19975a7 100644
--- a/java/dagger/internal/codegen/MapKeyProcessingStep.java
+++ b/java/dagger/internal/codegen/MapKeyProcessingStep.java
@@ -23,6 +23,7 @@
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.annotation.processing.Messager;
diff --git a/java/dagger/internal/codegen/MapKeyValidator.java b/java/dagger/internal/codegen/MapKeyValidator.java
index dfc0b07..f2568ef 100644
--- a/java/dagger/internal/codegen/MapKeyValidator.java
+++ b/java/dagger/internal/codegen/MapKeyValidator.java
@@ -19,6 +19,7 @@
import static javax.lang.model.util.ElementFilter.methodsIn;
import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.List;
import javax.inject.Inject;
import javax.lang.model.element.Element;
diff --git a/java/dagger/internal/codegen/MapKeys.java b/java/dagger/internal/codegen/MapKeys.java
index 48fb1e6..d8da6af 100644
--- a/java/dagger/internal/codegen/MapKeys.java
+++ b/java/dagger/internal/codegen/MapKeys.java
@@ -35,6 +35,8 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.NoSuchElementException;
import java.util.Optional;
import javax.lang.model.element.AnnotationMirror;
diff --git a/java/dagger/internal/codegen/MemberSelect.java b/java/dagger/internal/codegen/MemberSelect.java
index 2806207..c42c7c9 100644
--- a/java/dagger/internal/codegen/MemberSelect.java
+++ b/java/dagger/internal/codegen/MemberSelect.java
@@ -17,17 +17,17 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
import static dagger.internal.codegen.SourceFiles.setFactoryClassName;
-import static dagger.internal.codegen.TypeNames.FACTORY;
-import static dagger.internal.codegen.TypeNames.MAP_FACTORY;
-import static dagger.internal.codegen.TypeNames.PRODUCER;
-import static dagger.internal.codegen.TypeNames.PRODUCERS;
-import static dagger.internal.codegen.TypeNames.PROVIDER;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static javax.lang.model.type.TypeKind.DECLARED;
import com.google.auto.common.MoreTypes;
@@ -35,6 +35,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
import java.util.List;
import java.util.Optional;
import javax.lang.model.type.DeclaredType;
diff --git a/java/dagger/internal/codegen/MembersInjectionBinding.java b/java/dagger/internal/codegen/MembersInjectionBinding.java
index 95ad100..4918fa1 100644
--- a/java/dagger/internal/codegen/MembersInjectionBinding.java
+++ b/java/dagger/internal/codegen/MembersInjectionBinding.java
@@ -28,8 +28,10 @@
import java.util.Optional;
import javax.inject.Inject;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
/**
* Represents the full members injection of a particular type.
@@ -123,5 +125,16 @@
.collect(toList())
.indexOf(element());
}
+
+ static InjectionSite field(VariableElement element, DependencyRequest dependency) {
+ return new AutoValue_MembersInjectionBinding_InjectionSite(
+ Kind.FIELD, element, ImmutableSet.of(dependency));
+ }
+
+ static InjectionSite method(
+ ExecutableElement element, Iterable<DependencyRequest> dependencies) {
+ return new AutoValue_MembersInjectionBinding_InjectionSite(
+ Kind.METHOD, element, ImmutableSet.copyOf(dependencies));
+ }
}
}
diff --git a/java/dagger/internal/codegen/MembersInjectionBindingExpression.java b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
index 12e8070..e9a8ffc 100644
--- a/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
+++ b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
@@ -23,6 +23,7 @@
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.ParameterSpec;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
import javax.lang.model.element.ExecutableElement;
/**
diff --git a/java/dagger/internal/codegen/MembersInjectionMethods.java b/java/dagger/internal/codegen/MembersInjectionMethods.java
index bef30fc..1e04669 100644
--- a/java/dagger/internal/codegen/MembersInjectionMethods.java
+++ b/java/dagger/internal/codegen/MembersInjectionMethods.java
@@ -18,9 +18,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.MEMBERS_INJECTION_METHOD;
import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static javax.lang.model.element.Modifier.PRIVATE;
import com.google.common.collect.ImmutableSet;
@@ -31,6 +31,8 @@
import com.squareup.javapoet.TypeName;
import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.LinkedHashMap;
import java.util.Map;
diff --git a/java/dagger/internal/codegen/MembersInjectorGenerator.java b/java/dagger/internal/codegen/MembersInjectorGenerator.java
index dedf267..4360af7 100644
--- a/java/dagger/internal/codegen/MembersInjectorGenerator.java
+++ b/java/dagger/internal/codegen/MembersInjectorGenerator.java
@@ -20,18 +20,18 @@
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
import static dagger.internal.codegen.SourceFiles.frameworkFieldUsages;
import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.TypeNames.membersInjectorOf;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.membersInjectorOf;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -50,6 +50,8 @@
import dagger.MembersInjector;
import dagger.internal.codegen.InjectionMethods.InjectionSiteMethod;
import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.Map.Entry;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
index 25d034a..8e863e5 100644
--- a/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
@@ -19,8 +19,8 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.TypeNames.INSTANCE_FACTORY;
-import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTORS;
+import static dagger.internal.codegen.javapoet.TypeNames.INSTANCE_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MEMBERS_INJECTORS;
import com.google.auto.common.MoreTypes;
import com.squareup.javapoet.CodeBlock;
diff --git a/java/dagger/internal/codegen/MethodBindingExpression.java b/java/dagger/internal/codegen/MethodBindingExpression.java
index dfaa4ef..2120e80 100644
--- a/java/dagger/internal/codegen/MethodBindingExpression.java
+++ b/java/dagger/internal/codegen/MethodBindingExpression.java
@@ -32,6 +32,8 @@
import dagger.internal.MemoizedSentinel;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.RequestKind;
import java.util.Optional;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/MethodSignature.java b/java/dagger/internal/codegen/MethodSignature.java
index 75f25e6..ef5c9c5 100644
--- a/java/dagger/internal/codegen/MethodSignature.java
+++ b/java/dagger/internal/codegen/MethodSignature.java
@@ -23,6 +23,7 @@
import com.google.common.base.Equivalence;
import com.google.common.collect.ImmutableList;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.List;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
diff --git a/java/dagger/internal/codegen/MethodSignatureFormatter.java b/java/dagger/internal/codegen/MethodSignatureFormatter.java
index 28eb614..012d5b0 100644
--- a/java/dagger/internal/codegen/MethodSignatureFormatter.java
+++ b/java/dagger/internal/codegen/MethodSignatureFormatter.java
@@ -22,6 +22,7 @@
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/MissingBindingExpression.java b/java/dagger/internal/codegen/MissingBindingExpression.java
index c7fa17c..610d052 100644
--- a/java/dagger/internal/codegen/MissingBindingExpression.java
+++ b/java/dagger/internal/codegen/MissingBindingExpression.java
@@ -18,6 +18,7 @@
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/MissingBindingValidator.java b/java/dagger/internal/codegen/MissingBindingValidator.java
index 642f7a4..f39361d 100644
--- a/java/dagger/internal/codegen/MissingBindingValidator.java
+++ b/java/dagger/internal/codegen/MissingBindingValidator.java
@@ -23,6 +23,7 @@
import static dagger.internal.codegen.RequestKinds.canBeSatisfiedByProductionBinding;
import static javax.tools.Diagnostic.Kind.ERROR;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingGraph;
import dagger.model.BindingGraph.ComponentNode;
import dagger.model.BindingGraph.DependencyEdge;
@@ -54,7 +55,7 @@
@Override
public void visitGraph(BindingGraph graph, DiagnosticReporter diagnosticReporter) {
- // Don't report missing bindings when validating a full graph or a graph built from a
+ // Don't report missing bindings when validating a full binding graph or a graph built from a
// subcomponent.
if (graph.isFullBindingGraph() || graph.rootComponentNode().isSubcomponent()) {
return;
diff --git a/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
index 1020944..412acae 100644
--- a/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
@@ -25,6 +25,9 @@
import com.squareup.javapoet.TypeName;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
import javax.lang.model.type.TypeMirror;
diff --git a/java/dagger/internal/codegen/ModifiableBindingExpressions.java b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
index 4481f3e..76bcb8b 100644
--- a/java/dagger/internal/codegen/ModifiableBindingExpressions.java
+++ b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
@@ -27,8 +27,10 @@
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.MethodSpec;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.ComponentImplementation.MethodSpecKind;
import dagger.internal.codegen.MethodBindingExpression.MethodImplementationStrategy;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingKind;
import dagger.model.DependencyRequest;
import java.util.Optional;
@@ -62,22 +64,23 @@
}
/**
- * Records the binding exposed by the given component method as modifiable, if it is, and returns
- * the {@link ModifiableBindingType} associated with the binding.
+ * Adds {@code method} to the component implementation. If the binding for the method is
+ * modifiable, also registers the relevant modifiable binding information.
*/
- ModifiableBindingType registerComponentMethodIfModifiable(
+ void addPossiblyModifiableComponentMethod(
ComponentMethodDescriptor componentMethod, MethodSpec method) {
BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get());
ModifiableBindingType modifiableBindingType = getModifiableBindingType(request);
if (modifiableBindingType.isModifiable()) {
- componentImplementation.registerModifiableBindingMethod(
+ componentImplementation.addModifiableComponentMethod(
modifiableBindingType,
request,
componentMethod.resolvedReturnType(types),
method,
newModifiableBindingWillBeFinalized(modifiableBindingType, request));
+ } else {
+ componentImplementation.addMethod(MethodSpecKind.COMPONENT_METHOD, method);
}
- return modifiableBindingType;
}
/**
@@ -381,8 +384,17 @@
// Futures backed by provision bindings are inlined and contain no wrapping producer, so
// if the binding is modifiable and is resolved as a provision binding in a superclass
// but later resolved as a production binding, we can't take the same shortcut as before.
- if (componentImplementation.superclassImplementation().isPresent()) {
- return bindingTypeChanged(request, resolvedBindings);
+ Optional<ComponentImplementation> superclassImplementation =
+ componentImplementation.superclassImplementation();
+ if (superclassImplementation.isPresent()) {
+ if (superclassImplementation.get().isDeserializedImplementation()) {
+ // TODO(b/117833324): consider serializing the binding type so that we don't need to
+ // branch here. Or, instead, consider removing this optimization entirely if there
+ // aren't that many FUTURE entry point methods to justify the extra code.
+ break;
+ } else {
+ return bindingTypeChanged(request, resolvedBindings);
+ }
}
return false;
diff --git a/java/dagger/internal/codegen/ModifiableBindingMethods.java b/java/dagger/internal/codegen/ModifiableBindingMethods.java
index 55dd1ef..ead708d 100644
--- a/java/dagger/internal/codegen/ModifiableBindingMethods.java
+++ b/java/dagger/internal/codegen/ModifiableBindingMethods.java
@@ -16,7 +16,6 @@
package dagger.internal.codegen;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Verify.verify;
import com.google.auto.common.MoreTypes;
@@ -43,13 +42,14 @@
private final Map<BindingRequest, ModifiableBindingMethod> methods = Maps.newLinkedHashMap();
/** Registers a new method encapsulating a modifiable binding. */
- void addNewModifiableMethod(
+ void addModifiableMethod(
ModifiableBindingType type,
BindingRequest request,
TypeMirror returnType,
MethodSpec method,
boolean finalized) {
- checkArgument(type.isModifiable());
+ // It's ok for the type to not be modifiable, since it could be overriding a previously
+ // modifiable method (such as with addReimplementedMethod).
addMethod(ModifiableBindingMethod.create(type, request, returnType, method, finalized));
}
diff --git a/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
index 41b0fa4..907466b 100644
--- a/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
@@ -23,6 +23,7 @@
import static javax.lang.model.element.Modifier.PROTECTED;
import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import java.util.Optional;
/**
diff --git a/java/dagger/internal/codegen/ModuleAnnotation.java b/java/dagger/internal/codegen/ModuleAnnotation.java
index 866c66a..27dd071 100644
--- a/java/dagger/internal/codegen/ModuleAnnotation.java
+++ b/java/dagger/internal/codegen/ModuleAnnotation.java
@@ -19,9 +19,9 @@
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.MoreTypes.asTypeElement;
import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.DaggerElements.getAnyAnnotation;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.MoreAnnotationValues.asAnnotationValues;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnyAnnotation;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
@@ -39,6 +39,9 @@
/** A {@code @Module} or {@code @ProducerModule} annotation. */
@AutoValue
abstract class ModuleAnnotation {
+ private static final ImmutableSet<Class<? extends Annotation>> MODULE_ANNOTATIONS =
+ ImmutableSet.of(Module.class, ProducerModule.class);
+
/** The annotation itself. */
// This does not use AnnotationMirrors.equivalence() because we want the actual annotation
// instance.
@@ -102,8 +105,10 @@
.anyMatch(asTypeElement(annotation.getAnnotationType()).getQualifiedName()::contentEquals);
}
- private static final ImmutableSet<Class<? extends Annotation>> MODULE_ANNOTATIONS =
- ImmutableSet.of(Module.class, ProducerModule.class);
+ /** The module annotation types. */
+ static ImmutableSet<Class<? extends Annotation>> moduleAnnotations() {
+ return MODULE_ANNOTATIONS;
+ }
/**
* Creates an object that represents a {@code @Module} or {@code @ProducerModule}.
diff --git a/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java b/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java
index 2798eba..5f0d687 100644
--- a/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java
+++ b/java/dagger/internal/codegen/ModuleConstructorProxyGenerator.java
@@ -28,6 +28,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Optional;
import javax.annotation.processing.Filer;
import javax.inject.Inject;
diff --git a/java/dagger/internal/codegen/ModuleDescriptor.java b/java/dagger/internal/codegen/ModuleDescriptor.java
index ce248e1..ac7a4b7 100644
--- a/java/dagger/internal/codegen/ModuleDescriptor.java
+++ b/java/dagger/internal/codegen/ModuleDescriptor.java
@@ -22,11 +22,11 @@
import static com.google.common.base.CaseFormat.UPPER_CAMEL;
import static com.google.common.base.Verify.verify;
import static com.google.common.collect.Iterables.transform;
-import static dagger.internal.codegen.DaggerElements.isAnnotationPresent;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
import static dagger.internal.codegen.SourceFiles.classFileName;
import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnnotationPresent;
import static javax.lang.model.type.TypeKind.DECLARED;
import static javax.lang.model.type.TypeKind.NONE;
import static javax.lang.model.util.ElementFilter.methodsIn;
@@ -43,6 +43,7 @@
import dagger.BindsOptionalOf;
import dagger.Module;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.model.Key;
import dagger.multibindings.Multibinds;
import dagger.producers.Produces;
@@ -94,9 +95,7 @@
/** Returns the keys of all bindings declared by this module. */
ImmutableSet<Key> allBindingKeys() {
- return allBindingDeclarations().stream()
- .map(BindingDeclaration::key)
- .collect(toImmutableSet());
+ return allBindingDeclarations().stream().map(BindingDeclaration::key).collect(toImmutableSet());
}
@Singleton
@@ -178,8 +177,7 @@
@CanIgnoreReturnValue
private Set<TypeElement> collectIncludedModules(
- Set<TypeElement> includedModules,
- TypeElement moduleElement) {
+ Set<TypeElement> includedModules, TypeElement moduleElement) {
TypeMirror superclass = moduleElement.getSuperclass();
if (!superclass.getKind().equals(NONE)) {
verify(superclass.getKind().equals(DECLARED));
@@ -205,8 +203,7 @@
if (contributesAndroidInjector == null) {
return ImmutableSet.of();
}
- return methodsIn(moduleElement.getEnclosedElements())
- .stream()
+ return methodsIn(moduleElement.getEnclosedElements()).stream()
.filter(method -> isAnnotationPresent(method, contributesAndroidInjector.asType()))
.map(method -> elements.checkTypePresent(implicitlyIncludedModuleName(method)))
.collect(toImmutableSet());
diff --git a/java/dagger/internal/codegen/ModuleKind.java b/java/dagger/internal/codegen/ModuleKind.java
index ae169e3..c93d8ce 100644
--- a/java/dagger/internal/codegen/ModuleKind.java
+++ b/java/dagger/internal/codegen/ModuleKind.java
@@ -17,16 +17,14 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.DaggerElements.getAnnotationMirror;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
import com.google.auto.common.MoreElements;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import dagger.Module;
-import dagger.Provides;
import dagger.producers.ProducerModule;
-import dagger.producers.Produces;
import java.lang.annotation.Annotation;
import java.util.EnumSet;
import java.util.Optional;
@@ -37,10 +35,10 @@
/** Enumeration of the kinds of modules. */
enum ModuleKind {
/** {@code @Module} */
- MODULE(Module.class, Provides.class),
+ MODULE(Module.class),
/** {@code @ProducerModule} */
- PRODUCER_MODULE(ProducerModule.class, Produces.class);
+ PRODUCER_MODULE(ProducerModule.class);
/** Returns the annotations for modules of the given kinds. */
static ImmutableSet<Class<? extends Annotation>> annotationsFor(Set<ModuleKind> kinds) {
@@ -74,12 +72,9 @@
}
private final Class<? extends Annotation> moduleAnnotation;
- private final Class<? extends Annotation> methodAnnotation;
- ModuleKind(
- Class<? extends Annotation> moduleAnnotation, Class<? extends Annotation> methodAnnotation) {
+ ModuleKind(Class<? extends Annotation> moduleAnnotation) {
this.moduleAnnotation = moduleAnnotation;
- this.methodAnnotation = methodAnnotation;
}
/**
diff --git a/java/dagger/internal/codegen/ModuleProxies.java b/java/dagger/internal/codegen/ModuleProxies.java
index f5db82a..6426e69 100644
--- a/java/dagger/internal/codegen/ModuleProxies.java
+++ b/java/dagger/internal/codegen/ModuleProxies.java
@@ -16,7 +16,7 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.Accessibility.isElementAccessibleFrom;
+import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.STATIC;
@@ -24,6 +24,8 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.langmodel.Accessibility;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Optional;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
diff --git a/java/dagger/internal/codegen/ModuleValidator.java b/java/dagger/internal/codegen/ModuleValidator.java
index 403a321..094bf34 100644
--- a/java/dagger/internal/codegen/ModuleValidator.java
+++ b/java/dagger/internal/codegen/ModuleValidator.java
@@ -26,14 +26,15 @@
import static dagger.internal.codegen.ComponentAnnotation.subcomponentAnnotation;
import static dagger.internal.codegen.ComponentCreatorAnnotation.getCreatorAnnotations;
import static dagger.internal.codegen.ConfigurationAnnotations.getSubcomponentCreator;
-import static dagger.internal.codegen.DaggerElements.getAnnotationMirror;
-import static dagger.internal.codegen.DaggerElements.isAnyAnnotationPresent;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.ModuleAnnotation.isModuleAnnotation;
import static dagger.internal.codegen.ModuleAnnotation.moduleAnnotation;
import static dagger.internal.codegen.MoreAnnotationMirrors.simpleName;
import static dagger.internal.codegen.MoreAnnotationValues.asType;
import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
+import static dagger.internal.codegen.langmodel.DaggerElements.isAnyAnnotationPresent;
import static java.util.EnumSet.noneOf;
import static java.util.stream.Collectors.joining;
import static javax.lang.model.element.Modifier.ABSTRACT;
@@ -49,8 +50,11 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.FormatMethod;
import dagger.Module;
import dagger.Subcomponent;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingGraph;
import dagger.producers.ProducerModule;
import dagger.producers.ProductionSubcomponent;
@@ -225,7 +229,7 @@
validateSelfCycles(module, builder);
if (builder.build().isClean()
- && !compilerOptions.moduleBindingValidationType().equals(ValidationType.NONE)) {
+ && !compilerOptions.fullBindingGraphValidationType(module).equals(NONE)) {
validateModuleBindings(module, builder);
}
@@ -430,6 +434,7 @@
return null;
}
+ @FormatMethod
private void reportError(String format, Object... args) {
subreport.addError(
String.format(format, args), annotatedType, annotation, includedModule);
diff --git a/java/dagger/internal/codegen/MonitoringModuleGenerator.java b/java/dagger/internal/codegen/MonitoringModuleGenerator.java
index 9aa87b3..1738fe9 100644
--- a/java/dagger/internal/codegen/MonitoringModuleGenerator.java
+++ b/java/dagger/internal/codegen/MonitoringModuleGenerator.java
@@ -19,9 +19,9 @@
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.TypeNames.PRODUCTION_COMPONENT_MONITOR_FACTORY;
-import static dagger.internal.codegen.TypeNames.providerOf;
-import static dagger.internal.codegen.TypeNames.setOf;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCTION_COMPONENT_MONITOR_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.setOf;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.STATIC;
@@ -31,6 +31,7 @@
import com.squareup.javapoet.TypeSpec;
import dagger.Module;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.multibindings.Multibinds;
import dagger.producers.ProductionScope;
import dagger.producers.monitoring.ProductionComponentMonitor;
diff --git a/java/dagger/internal/codegen/MoreAnnotationMirrors.java b/java/dagger/internal/codegen/MoreAnnotationMirrors.java
index fb5bb74..92825a0 100644
--- a/java/dagger/internal/codegen/MoreAnnotationMirrors.java
+++ b/java/dagger/internal/codegen/MoreAnnotationMirrors.java
@@ -59,15 +59,6 @@
}
/**
- * Returns the value named {@code name} from {@code annotation}.
- *
- * @throws IllegalArgumentException unless that member represents a single type
- */
- static TypeMirror getTypeValue(AnnotationMirror annotation, String name) {
- return MoreAnnotationValues.asType(getAnnotationValue(annotation, name));
- }
-
- /**
* Returns the list of types that is the value named {@code name} from {@code annotationMirror}.
*
* @throws IllegalArgumentException unless that member represents an array of types
diff --git a/java/dagger/internal/codegen/MultibindingAnnotations.java b/java/dagger/internal/codegen/MultibindingAnnotations.java
index eaf7a17..b478704 100644
--- a/java/dagger/internal/codegen/MultibindingAnnotations.java
+++ b/java/dagger/internal/codegen/MultibindingAnnotations.java
@@ -16,21 +16,21 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.getAllAnnotations;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAllAnnotations;
import com.google.common.collect.ImmutableSet;
import dagger.multibindings.ElementsIntoSet;
import dagger.multibindings.IntoMap;
import dagger.multibindings.IntoSet;
import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Element;
/**
* Utility methods related to processing {@link IntoSet}, {@link ElementsIntoSet}, and {@link
* IntoMap}.
*/
final class MultibindingAnnotations {
- static ImmutableSet<AnnotationMirror> forMethod(ExecutableElement method) {
+ static ImmutableSet<AnnotationMirror> forElement(Element method) {
return getAllAnnotations(method, IntoSet.class, ElementsIntoSet.class, IntoMap.class);
}
}
diff --git a/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java b/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java
index 0535062..2bb0a7e 100644
--- a/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java
+++ b/java/dagger/internal/codegen/MultibindingAnnotationsProcessingStep.java
@@ -16,7 +16,7 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.getAnnotationMirror;
+import static dagger.internal.codegen.langmodel.DaggerElements.getAnnotationMirror;
import static javax.tools.Diagnostic.Kind.ERROR;
import com.google.auto.common.MoreElements;
diff --git a/java/dagger/internal/codegen/MultibindingDeclaration.java b/java/dagger/internal/codegen/MultibindingDeclaration.java
index 95e2b3f..c3724dc 100644
--- a/java/dagger/internal/codegen/MultibindingDeclaration.java
+++ b/java/dagger/internal/codegen/MultibindingDeclaration.java
@@ -23,6 +23,7 @@
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import dagger.internal.codegen.ContributionType.HasContributionType;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import dagger.multibindings.Multibinds;
import java.util.Map;
diff --git a/java/dagger/internal/codegen/MultibindingExpression.java b/java/dagger/internal/codegen/MultibindingExpression.java
index d5439ec..f0523eb 100644
--- a/java/dagger/internal/codegen/MultibindingExpression.java
+++ b/java/dagger/internal/codegen/MultibindingExpression.java
@@ -21,6 +21,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
diff --git a/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java b/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java
index 43e6978..abe161a 100644
--- a/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java
+++ b/java/dagger/internal/codegen/MultibindingFactoryCreationExpression.java
@@ -23,6 +23,8 @@
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.model.DependencyRequest;
import dagger.model.Key;
import java.util.Optional;
@@ -43,28 +45,29 @@
}
/** Returns the expression for a dependency of this multibinding. */
- protected final CodeBlock multibindingDependencyExpression(
- FrameworkDependency frameworkDependency) {
+ protected final CodeBlock multibindingDependencyExpression(DependencyRequest dependency) {
CodeBlock expression =
componentBindingExpressions
.getDependencyExpression(
- BindingRequest.bindingRequest(frameworkDependency), componentImplementation.name())
+ BindingRequest.bindingRequest(dependency.key(), binding.frameworkType()),
+ componentImplementation.name())
.codeBlock();
+
return useRawType()
- ? CodeBlocks.cast(expression, frameworkDependency.frameworkClass())
+ ? CodeBlocks.cast(expression, binding.frameworkType().frameworkClass())
: expression;
}
- protected final ImmutableSet<FrameworkDependency> frameworkDependenciesToImplement() {
+ protected final ImmutableSet<DependencyRequest> dependenciesToImplement() {
ImmutableSet<Key> alreadyImplementedKeys =
componentImplementation.superclassContributionsMade(bindingRequest());
- return binding.frameworkDependencies().stream()
- .filter(frameworkDependency -> !alreadyImplementedKeys.contains(frameworkDependency.key()))
+ return binding.dependencies().stream()
+ .filter(dependency -> !alreadyImplementedKeys.contains(dependency.key()))
.collect(toImmutableSet());
}
protected Optional<CodeBlock> superContributions() {
- if (frameworkDependenciesToImplement().size() == binding.frameworkDependencies().size()) {
+ if (dependenciesToImplement().size() == binding.dependencies().size()) {
return Optional.empty();
}
ModifiableBindingMethod superMethod =
@@ -74,9 +77,7 @@
/** The binding request for this framework instance. */
protected final BindingRequest bindingRequest() {
- return BindingRequest.bindingRequest(
- binding.key(),
- binding instanceof ProvisionBinding ? FrameworkType.PROVIDER : FrameworkType.PRODUCER_NODE);
+ return BindingRequest.bindingRequest(binding.key(), binding.frameworkType());
}
/**
diff --git a/java/dagger/internal/codegen/MultibindsMethodValidator.java b/java/dagger/internal/codegen/MultibindsMethodValidator.java
index f912792..bc97d30 100644
--- a/java/dagger/internal/codegen/MultibindsMethodValidator.java
+++ b/java/dagger/internal/codegen/MultibindsMethodValidator.java
@@ -16,15 +16,17 @@
package dagger.internal.codegen;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsMultibindings.NO_MULTIBINDINGS;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
import static dagger.internal.codegen.FrameworkTypes.isFrameworkType;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
import dagger.Module;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.multibindings.Multibinds;
import dagger.producers.ProducerModule;
import javax.inject.Inject;
@@ -53,45 +55,49 @@
}
@Override
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- super.checkMethod(builder);
-
- checkParameters(builder);
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
}
- @Override
- protected void checkParameters(ValidationReport.Builder<ExecutableElement> builder) {
- if (!builder.getSubject().getParameters().isEmpty()) {
- builder.addError(bindingMethods("cannot have parameters"));
+ private class Validator extends MethodValidator {
+ Validator(ExecutableElement element) {
+ super(element);
}
- }
- /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */
- @Override
- protected void checkReturnType(ValidationReport.Builder<ExecutableElement> builder) {
- if (!isPlainMap(builder.getSubject().getReturnType())
- && !isPlainSet(builder.getSubject().getReturnType())) {
- builder.addError(bindingMethods("must return Map<K, V> or Set<T>"));
+ @Override
+ protected void checkParameters() {
+ if (!element.getParameters().isEmpty()) {
+ report.addError(bindingMethods("cannot have parameters"));
+ }
}
- }
- private boolean isPlainMap(TypeMirror returnType) {
- if (!MapType.isMap(returnType)) {
- return false;
+ /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */
+ @Override
+ protected void checkType() {
+ if (!isPlainMap(element.getReturnType())
+ && !isPlainSet(element.getReturnType())) {
+ report.addError(bindingMethods("must return Map<K, V> or Set<T>"));
+ }
}
- MapType mapType = MapType.from(returnType);
- return !mapType.isRawType()
- && MoreTypes.isType(mapType.valueType()) // No wildcards.
- && !isFrameworkType(mapType.valueType());
- }
- private boolean isPlainSet(TypeMirror returnType) {
- if (!SetType.isSet(returnType)) {
- return false;
+ private boolean isPlainMap(TypeMirror returnType) {
+ if (!MapType.isMap(returnType)) {
+ return false;
+ }
+ MapType mapType = MapType.from(returnType);
+ return !mapType.isRawType()
+ && MoreTypes.isType(mapType.valueType()) // No wildcards.
+ && !isFrameworkType(mapType.valueType());
}
- SetType setType = SetType.from(returnType);
- return !setType.isRawType()
- && MoreTypes.isType(setType.elementType()) // No wildcards.
- && !isFrameworkType(setType.elementType());
+
+ private boolean isPlainSet(TypeMirror returnType) {
+ if (!SetType.isSet(returnType)) {
+ return false;
+ }
+ SetType setType = SetType.from(returnType);
+ return !setType.isRawType()
+ && MoreTypes.isType(setType.elementType()) // No wildcards.
+ && !isFrameworkType(setType.elementType());
+ }
}
}
diff --git a/java/dagger/internal/codegen/OptionalBindingExpression.java b/java/dagger/internal/codegen/OptionalBindingExpression.java
index 1ec9f45..dbb0e37 100644
--- a/java/dagger/internal/codegen/OptionalBindingExpression.java
+++ b/java/dagger/internal/codegen/OptionalBindingExpression.java
@@ -17,30 +17,36 @@
package dagger.internal.codegen;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import javax.inject.Inject;
+import javax.lang.model.SourceVersion;
/** A binding expression for optional bindings. */
final class OptionalBindingExpression extends SimpleInvocationBindingExpression {
private final ProvisionBinding binding;
private final ComponentBindingExpressions componentBindingExpressions;
private final DaggerTypes types;
+ private final SourceVersion sourceVersion;
@Inject
OptionalBindingExpression(
ResolvedBindings resolvedBindings,
ComponentBindingExpressions componentBindingExpressions,
- DaggerTypes types) {
+ DaggerTypes types,
+ SourceVersion sourceVersion) {
super(resolvedBindings);
this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
this.componentBindingExpressions = componentBindingExpressions;
this.types = types;
+ this.sourceVersion = sourceVersion;
}
@Override
@@ -48,14 +54,16 @@
OptionalType optionalType = OptionalType.from(binding.key());
OptionalKind optionalKind = optionalType.kind();
if (binding.dependencies().isEmpty()) {
- // When compiling with -source 7, javac's type inference isn't strong enough to detect
- // Futures.immediateFuture(Optional.absent()) for keys that aren't Object. It also has issues
- // when used as an argument to some members injection proxy methods (see
- // https://github.com/google/dagger/issues/916)
- if (isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
- return Expression.create(
- binding.key().type(),
- optionalKind.parameterizedAbsentValueExpression(optionalType));
+ if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+ // When compiling with -source 7, javac's type inference isn't strong enough to detect
+ // Futures.immediateFuture(Optional.absent()) for keys that aren't Object. It also has
+ // issues
+ // when used as an argument to some members injection proxy methods (see
+ // https://github.com/google/dagger/issues/916)
+ if (isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
+ return Expression.create(
+ binding.key().type(), optionalKind.parameterizedAbsentValueExpression(optionalType));
+ }
}
return Expression.create(binding.key().type(), optionalKind.absentValueExpression());
}
diff --git a/java/dagger/internal/codegen/OptionalFactories.java b/java/dagger/internal/codegen/OptionalFactories.java
index f4c1460..51c9939 100644
--- a/java/dagger/internal/codegen/OptionalFactories.java
+++ b/java/dagger/internal/codegen/OptionalFactories.java
@@ -24,16 +24,16 @@
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.ABSENT_OPTIONAL_FIELD;
import static dagger.internal.codegen.ComponentImplementation.MethodSpecKind.ABSENT_OPTIONAL_METHOD;
import static dagger.internal.codegen.ComponentImplementation.TypeSpecKind.PRESENT_FACTORY;
import static dagger.internal.codegen.RequestKinds.requestTypeName;
-import static dagger.internal.codegen.TypeNames.PROVIDER;
-import static dagger.internal.codegen.TypeNames.abstractProducerOf;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
+import static dagger.internal.codegen.javapoet.TypeNames.abstractProducerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -56,6 +56,7 @@
import dagger.internal.InstanceFactory;
import dagger.internal.Preconditions;
import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
import dagger.model.RequestKind;
import dagger.producers.Producer;
import dagger.producers.internal.Producers;
@@ -403,10 +404,8 @@
throw new UnsupportedOperationException(
spec.factoryType() + " objects are not supported");
}
-
- default:
- throw new AssertionError(spec.frameworkType());
}
+ throw new AssertionError(spec.frameworkType());
}
/**
diff --git a/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java b/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java
index 9d53c0e..ba9e25f 100644
--- a/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java
+++ b/java/dagger/internal/codegen/OptionalFactoryInstanceCreationExpression.java
@@ -52,7 +52,8 @@
binding,
componentBindingExpressions
.getDependencyExpression(
- bindingRequest(getOnlyElement(binding.frameworkDependencies())),
+ bindingRequest(
+ getOnlyElement(binding.dependencies()).key(), binding.frameworkType()),
componentImplementation.name())
.codeBlock());
}
diff --git a/java/dagger/internal/codegen/PrivateMethodBindingExpression.java b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
index ba62369..482c123 100644
--- a/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
@@ -23,6 +23,7 @@
import static javax.lang.model.element.Modifier.PRIVATE;
import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.langmodel.DaggerTypes;
/**
* A binding expression that wraps the dependency expressions in a private, no-arg method.
diff --git a/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java b/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java
new file mode 100644
index 0000000..cf2475d
--- /dev/null
+++ b/java/dagger/internal/codegen/ProcessingEnvironmentCompilerOptions.java
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Sets.immutableEnumSet;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.FeatureStatus.DISABLED;
+import static dagger.internal.codegen.FeatureStatus.ENABLED;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EMIT_MODIFIABLE_METADATA_ANNOTATIONS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.EXPERIMENTAL_ANDROID_MODE;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FAST_INIT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FLOATING_BINDS_METHODS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.FORMAT_GENERATED_SOURCE;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Feature.WRITE_PRODUCER_NAME_IN_TOKEN;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.HEADER_COMPILATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.KeyOnlyOption.USE_GRADLE_INCREMENTAL_PROCESSING;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.DISABLE_INTER_COMPONENT_SCOPE_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.EXPLICIT_BINDING_CONFLICTS_WITH_INJECT;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.FULL_BINDING_GRAPH_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.MODULE_HAS_DIFFERENT_SCOPES_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.NULLABLE_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.PRIVATE_MEMBER_VALIDATION;
+import static dagger.internal.codegen.ProcessingEnvironmentCompilerOptions.Validation.STATIC_MEMBER_VALIDATION;
+import static dagger.internal.codegen.ValidationType.ERROR;
+import static dagger.internal.codegen.ValidationType.NONE;
+import static dagger.internal.codegen.ValidationType.WARNING;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Stream.concat;
+
+import com.google.common.base.Ascii;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import dagger.producers.Produces;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+final class ProcessingEnvironmentCompilerOptions extends CompilerOptions {
+ /** Returns a valid {@link CompilerOptions} parsed from the processing environment. */
+ static CompilerOptions create(ProcessingEnvironment processingEnvironment) {
+ return new ProcessingEnvironmentCompilerOptions(processingEnvironment).checkValid();
+ }
+
+ private final ProcessingEnvironment processingEnvironment;
+ private final Map<EnumOption<?>, Object> enumOptions = new HashMap<>();
+ private final Map<EnumOption<?>, ImmutableMap<String, ? extends Enum<?>>> allCommandLineOptions =
+ new HashMap<>();
+
+ private ProcessingEnvironmentCompilerOptions(ProcessingEnvironment processingEnvironment) {
+ this.processingEnvironment = processingEnvironment;
+ }
+
+ @Override
+ boolean usesProducers() {
+ return processingEnvironment.getElementUtils().getTypeElement(Produces.class.getCanonicalName())
+ != null;
+ }
+
+ @Override
+ boolean headerCompilation() {
+ return isEnabled(HEADER_COMPILATION);
+ }
+
+ @Override
+ boolean fastInit() {
+ return isEnabled(FAST_INIT);
+ }
+
+ @Override
+ boolean formatGeneratedSource() {
+ return isEnabled(FORMAT_GENERATED_SOURCE);
+ }
+
+ @Override
+ boolean writeProducerNameInToken() {
+ return isEnabled(WRITE_PRODUCER_NAME_IN_TOKEN);
+ }
+
+ @Override
+ Diagnostic.Kind nullableValidationKind() {
+ return diagnosticKind(NULLABLE_VALIDATION);
+ }
+
+ @Override
+ Diagnostic.Kind privateMemberValidationKind() {
+ return diagnosticKind(PRIVATE_MEMBER_VALIDATION);
+ }
+
+ @Override
+ Diagnostic.Kind staticMemberValidationKind() {
+ return diagnosticKind(STATIC_MEMBER_VALIDATION);
+ }
+
+ @Override
+ boolean ignorePrivateAndStaticInjectionForComponent() {
+ return isEnabled(IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT);
+ }
+
+ @Override
+ ValidationType scopeCycleValidationType() {
+ return parseOption(DISABLE_INTER_COMPONENT_SCOPE_VALIDATION);
+ }
+
+ @Override
+ boolean warnIfInjectionFactoryNotGeneratedUpstream() {
+ return isEnabled(WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM);
+ }
+
+ @Override
+ boolean aheadOfTimeSubcomponents() {
+ return isEnabled(EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS);
+ }
+
+ @Override
+ boolean forceUseSerializedComponentImplementations() {
+ return isEnabled(FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS);
+ }
+
+ @Override
+ boolean emitModifiableMetadataAnnotations() {
+ return isEnabled(EMIT_MODIFIABLE_METADATA_ANNOTATIONS);
+ }
+
+ @Override
+ boolean useGradleIncrementalProcessing() {
+ return isEnabled(USE_GRADLE_INCREMENTAL_PROCESSING);
+ }
+
+ @Override
+ ValidationType fullBindingGraphValidationType(TypeElement element) {
+ return fullBindingGraphValidationType();
+ }
+
+ private ValidationType fullBindingGraphValidationType() {
+ return parseOption(FULL_BINDING_GRAPH_VALIDATION);
+ }
+
+ @Override
+ Diagnostic.Kind moduleHasDifferentScopesDiagnosticKind() {
+ return diagnosticKind(MODULE_HAS_DIFFERENT_SCOPES_VALIDATION);
+ }
+
+ @Override
+ ValidationType explicitBindingConflictsWithInjectValidationType() {
+ return parseOption(EXPLICIT_BINDING_CONFLICTS_WITH_INJECT);
+ }
+
+ private boolean isEnabled(KeyOnlyOption keyOnlyOption) {
+ return processingEnvironment.getOptions().containsKey(keyOnlyOption.toString());
+ }
+
+ private boolean isEnabled(Feature feature) {
+ return parseOption(feature).equals(ENABLED);
+ }
+
+ private Diagnostic.Kind diagnosticKind(Validation validation) {
+ return parseOption(validation).diagnosticKind().get();
+ }
+
+ @SuppressWarnings("CheckReturnValue")
+ private ProcessingEnvironmentCompilerOptions checkValid() {
+ for (KeyOnlyOption keyOnlyOption : KeyOnlyOption.values()) {
+ isEnabled(keyOnlyOption);
+ }
+ for (Feature feature : Feature.values()) {
+ parseOption(feature);
+ }
+ for (Validation validation : Validation.values()) {
+ parseOption(validation);
+ }
+ noLongerRecognized(EXPERIMENTAL_ANDROID_MODE);
+ noLongerRecognized(FLOATING_BINDS_METHODS);
+ return this;
+ }
+
+ private void noLongerRecognized(CommandLineOption commandLineOption) {
+ if (processingEnvironment.getOptions().containsKey(commandLineOption.toString())) {
+ processingEnvironment
+ .getMessager()
+ .printMessage(
+ Diagnostic.Kind.WARNING, commandLineOption + " is no longer recognized by Dagger");
+ }
+ }
+
+ private interface CommandLineOption {
+ /** The key of the option (appears after "-A"). */
+ @Override
+ String toString();
+
+ /**
+ * Returns all aliases besides {@link #toString()}, such as old names for an option, in order of
+ * precedence.
+ */
+ default ImmutableList<String> aliases() {
+ return ImmutableList.of();
+ }
+
+ /** All the command-line names for this option, in order of precedence. */
+ default Stream<String> allNames() {
+ return concat(Stream.of(toString()), aliases().stream());
+ }
+ }
+
+ /** An option that can be set on the command line. */
+ private interface EnumOption<E extends Enum<E>> extends CommandLineOption {
+ /** The default value for this option. */
+ E defaultValue();
+
+ /** The valid values for this option. */
+ Set<E> validValues();
+ }
+
+ enum KeyOnlyOption implements CommandLineOption {
+ HEADER_COMPILATION {
+ @Override
+ public String toString() {
+ return "experimental_turbine_hjar";
+ }
+ },
+
+ USE_GRADLE_INCREMENTAL_PROCESSING {
+ @Override
+ public String toString() {
+ return "dagger.gradle.incremental";
+ }
+ },
+ }
+
+ /**
+ * A feature that can be enabled or disabled on the command line by setting {@code -Akey=ENABLED}
+ * or {@code -Akey=DISABLED}.
+ */
+ enum Feature implements EnumOption<FeatureStatus> {
+ FAST_INIT,
+
+ EXPERIMENTAL_ANDROID_MODE,
+
+ FORMAT_GENERATED_SOURCE,
+
+ WRITE_PRODUCER_NAME_IN_TOKEN,
+
+ WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM,
+
+ IGNORE_PRIVATE_AND_STATIC_INJECTION_FOR_COMPONENT,
+
+ EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS,
+
+ FORCE_USE_SERIALIZED_COMPONENT_IMPLEMENTATIONS,
+
+ EMIT_MODIFIABLE_METADATA_ANNOTATIONS(ENABLED),
+
+ FLOATING_BINDS_METHODS,
+ ;
+
+ final FeatureStatus defaultValue;
+
+ Feature() {
+ this(DISABLED);
+ }
+
+ Feature(FeatureStatus defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ @Override
+ public FeatureStatus defaultValue() {
+ return defaultValue;
+ }
+
+ @Override
+ public Set<FeatureStatus> validValues() {
+ return EnumSet.allOf(FeatureStatus.class);
+ }
+
+ @Override
+ public String toString() {
+ return optionName(this);
+ }
+ }
+
+ /** The diagnostic kind or validation type for a kind of validation. */
+ enum Validation implements EnumOption<ValidationType> {
+ DISABLE_INTER_COMPONENT_SCOPE_VALIDATION(),
+
+ NULLABLE_VALIDATION(ERROR, WARNING),
+
+ PRIVATE_MEMBER_VALIDATION(ERROR, WARNING),
+
+ STATIC_MEMBER_VALIDATION(ERROR, WARNING),
+
+ /** Whether to validate full binding graphs for components, subcomponents, and modules. */
+ FULL_BINDING_GRAPH_VALIDATION(NONE, ERROR, WARNING) {
+ @Override
+ public ImmutableList<String> aliases() {
+ return ImmutableList.of("dagger.moduleBindingValidation");
+ }
+ },
+
+ /**
+ * How to report conflicting scoped bindings when validating partial binding graphs associated
+ * with modules.
+ */
+ MODULE_HAS_DIFFERENT_SCOPES_VALIDATION(ERROR, WARNING),
+
+ /**
+ * How to report that an explicit binding in a subcomponent conflicts with an {@code @Inject}
+ * constructor used in an ancestor component.
+ */
+ EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(WARNING, ERROR, NONE),
+ ;
+
+ final ValidationType defaultType;
+ final ImmutableSet<ValidationType> validTypes;
+
+ Validation() {
+ this(ERROR, WARNING, NONE);
+ }
+
+ Validation(ValidationType defaultType, ValidationType... moreValidTypes) {
+ this.defaultType = defaultType;
+ this.validTypes = immutableEnumSet(defaultType, moreValidTypes);
+ }
+
+ @Override
+ public ValidationType defaultValue() {
+ return defaultType;
+ }
+
+ @Override
+ public Set<ValidationType> validValues() {
+ return validTypes;
+ }
+
+ @Override
+ public String toString() {
+ return optionName(this);
+ }
+ }
+
+ private static String optionName(Enum<? extends EnumOption<?>> option) {
+ return "dagger." + UPPER_UNDERSCORE.to(LOWER_CAMEL, option.name());
+ }
+
+ /** The supported command-line options. */
+ static ImmutableSet<String> supportedOptions() {
+ // need explicit type parameter to avoid a runtime stream error
+ return Stream.<CommandLineOption[]>of(
+ KeyOnlyOption.values(), Feature.values(), Validation.values())
+ .flatMap(Arrays::stream)
+ .flatMap(CommandLineOption::allNames)
+ .collect(toImmutableSet());
+ }
+
+ /**
+ * Returns the value for the option as set on the command line by any name, or the default value
+ * if not set.
+ *
+ * <p>If more than one name is used to set the value, but all names specify the same value,
+ * reports a warning and returns that value.
+ *
+ * <p>If more than one name is used to set the value, and not all names specify the same value,
+ * reports an error and returns the default value.
+ */
+ private <T extends Enum<T>> T parseOption(EnumOption<T> option) {
+ @SuppressWarnings("unchecked") // we only put covariant values into the map
+ T value = (T) enumOptions.computeIfAbsent(option, this::parseOptionUncached);
+ return value;
+ }
+
+ private <T extends Enum<T>> T parseOptionUncached(EnumOption<T> option) {
+ ImmutableMap<String, T> values = parseOptionWithAllNames(option);
+
+ // If no value is specified, return the default value.
+ if (values.isEmpty()) {
+ return option.defaultValue();
+ }
+
+ // If all names have the same value, return that.
+ if (values.asMultimap().inverse().keySet().size() == 1) {
+ // Warn if an option was set with more than one name. That would be an error if the values
+ // differed.
+ if (values.size() > 1) {
+ reportUseOfDifferentNamesForOption(Diagnostic.Kind.WARNING, option, values.keySet());
+ }
+ return values.values().asList().get(0);
+ }
+
+ // If different names have different values, report an error and return the default
+ // value.
+ reportUseOfDifferentNamesForOption(Diagnostic.Kind.ERROR, option, values.keySet());
+ return option.defaultValue();
+ }
+
+ private void reportUseOfDifferentNamesForOption(
+ Diagnostic.Kind diagnosticKind, EnumOption<?> option, ImmutableSet<String> usedNames) {
+ processingEnvironment
+ .getMessager()
+ .printMessage(
+ diagnosticKind,
+ String.format(
+ "Only one of the equivalent options (%s) should be used; prefer -A%s",
+ usedNames.stream().map(name -> "-A" + name).collect(joining(", ")), option));
+ }
+
+ private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNames(
+ EnumOption<T> option) {
+ @SuppressWarnings("unchecked") // map is covariant
+ ImmutableMap<String, T> aliasValues =
+ (ImmutableMap<String, T>)
+ allCommandLineOptions.computeIfAbsent(option, this::parseOptionWithAllNamesUncached);
+ return aliasValues;
+ }
+
+ private <T extends Enum<T>> ImmutableMap<String, T> parseOptionWithAllNamesUncached(
+ EnumOption<T> option) {
+ ImmutableMap.Builder<String, T> values = ImmutableMap.builder();
+ getUsedNames(option)
+ .forEach(
+ name -> parseOptionWithName(option, name).ifPresent(value -> values.put(name, value)));
+ return values.build();
+ }
+
+ private <T extends Enum<T>> Optional<T> parseOptionWithName(EnumOption<T> option, String key) {
+ checkArgument(processingEnvironment.getOptions().containsKey(key), "key %s not found", key);
+ String stringValue = processingEnvironment.getOptions().get(key);
+ if (stringValue == null) {
+ processingEnvironment
+ .getMessager()
+ .printMessage(Diagnostic.Kind.ERROR, "Processor option -A" + key + " needs a value");
+ } else {
+ try {
+ T value =
+ Enum.valueOf(option.defaultValue().getDeclaringClass(), Ascii.toUpperCase(stringValue));
+ if (option.validValues().contains(value)) {
+ return Optional.of(value);
+ }
+ } catch (IllegalArgumentException e) {
+ // handled below
+ }
+ processingEnvironment
+ .getMessager()
+ .printMessage(
+ Diagnostic.Kind.ERROR,
+ String.format(
+ "Processor option -A%s may only have the values %s "
+ + "(case insensitive), found: %s",
+ key, option.validValues(), stringValue));
+ }
+ return Optional.empty();
+ }
+
+ private Stream<String> getUsedNames(CommandLineOption option) {
+ return option.allNames().filter(name -> processingEnvironment.getOptions().containsKey(name));
+ }
+}
diff --git a/java/dagger/internal/codegen/ProcessingEnvironmentModule.java b/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
index b5cbc81..1730574 100644
--- a/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
+++ b/java/dagger/internal/codegen/ProcessingEnvironmentModule.java
@@ -22,6 +22,7 @@
import dagger.Module;
import dagger.Provides;
import dagger.Reusable;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Map;
import java.util.Optional;
import javax.annotation.processing.Filer;
@@ -78,7 +79,7 @@
@Provides
@Reusable // to avoid parsing options more than once
CompilerOptions compilerOptions() {
- return CompilerOptions.create(processingEnvironment);
+ return ProcessingEnvironmentCompilerOptions.create(processingEnvironment);
}
@Provides
diff --git a/java/dagger/internal/codegen/ProducerEntryPointView.java b/java/dagger/internal/codegen/ProducerEntryPointView.java
index 8cb41ff..87b5a4a 100644
--- a/java/dagger/internal/codegen/ProducerEntryPointView.java
+++ b/java/dagger/internal/codegen/ProducerEntryPointView.java
@@ -23,6 +23,8 @@
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.TypeName;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.RequestKind;
import dagger.producers.Producer;
import dagger.producers.internal.CancellationListener;
diff --git a/java/dagger/internal/codegen/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
index e80c1d6..3f2bef4 100644
--- a/java/dagger/internal/codegen/ProducerFactoryGenerator.java
+++ b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
@@ -22,22 +22,22 @@
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation;
import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames;
-import static dagger.internal.codegen.SourceFiles.frameworkTypeUsageStatement;
import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies;
import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
import static dagger.internal.codegen.SourceFiles.parameterizedGeneratedTypeNameForBinding;
-import static dagger.internal.codegen.TypeNames.FUTURES;
-import static dagger.internal.codegen.TypeNames.PRODUCERS;
-import static dagger.internal.codegen.TypeNames.PRODUCER_TOKEN;
-import static dagger.internal.codegen.TypeNames.VOID_CLASS;
-import static dagger.internal.codegen.TypeNames.listOf;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.TypeNames.producedOf;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.FUTURES;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
+import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER_TOKEN;
+import static dagger.internal.codegen.javapoet.TypeNames.VOID_CLASS;
+import static dagger.internal.codegen.javapoet.TypeNames.listOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
import static java.util.stream.Collectors.joining;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
@@ -57,6 +57,9 @@
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.javapoet.AnnotationSpecs;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
@@ -327,6 +330,11 @@
return false;
}
+ CodeBlock frameworkTypeUsageStatement(DependencyRequest dependency) {
+ return SourceFiles.frameworkTypeUsageStatement(
+ CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind());
+ }
+
static FutureTransform create(
ImmutableMap<Key, FieldSpec> fields,
ProductionBinding binding,
@@ -364,13 +372,9 @@
@Override
ImmutableList<CodeBlock> parameterCodeBlocks() {
- ImmutableList.Builder<CodeBlock> parameterCodeBlocks = ImmutableList.builder();
- for (DependencyRequest dependency : binding.explicitDependencies()) {
- parameterCodeBlocks.add(
- frameworkTypeUsageStatement(
- CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind()));
- }
- return parameterCodeBlocks.build();
+ return binding.explicitDependencies().stream()
+ .map(this::frameworkTypeUsageStatement)
+ .collect(toImmutableList());
}
}
@@ -413,10 +417,7 @@
if (dependency == asyncDependency) {
parameterCodeBlocks.add(CodeBlock.of("$L", applyArgName()));
} else {
- parameterCodeBlocks.add(
- // TODO(ronshapiro) extract this into a method shared by FutureTransform subclasses
- frameworkTypeUsageStatement(
- CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind()));
+ parameterCodeBlocks.add(frameworkTypeUsageStatement(dependency));
}
}
return parameterCodeBlocks.build();
@@ -458,7 +459,19 @@
@Override
ImmutableList<CodeBlock> parameterCodeBlocks() {
- return getParameterCodeBlocks(binding, fields, applyArgName());
+ int argIndex = 0;
+ ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
+ for (DependencyRequest dependency : binding.explicitDependencies()) {
+ if (isAsyncDependency(dependency)) {
+ codeBlocks.add(
+ CodeBlock.of(
+ "($T) $L.get($L)", asyncDependencyType(dependency), applyArgName(), argIndex));
+ argIndex++;
+ } else {
+ codeBlocks.add(frameworkTypeUsageStatement(dependency));
+ }
+ }
+ return codeBlocks.build();
}
@Override
@@ -489,25 +502,6 @@
}
}
- private static ImmutableList<CodeBlock> getParameterCodeBlocks(
- ProductionBinding binding, ImmutableMap<Key, FieldSpec> fields, String listArgName) {
- int argIndex = 0;
- ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
- for (DependencyRequest dependency : binding.explicitDependencies()) {
- if (isAsyncDependency(dependency)) {
- codeBlocks.add(
- CodeBlock.of(
- "($T) $L.get($L)", asyncDependencyType(dependency), listArgName, argIndex));
- argIndex++;
- } else {
- codeBlocks.add(
- frameworkTypeUsageStatement(
- CodeBlock.of("$N", fields.get(dependency.key())), dependency.kind()));
- }
- }
- return codeBlocks.build();
- }
-
/**
* Creates a code block for the invocation of the producer method from the module, which should be
* used entirely within a method body.
diff --git a/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
index 5ad9236..aca9756 100644
--- a/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
@@ -22,6 +22,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.javapoet.TypeNames;
import dagger.model.RequestKind;
import dagger.producers.Producer;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java b/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java
index 5c7dd01..18818d5 100644
--- a/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/ProducerNodeInstanceBindingExpression.java
@@ -20,6 +20,9 @@
import com.squareup.javapoet.ClassName;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
/** Binding expression for producer node instances. */
diff --git a/java/dagger/internal/codegen/ProducesMethodValidator.java b/java/dagger/internal/codegen/ProducesMethodValidator.java
index 4003706..bf45948 100644
--- a/java/dagger/internal/codegen/ProducesMethodValidator.java
+++ b/java/dagger/internal/codegen/ProducesMethodValidator.java
@@ -17,13 +17,15 @@
package dagger.internal.codegen;
import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsScoping.NO_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.EXCEPTION;
import com.google.auto.common.MoreTypes;
import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.multibindings.ElementsIntoSet;
import dagger.producers.ProducerModule;
import dagger.producers.Produces;
@@ -34,9 +36,7 @@
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
-/**
- * A validator for {@link Produces} methods.
- */
+/** A validator for {@link Produces} methods. */
final class ProducesMethodValidator extends BindingMethodValidator {
@Inject
@@ -57,70 +57,77 @@
}
@Override
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- super.checkMethod(builder);
- checkNullable(builder);
- }
-
- /** Adds a warning if a {@link Produces @Produces} method is declared nullable. */
- // TODO(beder): Properly handle nullable with producer methods.
- private void checkNullable(ValidationReport.Builder<ExecutableElement> builder) {
- if (ConfigurationAnnotations.getNullableType(builder.getSubject()).isPresent()) {
- builder.addWarning("@Nullable on @Produces methods does not do anything");
- }
+ protected String elementsIntoSetNotASetMessage() {
+ return "@Produces methods of type set values must return a Set or ListenableFuture of Set";
}
@Override
- protected String badReturnTypeMessage() {
+ protected String badTypeMessage() {
return "@Produces methods can return only a primitive, an array, a type variable, "
+ "a declared type, or a ListenableFuture of one of those types";
}
- /**
- * {@inheritDoc}
- *
- * <p>Allows {@code keyType} to be a {@link ListenableFuture} of an otherwise-valid key type.
- */
@Override
- protected void checkKeyType(
- ValidationReport.Builder<ExecutableElement> reportBuilder, TypeMirror keyType) {
- Optional<TypeMirror> typeToCheck = unwrapListenableFuture(reportBuilder, keyType);
- if (typeToCheck.isPresent()) {
- super.checkKeyType(reportBuilder, typeToCheck.get());
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
+ }
+
+ private class Validator extends MethodValidator {
+ Validator(ExecutableElement element) {
+ super(element);
}
- }
- /**
- * {@inheritDoc}
- *
- * <p>Allows an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method to return a
- * {@link ListenableFuture} of a {@link Set} as well.
- */
- @Override
- protected void checkSetValuesType(ValidationReport.Builder<ExecutableElement> builder) {
- Optional<TypeMirror> typeToCheck =
- unwrapListenableFuture(builder, builder.getSubject().getReturnType());
- if (typeToCheck.isPresent()) {
- checkSetValuesType(builder, typeToCheck.get());
+ @Override
+ protected void checkAdditionalMethodProperties() {
+ checkNullable();
}
- }
- @Override
- protected String badSetValuesTypeMessage() {
- return "@Produces methods of type set values must return a Set or ListenableFuture of Set";
- }
-
- private static Optional<TypeMirror> unwrapListenableFuture(
- ValidationReport.Builder<ExecutableElement> reportBuilder, TypeMirror type) {
- if (MoreTypes.isType(type) && MoreTypes.isTypeOf(ListenableFuture.class, type)) {
- DeclaredType declaredType = MoreTypes.asDeclared(type);
- if (declaredType.getTypeArguments().isEmpty()) {
- reportBuilder.addError("@Produces methods cannot return a raw ListenableFuture");
- return Optional.empty();
- } else {
- return Optional.of((TypeMirror) getOnlyElement(declaredType.getTypeArguments()));
+ /** Adds a warning if a {@link Produces @Produces} method is declared nullable. */
+ // TODO(beder): Properly handle nullable with producer methods.
+ private void checkNullable() {
+ if (ConfigurationAnnotations.getNullableType(element).isPresent()) {
+ report.addWarning("@Nullable on @Produces methods does not do anything");
}
}
- return Optional.of(type);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Allows {@code keyType} to be a {@link ListenableFuture} of an otherwise-valid key type.
+ */
+ @Override
+ protected void checkKeyType(TypeMirror keyType) {
+ Optional<TypeMirror> typeToCheck = unwrapListenableFuture(keyType);
+ if (typeToCheck.isPresent()) {
+ super.checkKeyType(typeToCheck.get());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Allows an {@link ElementsIntoSet @ElementsIntoSet} or {@code SET_VALUES} method to return
+ * a {@link ListenableFuture} of a {@link Set} as well.
+ */
+ @Override
+ protected void checkSetValuesType() {
+ Optional<TypeMirror> typeToCheck = unwrapListenableFuture(element.getReturnType());
+ if (typeToCheck.isPresent()) {
+ checkSetValuesType(typeToCheck.get());
+ }
+ }
+
+ private Optional<TypeMirror> unwrapListenableFuture(TypeMirror type) {
+ if (MoreTypes.isType(type) && MoreTypes.isTypeOf(ListenableFuture.class, type)) {
+ DeclaredType declaredType = MoreTypes.asDeclared(type);
+ if (declaredType.getTypeArguments().isEmpty()) {
+ report.addError("@Produces methods cannot return a raw ListenableFuture");
+ return Optional.empty();
+ } else {
+ return Optional.of((TypeMirror) getOnlyElement(declaredType.getTypeArguments()));
+ }
+ }
+ return Optional.of(type);
+ }
}
}
diff --git a/java/dagger/internal/codegen/ProductionBinding.java b/java/dagger/internal/codegen/ProductionBinding.java
index d9c2645..a22f21c 100644
--- a/java/dagger/internal/codegen/ProductionBinding.java
+++ b/java/dagger/internal/codegen/ProductionBinding.java
@@ -17,7 +17,7 @@
package dagger.internal.codegen;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.DaggerTypes.isFutureType;
+import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
@@ -66,7 +66,7 @@
static ProductionKind fromProducesMethod(ExecutableElement producesMethod) {
if (isFutureType(producesMethod.getReturnType())) {
return FUTURE;
- } else if (ContributionType.fromBindingMethod(producesMethod)
+ } else if (ContributionType.fromBindingElement(producesMethod)
.equals(ContributionType.SET_VALUES)
&& isFutureType(SetType.from(producesMethod.getReturnType()).elementType())) {
return SET_OF_FUTURE;
diff --git a/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java b/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java
index aa8c815..60166de 100644
--- a/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/ProviderInstanceBindingExpression.java
@@ -16,6 +16,9 @@
package dagger.internal.codegen;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+
/** Binding expression for provider instances. */
final class ProviderInstanceBindingExpression extends FrameworkInstanceBindingExpression {
diff --git a/java/dagger/internal/codegen/ProvidesMethodValidator.java b/java/dagger/internal/codegen/ProvidesMethodValidator.java
index db24e66..01e71ae 100644
--- a/java/dagger/internal/codegen/ProvidesMethodValidator.java
+++ b/java/dagger/internal/codegen/ProvidesMethodValidator.java
@@ -16,22 +16,22 @@
package dagger.internal.codegen;
+import static dagger.internal.codegen.BindingElementValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
+import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.ALLOWS_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_CONCRETE;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsMultibindings.ALLOWS_MULTIBINDINGS;
-import static dagger.internal.codegen.BindingMethodValidator.AllowsScoping.ALLOWS_SCOPING;
import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.RUNTIME_EXCEPTION;
import com.google.common.collect.ImmutableSet;
import dagger.Module;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.producers.ProducerModule;
import javax.inject.Inject;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
-/**
- * A validator for {@link Provides} methods.
- */
+/** A validator for {@link Provides} methods. */
final class ProvidesMethodValidator extends BindingMethodValidator {
private final DependencyRequestValidator dependencyRequestValidator;
@@ -55,15 +55,24 @@
}
@Override
- protected void checkMethod(ValidationReport.Builder<ExecutableElement> builder) {
- super.checkMethod(builder);
+ protected ElementValidator elementValidator(ExecutableElement element) {
+ return new Validator(element);
}
- /** Adds an error if a {@link Provides @Provides} method depends on a producer type. */
- @Override
- protected void checkParameter(
- ValidationReport.Builder<ExecutableElement> builder, VariableElement parameter) {
- super.checkParameter(builder, parameter);
- dependencyRequestValidator.checkNotProducer(builder, parameter);
+ private class Validator extends MethodValidator {
+ Validator(ExecutableElement element) {
+ super(element);
+ }
+
+ @Override
+ protected void checkAdditionalMethodProperties() {
+ }
+
+ /** Adds an error if a {@link Provides @Provides} method depends on a producer type. */
+ @Override
+ protected void checkParameter(VariableElement parameter) {
+ super.checkParameter(parameter);
+ dependencyRequestValidator.checkNotProducer(report, parameter);
+ }
}
}
diff --git a/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
index f76c49c..6eb92ac 100644
--- a/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
@@ -20,6 +20,8 @@
import com.squareup.javapoet.CodeBlock;
import dagger.internal.MissingBindingFactory;
import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.producers.internal.MissingBindingProducer;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/RequestKinds.java b/java/dagger/internal/codegen/RequestKinds.java
index 3c6b2f0..aa17f5e 100644
--- a/java/dagger/internal/codegen/RequestKinds.java
+++ b/java/dagger/internal/codegen/RequestKinds.java
@@ -21,12 +21,12 @@
import static com.google.auto.common.MoreTypes.isTypeOf;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.DaggerTypes.checkTypePresent;
-import static dagger.internal.codegen.TypeNames.lazyOf;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.TypeNames.producedOf;
-import static dagger.internal.codegen.TypeNames.producerOf;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.lazyOf;
+import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producedOf;
+import static dagger.internal.codegen.javapoet.TypeNames.producerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.langmodel.DaggerTypes.checkTypePresent;
import static dagger.model.RequestKind.INSTANCE;
import static dagger.model.RequestKind.LAZY;
import static dagger.model.RequestKind.PRODUCED;
@@ -39,6 +39,7 @@
import com.google.common.util.concurrent.ListenableFuture;
import com.squareup.javapoet.TypeName;
import dagger.Lazy;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.RequestKind;
import dagger.producers.Produced;
import dagger.producers.Producer;
diff --git a/java/dagger/internal/codegen/Scopes.java b/java/dagger/internal/codegen/Scopes.java
index e188f9b..252f712 100644
--- a/java/dagger/internal/codegen/Scopes.java
+++ b/java/dagger/internal/codegen/Scopes.java
@@ -22,6 +22,7 @@
import com.google.auto.common.AnnotationMirrors;
import com.google.common.collect.ImmutableSet;
+import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.model.Scope;
import dagger.producers.ProductionScope;
import java.lang.annotation.Annotation;
diff --git a/java/dagger/internal/codegen/SetBindingExpression.java b/java/dagger/internal/codegen/SetBindingExpression.java
index e6a3a68..5efb85f 100644
--- a/java/dagger/internal/codegen/SetBindingExpression.java
+++ b/java/dagger/internal/codegen/SetBindingExpression.java
@@ -17,15 +17,18 @@
package dagger.internal.codegen;
import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.BindingRequest.bindingRequest;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import static javax.lang.model.util.ElementFilter.methodsIn;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import dagger.internal.SetBuilder;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import java.util.Collections;
import java.util.Optional;
diff --git a/java/dagger/internal/codegen/SetFactoryCreationExpression.java b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
index d69f4a2..9712091 100644
--- a/java/dagger/internal/codegen/SetFactoryCreationExpression.java
+++ b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
@@ -20,6 +20,7 @@
import static dagger.internal.codegen.SourceFiles.setFactoryClassName;
import com.squareup.javapoet.CodeBlock;
+import dagger.model.DependencyRequest;
import dagger.producers.Produced;
import java.util.Optional;
@@ -69,9 +70,9 @@
setProviders++;
}
- for (FrameworkDependency frameworkDependency : frameworkDependenciesToImplement()) {
+ for (DependencyRequest dependency : dependenciesToImplement()) {
ContributionType contributionType =
- graph.contributionBindings().get(frameworkDependency.key()).contributionType();
+ graph.contributionBindings().get(dependency.key()).contributionType();
String methodNamePrefix;
switch (contributionType) {
case SET:
@@ -83,14 +84,14 @@
methodNamePrefix = "addCollection";
break;
default:
- throw new AssertionError(frameworkDependency + " is not a set multibinding");
+ throw new AssertionError(dependency + " is not a set multibinding");
}
builderMethodCalls.add(
".$N$N($L)",
methodNamePrefix,
methodNameSuffix,
- multibindingDependencyExpression(frameworkDependency));
+ multibindingDependencyExpression(dependency));
}
builder.add("builder($L, $L)", individualProviders, setProviders);
builder.add(builderMethodCalls.build());
diff --git a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
index 3bd908f..805ac7b 100644
--- a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
@@ -18,10 +18,10 @@
import static com.google.auto.common.MoreElements.asExecutable;
import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
import static dagger.internal.codegen.InjectionMethods.ProvisionMethod.requiresInjectionMethod;
-import static dagger.internal.codegen.TypeNames.rawTypeName;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
+import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableMap;
@@ -31,9 +31,13 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import dagger.internal.codegen.InjectionMethods.ProvisionMethod;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.DependencyRequest;
import java.util.Optional;
import java.util.function.Function;
+import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.DeclaredType;
@@ -51,6 +55,7 @@
private final ComponentRequirementExpressions componentRequirementExpressions;
private final DaggerTypes types;
private final DaggerElements elements;
+ private final SourceVersion sourceVersion;
SimpleMethodBindingExpression(
ResolvedBindings resolvedBindings,
@@ -59,7 +64,8 @@
MembersInjectionMethods membersInjectionMethods,
ComponentRequirementExpressions componentRequirementExpressions,
DaggerTypes types,
- DaggerElements elements) {
+ DaggerElements elements,
+ SourceVersion sourceVersion) {
super(resolvedBindings);
this.compilerOptions = compilerOptions;
this.provisionBinding = (ProvisionBinding) resolvedBindings.contributionBinding();
@@ -72,6 +78,7 @@
this.componentRequirementExpressions = componentRequirementExpressions;
this.types = types;
this.elements = elements;
+ this.sourceVersion = sourceVersion;
}
@Override
@@ -151,14 +158,15 @@
if (provisionBinding.injectionSites().isEmpty()) {
return Expression.create(simpleMethodReturnType(), instance);
}
- // Java 7 type inference can't figure out that instance in
- // injectParameterized(Parameterized_Factory.newParameterized()) is Parameterized<T> and not
- // Parameterized<Object>
- if (!MoreTypes.asDeclared(provisionBinding.key().type()).getTypeArguments().isEmpty()) {
- TypeName keyType = TypeName.get(provisionBinding.key().type());
- instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
+ if (sourceVersion.compareTo(SourceVersion.RELEASE_7) <= 0) {
+ // Java 7 type inference can't figure out that instance in
+ // injectParameterized(Parameterized_Factory.newParameterized()) is Parameterized<T> and not
+ // Parameterized<Object>
+ if (!MoreTypes.asDeclared(provisionBinding.key().type()).getTypeArguments().isEmpty()) {
+ TypeName keyType = TypeName.get(provisionBinding.key().type());
+ instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
+ }
}
-
MethodSpec membersInjectionMethod = membersInjectionMethods.getOrCreate(provisionBinding.key());
TypeMirror returnType =
membersInjectionMethod.returnType.equals(TypeName.OBJECT)
diff --git a/java/dagger/internal/codegen/SourceFileGenerator.java b/java/dagger/internal/codegen/SourceFileGenerator.java
index 747acf6..7dddc2f 100644
--- a/java/dagger/internal/codegen/SourceFileGenerator.java
+++ b/java/dagger/internal/codegen/SourceFileGenerator.java
@@ -24,6 +24,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Optional;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
@@ -38,7 +39,7 @@
* @param <T> The input type from which source is to be generated.
*/
abstract class SourceFileGenerator<T> {
- private static final String GENERATED_COMMENTS = "https://google.github.io/dagger";
+ private static final String GENERATED_COMMENTS = "https://dagger.dev";
private final Filer filer;
private final DaggerElements elements;
diff --git a/java/dagger/internal/codegen/SourceFiles.java b/java/dagger/internal/codegen/SourceFiles.java
index d7ce535..fd93d0d 100644
--- a/java/dagger/internal/codegen/SourceFiles.java
+++ b/java/dagger/internal/codegen/SourceFiles.java
@@ -24,16 +24,16 @@
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.Optionals.optionalComparator;
-import static dagger.internal.codegen.TypeNames.DOUBLE_CHECK;
-import static dagger.internal.codegen.TypeNames.MAP_FACTORY;
-import static dagger.internal.codegen.TypeNames.MAP_OF_PRODUCED_PRODUCER;
-import static dagger.internal.codegen.TypeNames.MAP_OF_PRODUCER_PRODUCER;
-import static dagger.internal.codegen.TypeNames.MAP_PRODUCER;
-import static dagger.internal.codegen.TypeNames.MAP_PROVIDER_FACTORY;
-import static dagger.internal.codegen.TypeNames.PROVIDER_OF_LAZY;
-import static dagger.internal.codegen.TypeNames.SET_FACTORY;
-import static dagger.internal.codegen.TypeNames.SET_OF_PRODUCED_PRODUCER;
-import static dagger.internal.codegen.TypeNames.SET_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.DOUBLE_CHECK;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCED_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_OF_PRODUCER_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.MAP_PROVIDER_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER_OF_LAZY;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_OF_PRODUCED_PRODUCER;
+import static dagger.internal.codegen.javapoet.TypeNames.SET_PRODUCER;
import static dagger.model.BindingKind.INJECTION;
import static dagger.model.BindingKind.MULTIBOUND_MAP;
import static dagger.model.BindingKind.MULTIBOUND_SET;
@@ -201,10 +201,8 @@
case MEMBERS_INJECTION:
return membersInjectorNameForType(
((MembersInjectionBinding) binding).membersInjectedType());
-
- default:
- throw new AssertionError();
}
+ throw new AssertionError();
}
/**
@@ -247,10 +245,6 @@
return siblingClassName(componentElement, "_MonitoringModule");
}
- static ClassName generatedProductionExecutorModuleName(TypeElement componentElement) {
- return siblingClassName(componentElement, "_ProductionExecutorModule");
- }
-
// TODO(ronshapiro): when JavaPoet migration is complete, replace the duplicated code
// which could use this.
private static ClassName siblingClassName(TypeElement typeElement, String suffix) {
diff --git a/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java b/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java
index 782feb8..c97024e 100644
--- a/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java
+++ b/java/dagger/internal/codegen/SubcomponentCreatorBindingEdgeImpl.java
@@ -17,6 +17,8 @@
package dagger.internal.codegen;
import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.DaggerStreams.presentValues;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableSet;
@@ -26,23 +28,27 @@
/** An implementation of {@link SubcomponentCreatorBindingEdge}. */
final class SubcomponentCreatorBindingEdgeImpl implements SubcomponentCreatorBindingEdge {
- private final ImmutableSet<TypeElement> declaringModules;
+ private final ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations;
- SubcomponentCreatorBindingEdgeImpl(Iterable<TypeElement> declaringModules) {
- this.declaringModules = ImmutableSet.copyOf(declaringModules);
+ SubcomponentCreatorBindingEdgeImpl(
+ ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
+ this.subcomponentDeclarations = subcomponentDeclarations;
}
@Override
public ImmutableSet<TypeElement> declaringModules() {
- return declaringModules;
+ return subcomponentDeclarations.stream()
+ .map(SubcomponentDeclaration::contributingModule)
+ .flatMap(presentValues())
+ .collect(toImmutableSet());
}
@Override
public String toString() {
return "subcomponent declared by "
- + (declaringModules.size() == 1
- ? getOnlyElement(declaringModules).getQualifiedName()
- : declaringModules.stream()
+ + (subcomponentDeclarations.size() == 1
+ ? getOnlyElement(declaringModules()).getQualifiedName()
+ : declaringModules().stream()
.map(TypeElement::getQualifiedName)
.collect(joining(", ", "{", "}")));
}
diff --git a/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java b/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java
index 510e8c4..b415d3f 100644
--- a/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java
+++ b/java/dagger/internal/codegen/SubcomponentCreatorBindingExpression.java
@@ -17,6 +17,7 @@
package dagger.internal.codegen;
import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.javapoet.Expression;
import javax.lang.model.type.TypeMirror;
/** A binding expression for a subcomponent creator that just invokes the constructor. */
diff --git a/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java
index 7d95ee4..0c6a006 100644
--- a/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java
+++ b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidator.java
@@ -29,6 +29,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.BindingGraph;
import dagger.model.BindingGraph.ChildFactoryMethodEdge;
import dagger.model.BindingGraph.ComponentNode;
diff --git a/java/dagger/internal/codegen/SwitchingProviders.java b/java/dagger/internal/codegen/SwitchingProviders.java
index f1fe857..29633d9 100644
--- a/java/dagger/internal/codegen/SwitchingProviders.java
+++ b/java/dagger/internal/codegen/SwitchingProviders.java
@@ -21,10 +21,10 @@
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.AnnotationSpecs.suppressWarnings;
import static dagger.internal.codegen.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -35,6 +35,9 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import java.util.HashMap;
import java.util.LinkedHashMap;
diff --git a/java/dagger/internal/codegen/TypeNames.java b/java/dagger/internal/codegen/TypeNames.java
deleted file mode 100644
index 2b590d4..0000000
--- a/java/dagger/internal/codegen/TypeNames.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2016 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen;
-
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
-import dagger.Lazy;
-import dagger.MembersInjector;
-import dagger.internal.DoubleCheck;
-import dagger.internal.Factory;
-import dagger.internal.InstanceFactory;
-import dagger.internal.MapFactory;
-import dagger.internal.MapProviderFactory;
-import dagger.internal.MembersInjectors;
-import dagger.internal.ProviderOfLazy;
-import dagger.internal.SetFactory;
-import dagger.internal.SingleCheck;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.producers.internal.AbstractProducer;
-import dagger.producers.internal.DependencyMethodProducer;
-import dagger.producers.internal.MapOfProducedProducer;
-import dagger.producers.internal.MapOfProducerProducer;
-import dagger.producers.internal.MapProducer;
-import dagger.producers.internal.Producers;
-import dagger.producers.internal.SetOfProducedProducer;
-import dagger.producers.internal.SetProducer;
-import dagger.producers.monitoring.ProducerToken;
-import dagger.producers.monitoring.ProductionComponentMonitor;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import javax.inject.Provider;
-
-/**
- * Common names and convenience methods for JavaPoet {@link TypeName} usage.
- */
-final class TypeNames {
-
- static final ClassName ABSTRACT_PRODUCER = ClassName.get(AbstractProducer.class);
- static final ClassName ASYNC_FUNCTION = ClassName.get(AsyncFunction.class);
- static final ClassName DEPENDENCY_METHOD_PRODUCER = ClassName.get(DependencyMethodProducer.class);
- static final ClassName DOUBLE_CHECK = ClassName.get(DoubleCheck.class);
- static final ClassName EXECUTOR = ClassName.get(Executor.class);
- static final ClassName FACTORY = ClassName.get(Factory.class);
- static final ClassName FUTURES = ClassName.get(Futures.class);
- static final ClassName INSTANCE_FACTORY = ClassName.get(InstanceFactory.class);
- static final ClassName LAZY = ClassName.get(Lazy.class);
- static final ClassName LIST = ClassName.get(List.class);
- static final ClassName LISTENABLE_FUTURE = ClassName.get(ListenableFuture.class);
- static final ClassName MAP_FACTORY = ClassName.get(MapFactory.class);
- static final ClassName MAP_OF_PRODUCED_PRODUCER = ClassName.get(MapOfProducedProducer.class);
- static final ClassName MAP_OF_PRODUCER_PRODUCER = ClassName.get(MapOfProducerProducer.class);
- static final ClassName MAP_PRODUCER = ClassName.get(MapProducer.class);
- static final ClassName MAP_PROVIDER_FACTORY = ClassName.get(MapProviderFactory.class);
- static final ClassName MEMBERS_INJECTOR = ClassName.get(MembersInjector.class);
- static final ClassName MEMBERS_INJECTORS = ClassName.get(MembersInjectors.class);
- static final ClassName OPTIONAL = ClassName.get(Optional.class);
- static final ClassName PRODUCER_TOKEN = ClassName.get(ProducerToken.class);
- static final ClassName PRODUCED = ClassName.get(Produced.class);
- static final ClassName PRODUCER = ClassName.get(Producer.class);
- static final ClassName PRODUCERS = ClassName.get(Producers.class);
- static final ClassName PRODUCTION_COMPONENT_MONITOR_FACTORY =
- ClassName.get(ProductionComponentMonitor.Factory.class);
- static final ClassName PROVIDER = ClassName.get(Provider.class);
- static final ClassName PROVIDER_OF_LAZY = ClassName.get(ProviderOfLazy.class);
- static final ClassName RUNNABLE = ClassName.get(Runnable.class);
- static final ClassName SET = ClassName.get(Set.class);
- static final ClassName SET_FACTORY = ClassName.get(SetFactory.class);
- static final ClassName SET_OF_PRODUCED_PRODUCER = ClassName.get(SetOfProducedProducer.class);
- static final ClassName SET_PRODUCER = ClassName.get(SetProducer.class);
- static final ClassName SINGLE_CHECK = ClassName.get(SingleCheck.class);
-
- /**
- * {@link TypeName#VOID} is lowercase-v {@code void} whereas this represents the class, {@link
- * Void}.
- */
- static final ClassName VOID_CLASS = ClassName.get(Void.class);
-
- static ParameterizedTypeName abstractProducerOf(TypeName typeName) {
- return ParameterizedTypeName.get(ABSTRACT_PRODUCER, typeName);
- }
-
- static ParameterizedTypeName factoryOf(TypeName factoryType) {
- return ParameterizedTypeName.get(FACTORY, factoryType);
- }
-
- static ParameterizedTypeName lazyOf(TypeName typeName) {
- return ParameterizedTypeName.get(LAZY, typeName);
- }
-
- static ParameterizedTypeName listOf(TypeName typeName) {
- return ParameterizedTypeName.get(LIST, typeName);
- }
-
- static ParameterizedTypeName listenableFutureOf(TypeName typeName) {
- return ParameterizedTypeName.get(LISTENABLE_FUTURE, typeName);
- }
-
- static ParameterizedTypeName membersInjectorOf(TypeName membersInjectorType) {
- return ParameterizedTypeName.get(MEMBERS_INJECTOR, membersInjectorType);
- }
-
- static ParameterizedTypeName optionalOf(TypeName type) {
- return ParameterizedTypeName.get(OPTIONAL, type);
- }
-
- static ParameterizedTypeName producedOf(TypeName typeName) {
- return ParameterizedTypeName.get(PRODUCED, typeName);
- }
-
- static ParameterizedTypeName producerOf(TypeName typeName) {
- return ParameterizedTypeName.get(PRODUCER, typeName);
- }
-
- static ParameterizedTypeName dependencyMethodProducerOf(TypeName typeName) {
- return ParameterizedTypeName.get(DEPENDENCY_METHOD_PRODUCER, typeName);
- }
-
- static ParameterizedTypeName providerOf(TypeName typeName) {
- return ParameterizedTypeName.get(PROVIDER, typeName);
- }
-
- static ParameterizedTypeName setOf(TypeName elementType) {
- return ParameterizedTypeName.get(SET, elementType);
- }
-
- /**
- * Returns the {@link TypeName} for the raw type of the given type name. If the argument isn't a
- * parameterized type, it returns the argument unchanged.
- */
- static TypeName rawTypeName(TypeName typeName) {
- return (typeName instanceof ParameterizedTypeName)
- ? ((ParameterizedTypeName) typeName).rawType
- : typeName;
- }
-
- private TypeNames() {}
-}
diff --git a/java/dagger/internal/codegen/TypeProtoConverter.java b/java/dagger/internal/codegen/TypeProtoConverter.java
new file mode 100644
index 0000000..c703bd8
--- /dev/null
+++ b/java/dagger/internal/codegen/TypeProtoConverter.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static javax.lang.model.util.ElementFilter.typesIn;
+
+import com.google.auto.common.MoreTypes;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.TypeProto;
+import dagger.internal.codegen.serialization.TypeProto.PrimitiveKind;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.WildcardType;
+
+/** Converts {@link TypeMirror}s to {@link TypeProto}s and vice-versa. */
+final class TypeProtoConverter {
+ // TODO(ronshapiro): if DaggerTypes and DaggerElements become public, move this file to
+ // dagger.internal.codegen.serialization
+ private final DaggerTypes types;
+ private final DaggerElements elements;
+
+ @Inject
+ TypeProtoConverter(DaggerTypes types, DaggerElements elements) {
+ this.types = types;
+ this.elements = elements;
+ }
+
+ /** Translates a {@link TypeMirror} to a proto representation. */
+ static TypeProto toProto(TypeMirror type) {
+ TypeProto.Builder builder = TypeProto.newBuilder();
+ int arrayDimensions = 0;
+ while (type.getKind().equals(TypeKind.ARRAY)) {
+ type = MoreTypes.asArray(type).getComponentType();
+ arrayDimensions++;
+ }
+ builder.setArrayDimensions(arrayDimensions);
+ if (type.getKind().isPrimitive()) {
+ builder.setPrimitiveKind(PrimitiveKind.valueOf(type.getKind().name()));
+ } else if (type.getKind().equals(TypeKind.WILDCARD)) {
+ WildcardType wildcardType = MoreTypes.asWildcard(type);
+ TypeProto.Wildcard.Builder wildcardBuilder = TypeProto.Wildcard.newBuilder();
+ if (wildcardType.getExtendsBound() != null) {
+ wildcardBuilder.setExtendsBound(toProto(wildcardType.getExtendsBound()));
+ } else if (wildcardType.getSuperBound() != null) {
+ wildcardBuilder.setSuperBound(toProto(wildcardType.getSuperBound()));
+ }
+ builder.setWildcard(wildcardBuilder);
+ } else {
+ TypeElement typeElement = MoreTypes.asTypeElement(type);
+ DeclaredType declaredType = MoreTypes.asDeclared(type);
+ TypeMirror enclosingType = declaredType.getEnclosingType();
+ if (enclosingType.getKind().equals(TypeKind.NONE)) {
+ builder.setQualifiedName(typeElement.getQualifiedName().toString());
+ } else {
+ builder
+ .setEnclosingType(toProto(enclosingType))
+ .setSimpleName(typeElement.getSimpleName().toString());
+ }
+ declaredType.getTypeArguments().stream()
+ .map(TypeProtoConverter::toProto)
+ .forEachOrdered(builder::addTypeArguments);
+ }
+ return builder.build();
+ }
+
+ /** Creates an {@link TypeMirror} from its proto representation. */
+ TypeMirror fromProto(TypeProto type) {
+ if (type.hasWildcard()) {
+ return wildcardType(type.getWildcard());
+ }
+
+ TypeMirror[] typeArguments =
+ type.getTypeArgumentsList().stream().map(this::fromProto).toArray(TypeMirror[]::new);
+ TypeMirror typeMirror;
+ if (!type.getPrimitiveKind().equals(PrimitiveKind.UNKNOWN)) {
+ typeMirror = types.getPrimitiveType(TypeKind.valueOf(type.getPrimitiveKind().name()));
+ } else if (type.hasEnclosingType()) {
+ DeclaredType enclosingType = MoreTypes.asDeclared(fromProto(type.getEnclosingType()));
+ TypeElement typeElement =
+ typesIn(enclosingType.asElement().getEnclosedElements()).stream()
+ .filter(inner -> inner.getSimpleName().contentEquals(type.getSimpleName()))
+ .findFirst()
+ .get();
+ typeMirror = types.getDeclaredType(enclosingType, typeElement, typeArguments);
+ } else {
+ typeMirror =
+ types.getDeclaredType(elements.getTypeElement(type.getQualifiedName()), typeArguments);
+ }
+ for (int i = 0; i < type.getArrayDimensions(); i++) {
+ typeMirror = types.getArrayType(typeMirror);
+ }
+ return typeMirror;
+ }
+
+ private TypeMirror wildcardType(TypeProto.Wildcard wildcard) {
+ if (wildcard.hasExtendsBound()) {
+ return types.getWildcardType(fromProto(wildcard.getExtendsBound()), null);
+ } else if (wildcard.hasSuperBound()) {
+ return types.getWildcardType(null, fromProto(wildcard.getSuperBound()));
+ } else {
+ return types.getWildcardType(null, null);
+ }
+ }
+}
diff --git a/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java b/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java
index 9f7e40c..2b7b02c 100644
--- a/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java
+++ b/java/dagger/internal/codegen/UnwrappedMapKeyGenerator.java
@@ -17,6 +17,7 @@
package dagger.internal.codegen;
import dagger.MapKey;
+import dagger.internal.codegen.langmodel.DaggerElements;
import java.util.Set;
import javax.annotation.processing.Filer;
import javax.inject.Inject;
diff --git a/java/dagger/internal/codegen/Util.java b/java/dagger/internal/codegen/Util.java
index 7a56944..1869b7c 100644
--- a/java/dagger/internal/codegen/Util.java
+++ b/java/dagger/internal/codegen/Util.java
@@ -77,10 +77,9 @@
case ANONYMOUS:
case LOCAL:
return true;
- default:
- throw new AssertionError(
- "TypeElement cannot have nesting kind: " + typeElement.getNestingKind());
}
+ throw new AssertionError(
+ "TypeElement cannot have nesting kind: " + typeElement.getNestingKind());
}
/**
diff --git a/java/dagger/internal/codegen/ValidationReport.java b/java/dagger/internal/codegen/ValidationReport.java
index 0a3765a..d7c3252 100644
--- a/java/dagger/internal/codegen/ValidationReport.java
+++ b/java/dagger/internal/codegen/ValidationReport.java
@@ -16,8 +16,8 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.DaggerElements.elementToString;
import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.ElementFormatter.elementToString;
import static javax.tools.Diagnostic.Kind.ERROR;
import static javax.tools.Diagnostic.Kind.NOTE;
import static javax.tools.Diagnostic.Kind.WARNING;
diff --git a/java/dagger/internal/codegen/AnnotationSpecs.java b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
similarity index 77%
rename from java/dagger/internal/codegen/AnnotationSpecs.java
rename to java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
index 06416f9..cc0d7de 100644
--- a/java/dagger/internal/codegen/AnnotationSpecs.java
+++ b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -24,8 +24,10 @@
import com.squareup.javapoet.AnnotationSpec;
import java.util.Arrays;
-final class AnnotationSpecs {
- enum Suppression {
+/** Static factories to create {@link AnnotationSpec}s. */
+public final class AnnotationSpecs {
+ /** Values for an {@link SuppressWarnings} annotation. */
+ public enum Suppression {
RAWTYPES,
UNCHECKED,
;
@@ -36,7 +38,8 @@
}
}
- static AnnotationSpec suppressWarnings(Suppression first, Suppression... rest) {
+ /** Creates an {@link AnnotationSpec} for {@link SuppressWarnings}. */
+ public static AnnotationSpec suppressWarnings(Suppression first, Suppression... rest) {
checkNotNull(first);
Arrays.stream(rest).forEach(Preconditions::checkNotNull);
AnnotationSpec.Builder builder = AnnotationSpec.builder(SuppressWarnings.class);
diff --git a/java/dagger/internal/codegen/javapoet/BUILD b/java/dagger/internal/codegen/javapoet/BUILD
new file mode 100644
index 0000000..f829d49
--- /dev/null
+++ b/java/dagger/internal/codegen/javapoet/BUILD
@@ -0,0 +1,34 @@
+# Copyright (C) 2017 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Description:
+# JavaPoet extensions for use in Dagger
+
+package(default_visibility = ["//:src"])
+
+java_library(
+ name = "javapoet",
+ srcs = glob(["*.java"]),
+ plugins = ["//java/dagger/internal/codegen:bootstrap_compiler_plugin"],
+ tags = ["maven:merged"],
+ deps = [
+ "//java/dagger:core",
+ "//java/dagger/internal/codegen/langmodel",
+ "//java/dagger/producers",
+ "@google_bazel_common//third_party/java/auto:common",
+ "@google_bazel_common//third_party/java/error_prone:annotations",
+ "@google_bazel_common//third_party/java/guava",
+ "@google_bazel_common//third_party/java/javapoet",
+ ],
+)
diff --git a/java/dagger/internal/codegen/CodeBlocks.java b/java/dagger/internal/codegen/javapoet/CodeBlocks.java
similarity index 79%
rename from java/dagger/internal/codegen/CodeBlocks.java
rename to java/dagger/internal/codegen/javapoet/CodeBlocks.java
index e551aeb..3e9f75d 100644
--- a/java/dagger/internal/codegen/CodeBlocks.java
+++ b/java/dagger/internal/codegen/javapoet/CodeBlocks.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static dagger.internal.codegen.TypeNames.providerOf;
-import static dagger.internal.codegen.TypeNames.rawTypeName;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
import static java.util.stream.StreamSupport.stream;
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -35,24 +35,25 @@
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
-final class CodeBlocks {
+/** Convenience methods for creating {@link CodeBlock}s. */
+public final class CodeBlocks {
/**
* Joins {@link CodeBlock} instances in a manner suitable for use as method parameters (or
* arguments).
*/
- static Collector<CodeBlock, ?, CodeBlock> toParametersCodeBlock() {
+ public static Collector<CodeBlock, ?, CodeBlock> toParametersCodeBlock() {
// TODO(ronshapiro,jakew): consider adding zero-width spaces to help line breaking when the
// formatter is off. If not, inline this
return CodeBlock.joining(", ");
}
/** Concatenates {@link CodeBlock} instances separated by newlines for readability. */
- static Collector<CodeBlock, ?, CodeBlock> toConcatenatedCodeBlock() {
+ public static Collector<CodeBlock, ?, CodeBlock> toConcatenatedCodeBlock() {
return CodeBlock.joining("\n", "", "\n");
}
/** Returns a comma-separated version of {@code codeBlocks} as one unified {@link CodeBlock}. */
- static CodeBlock makeParametersCodeBlock(Iterable<CodeBlock> codeBlocks) {
+ public static CodeBlock makeParametersCodeBlock(Iterable<CodeBlock> codeBlocks) {
return stream(codeBlocks.spliterator(), false).collect(toParametersCodeBlock());
}
@@ -60,7 +61,7 @@
* Returns a comma-separated {@link CodeBlock} using the name of every parameter in {@code
* parameters}.
*/
- static CodeBlock parameterNames(Iterable<ParameterSpec> parameters) {
+ public static CodeBlock parameterNames(Iterable<ParameterSpec> parameters) {
// TODO(ronshapiro): Add DaggerStreams.stream(Iterable)
return stream(parameters.spliterator(), false)
.map(p -> CodeBlock.of("$N", p))
@@ -71,12 +72,12 @@
* Returns one unified {@link CodeBlock} which joins each item in {@code codeBlocks} with a
* newline.
*/
- static CodeBlock concat(Iterable<CodeBlock> codeBlocks) {
+ public static CodeBlock concat(Iterable<CodeBlock> codeBlocks) {
return stream(codeBlocks.spliterator(), false).collect(toConcatenatedCodeBlock());
}
/** Adds an annotation to a method. */
- static void addAnnotation(MethodSpec.Builder method, DeclaredType nullableType) {
+ public static void addAnnotation(MethodSpec.Builder method, DeclaredType nullableType) {
method.addAnnotation(ClassName.get(MoreTypes.asTypeElement(nullableType)));
}
@@ -84,7 +85,7 @@
* Returns an anonymous {@link javax.inject.Provider} class with the single {@link
* javax.inject.Provider#get()} method that returns the given {@code expression}.
*/
- static CodeBlock anonymousProvider(Expression expression) {
+ public static CodeBlock anonymousProvider(Expression expression) {
// More of a precondition check that the type Provider is parameterized with is a DeclaredType
DeclaredType type = MoreTypes.asDeclared(expression.type());
return anonymousProvider(
@@ -95,8 +96,9 @@
* Returns an anonymous {@link javax.inject.Provider} class with the single {@link
* javax.inject.Provider#get()} method implemented by {@code body}.
*/
- static CodeBlock anonymousProvider(TypeName providedType, CodeBlock body) {
- return CodeBlock.of("$L",
+ public static CodeBlock anonymousProvider(TypeName providedType, CodeBlock body) {
+ return CodeBlock.of(
+ "$L",
anonymousClassBuilder("")
.superclass(providerOf(providedType))
.addMethod(
@@ -110,20 +112,20 @@
}
/** Returns {@code expression} cast to a type. */
- static CodeBlock cast(CodeBlock expression, Class<?> castTo) {
+ public static CodeBlock cast(CodeBlock expression, Class<?> castTo) {
return CodeBlock.of("($T) $L", castTo, expression);
}
- static CodeBlock type(TypeMirror type) {
+ public static CodeBlock type(TypeMirror type) {
return CodeBlock.of("$T", type);
}
- static CodeBlock stringLiteral(String toWrap) {
+ public static CodeBlock stringLiteral(String toWrap) {
return CodeBlock.of("$S", toWrap);
}
/** Returns a javadoc {@literal @link} tag that poins to the given {@link ExecutableElement}. */
- static CodeBlock javadocLinkTo(ExecutableElement executableElement) {
+ public static CodeBlock javadocLinkTo(ExecutableElement executableElement) {
CodeBlock.Builder builder =
CodeBlock.builder()
.add(
@@ -146,9 +148,7 @@
}
builder.add("(");
builder.add(
- executableElement
- .getParameters()
- .stream()
+ executableElement.getParameters().stream()
.map(parameter -> CodeBlock.of("$T", rawTypeName(TypeName.get(parameter.asType()))))
.collect(toParametersCodeBlock()));
return builder.add(")}").build();
diff --git a/java/dagger/internal/codegen/Expression.java b/java/dagger/internal/codegen/javapoet/Expression.java
similarity index 85%
rename from java/dagger/internal/codegen/Expression.java
rename to java/dagger/internal/codegen/javapoet/Expression.java
index b6d215c..b79c55c 100644
--- a/java/dagger/internal/codegen/Expression.java
+++ b/java/dagger/internal/codegen/javapoet/Expression.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import com.google.auto.common.MoreTypes;
import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.lang.model.type.TypeMirror;
/**
@@ -34,7 +35,7 @@
* <p>An {@code Expression} for {@code fooImplProvider.get()} would have a {@link #type()} of {@code
* java.lang.Object} and not {@code FooImpl}.
*/
-final class Expression {
+public final class Expression {
private final TypeMirror type;
private final CodeBlock codeBlock;
@@ -44,7 +45,7 @@
}
/** Creates a new {@link Expression} with a {@link TypeMirror} and {@link CodeBlock}. */
- static Expression create(TypeMirror type, CodeBlock expression) {
+ public static Expression create(TypeMirror type, CodeBlock expression) {
return new Expression(type, expression);
}
@@ -52,14 +53,14 @@
* Creates a new {@link Expression} with a {@link TypeMirror}, {@linkplain CodeBlock#of(String,
* Object[]) format, and arguments}.
*/
- static Expression create(TypeMirror type, String format, Object... args) {
+ public static Expression create(TypeMirror type, String format, Object... args) {
return create(type, CodeBlock.of(format, args));
}
/** Returns a new expression that casts the current expression to {@code newType}. */
// TODO(ronshapiro): consider overloads that take a Types and Elements and only cast if necessary,
// or just embedding a Types/Elements instance in an Expression.
- Expression castTo(TypeMirror newType) {
+ public Expression castTo(TypeMirror newType) {
return create(newType, "($T) $L", newType, codeBlock);
}
@@ -67,19 +68,19 @@
* Returns a new expression that {@link #castTo(TypeMirror)} casts the current expression to its
* boxed type if this expression has a primitive type.
*/
- Expression box(DaggerTypes types) {
+ public Expression box(DaggerTypes types) {
return type.getKind().isPrimitive()
? castTo(types.boxedClass(MoreTypes.asPrimitiveType(type)).asType())
: this;
}
/** The {@link TypeMirror type} to which the expression evaluates. */
- TypeMirror type() {
+ public TypeMirror type() {
return type;
}
/** The code of the expression. */
- CodeBlock codeBlock() {
+ public CodeBlock codeBlock() {
return codeBlock;
}
diff --git a/java/dagger/internal/codegen/javapoet/TypeNames.java b/java/dagger/internal/codegen/javapoet/TypeNames.java
new file mode 100644
index 0000000..9301dbc
--- /dev/null
+++ b/java/dagger/internal/codegen/javapoet/TypeNames.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.javapoet;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import dagger.Lazy;
+import dagger.MembersInjector;
+import dagger.internal.DoubleCheck;
+import dagger.internal.Factory;
+import dagger.internal.InstanceFactory;
+import dagger.internal.MapFactory;
+import dagger.internal.MapProviderFactory;
+import dagger.internal.MembersInjectors;
+import dagger.internal.ProviderOfLazy;
+import dagger.internal.SetFactory;
+import dagger.internal.SingleCheck;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import dagger.producers.internal.AbstractProducer;
+import dagger.producers.internal.DependencyMethodProducer;
+import dagger.producers.internal.MapOfProducedProducer;
+import dagger.producers.internal.MapOfProducerProducer;
+import dagger.producers.internal.MapProducer;
+import dagger.producers.internal.Producers;
+import dagger.producers.internal.SetOfProducedProducer;
+import dagger.producers.internal.SetProducer;
+import dagger.producers.monitoring.ProducerToken;
+import dagger.producers.monitoring.ProductionComponentMonitor;
+import java.util.List;
+import java.util.Set;
+import javax.inject.Provider;
+
+/** Common names and convenience methods for JavaPoet {@link TypeName} usage. */
+public final class TypeNames {
+
+ public static final ClassName ABSTRACT_PRODUCER = ClassName.get(AbstractProducer.class);
+ public static final ClassName DEPENDENCY_METHOD_PRODUCER =
+ ClassName.get(DependencyMethodProducer.class);
+ public static final ClassName DOUBLE_CHECK = ClassName.get(DoubleCheck.class);
+ public static final ClassName FACTORY = ClassName.get(Factory.class);
+ public static final ClassName FUTURES = ClassName.get(Futures.class);
+ public static final ClassName INSTANCE_FACTORY = ClassName.get(InstanceFactory.class);
+ public static final ClassName LAZY = ClassName.get(Lazy.class);
+ public static final ClassName LIST = ClassName.get(List.class);
+ public static final ClassName LISTENABLE_FUTURE = ClassName.get(ListenableFuture.class);
+ public static final ClassName MAP_FACTORY = ClassName.get(MapFactory.class);
+ public static final ClassName MAP_OF_PRODUCED_PRODUCER =
+ ClassName.get(MapOfProducedProducer.class);
+ public static final ClassName MAP_OF_PRODUCER_PRODUCER =
+ ClassName.get(MapOfProducerProducer.class);
+ public static final ClassName MAP_PRODUCER = ClassName.get(MapProducer.class);
+ public static final ClassName MAP_PROVIDER_FACTORY = ClassName.get(MapProviderFactory.class);
+ public static final ClassName MEMBERS_INJECTOR = ClassName.get(MembersInjector.class);
+ public static final ClassName MEMBERS_INJECTORS = ClassName.get(MembersInjectors.class);
+ public static final ClassName PRODUCER_TOKEN = ClassName.get(ProducerToken.class);
+ public static final ClassName PRODUCED = ClassName.get(Produced.class);
+ public static final ClassName PRODUCER = ClassName.get(Producer.class);
+ public static final ClassName PRODUCERS = ClassName.get(Producers.class);
+ public static final ClassName PRODUCTION_COMPONENT_MONITOR_FACTORY =
+ ClassName.get(ProductionComponentMonitor.Factory.class);
+ public static final ClassName PROVIDER = ClassName.get(Provider.class);
+ public static final ClassName PROVIDER_OF_LAZY = ClassName.get(ProviderOfLazy.class);
+ public static final ClassName SET = ClassName.get(Set.class);
+ public static final ClassName SET_FACTORY = ClassName.get(SetFactory.class);
+ public static final ClassName SET_OF_PRODUCED_PRODUCER =
+ ClassName.get(SetOfProducedProducer.class);
+ public static final ClassName SET_PRODUCER = ClassName.get(SetProducer.class);
+ public static final ClassName SINGLE_CHECK = ClassName.get(SingleCheck.class);
+
+ /**
+ * {@link TypeName#VOID} is lowercase-v {@code void} whereas this represents the class, {@link
+ * Void}.
+ */
+ public static final ClassName VOID_CLASS = ClassName.get(Void.class);
+
+ public static ParameterizedTypeName abstractProducerOf(TypeName typeName) {
+ return ParameterizedTypeName.get(ABSTRACT_PRODUCER, typeName);
+ }
+
+ public static ParameterizedTypeName factoryOf(TypeName factoryType) {
+ return ParameterizedTypeName.get(FACTORY, factoryType);
+ }
+
+ public static ParameterizedTypeName lazyOf(TypeName typeName) {
+ return ParameterizedTypeName.get(LAZY, typeName);
+ }
+
+ public static ParameterizedTypeName listOf(TypeName typeName) {
+ return ParameterizedTypeName.get(LIST, typeName);
+ }
+
+ public static ParameterizedTypeName listenableFutureOf(TypeName typeName) {
+ return ParameterizedTypeName.get(LISTENABLE_FUTURE, typeName);
+ }
+
+ public static ParameterizedTypeName membersInjectorOf(TypeName membersInjectorType) {
+ return ParameterizedTypeName.get(MEMBERS_INJECTOR, membersInjectorType);
+ }
+
+ public static ParameterizedTypeName producedOf(TypeName typeName) {
+ return ParameterizedTypeName.get(PRODUCED, typeName);
+ }
+
+ public static ParameterizedTypeName producerOf(TypeName typeName) {
+ return ParameterizedTypeName.get(PRODUCER, typeName);
+ }
+
+ public static ParameterizedTypeName dependencyMethodProducerOf(TypeName typeName) {
+ return ParameterizedTypeName.get(DEPENDENCY_METHOD_PRODUCER, typeName);
+ }
+
+ public static ParameterizedTypeName providerOf(TypeName typeName) {
+ return ParameterizedTypeName.get(PROVIDER, typeName);
+ }
+
+ public static ParameterizedTypeName setOf(TypeName elementType) {
+ return ParameterizedTypeName.get(SET, elementType);
+ }
+
+ /**
+ * Returns the {@link TypeName} for the raw type of the given type name. If the argument isn't a
+ * parameterized type, it returns the argument unchanged.
+ */
+ public static TypeName rawTypeName(TypeName typeName) {
+ return (typeName instanceof ParameterizedTypeName)
+ ? ((ParameterizedTypeName) typeName).rawType
+ : typeName;
+ }
+
+ private TypeNames() {}
+}
diff --git a/java/dagger/internal/codegen/TypeSpecs.java b/java/dagger/internal/codegen/javapoet/TypeSpecs.java
similarity index 84%
rename from java/dagger/internal/codegen/TypeSpecs.java
rename to java/dagger/internal/codegen/javapoet/TypeSpecs.java
index 92f1a3a..8ec8747 100644
--- a/java/dagger/internal/codegen/TypeSpecs.java
+++ b/java/dagger/internal/codegen/javapoet/TypeSpecs.java
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
import javax.lang.model.element.TypeElement;
-/**
- * Convenience methods for use with JavaPoet's {@link TypeSpec}.
- */
-final class TypeSpecs {
+/** Convenience methods for use with JavaPoet's {@link TypeSpec}. */
+public final class TypeSpecs {
/**
* If {@code supertype} is a class, adds it as a superclass for {@code typeBuilder}; if it is an
@@ -33,7 +31,7 @@
* @return {@code typeBuilder}
*/
@CanIgnoreReturnValue
- static TypeSpec.Builder addSupertype(TypeSpec.Builder typeBuilder, TypeElement supertype) {
+ public static TypeSpec.Builder addSupertype(TypeSpec.Builder typeBuilder, TypeElement supertype) {
switch (supertype.getKind()) {
case CLASS:
return typeBuilder.superclass(ClassName.get(supertype));
diff --git a/java/dagger/internal/codegen/Accessibility.java b/java/dagger/internal/codegen/langmodel/Accessibility.java
similarity index 84%
rename from java/dagger/internal/codegen/Accessibility.java
rename to java/dagger/internal/codegen/langmodel/Accessibility.java
index 558b58f..62c1fbd 100644
--- a/java/dagger/internal/codegen/Accessibility.java
+++ b/java/dagger/internal/codegen/langmodel/Accessibility.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.langmodel;
import static com.google.auto.common.MoreElements.getPackage;
import static com.google.common.base.Preconditions.checkArgument;
@@ -45,31 +45,28 @@
/**
* Utility methods for determining whether a {@linkplain TypeMirror type} or an {@linkplain Element
- * element} is accessible given the rules outlined in
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6">section 6.6 of the
+ * element} is accessible given the rules outlined in <a
+ * href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6">section 6.6 of the
* Java Language Specification</a>.
*
- * <p>This class only provides an approximation for accessibility. It does not always yield the
- * same result as the compiler, but will always err on the side of declaring something inaccessible.
- * This ensures that using this class will never result in generating code that will not compile.
+ * <p>This class only provides an approximation for accessibility. It does not always yield the same
+ * result as the compiler, but will always err on the side of declaring something inaccessible. This
+ * ensures that using this class will never result in generating code that will not compile.
*
* <p>Whenever compiler independence is not a requirement, the compiler-specific implementation of
- * this functionality should be preferred. For example,
- * {@link com.sun.source.util.Trees#isAccessible(com.sun.source.tree.Scope, TypeElement)} would be
+ * this functionality should be preferred. For example, {@link
+ * com.sun.source.util.Trees#isAccessible(com.sun.source.tree.Scope, TypeElement)} would be
* preferable for {@code javac}.
*/
-final class Accessibility {
-
- /**
- * Returns true if the given type can be referenced from code in the given package.
- */
- static boolean isTypeAccessibleFrom(TypeMirror type, String packageName) {
- return type.accept(new TypeAccessibilityVisitor(packageName), null);
+public final class Accessibility {
+ /** Returns true if the given type can be referenced from any package. */
+ public static boolean isTypePubliclyAccessible(TypeMirror type) {
+ return type.accept(new TypeAccessibilityVisitor(), null);
}
- /** Returns true if the given type can be referenced from any package. */
- static boolean isTypePubliclyAccessible(TypeMirror type) {
- return type.accept(new TypeAccessibilityVisitor(), null);
+ /** Returns true if the given type can be referenced from code in the given package. */
+ public static boolean isTypeAccessibleFrom(TypeMirror type, String packageName) {
+ return type.accept(new TypeAccessibilityVisitor(packageName), null);
}
private static boolean isTypeAccessibleFrom(TypeMirror type, Optional<String> packageName) {
@@ -151,20 +148,21 @@
@Override
protected Boolean defaultAction(TypeMirror type, Void p) {
- throw new IllegalArgumentException(String.format(
- "%s of kind %s should not be checked for accessibility", type, type.getKind()));
+ throw new IllegalArgumentException(
+ String.format(
+ "%s of kind %s should not be checked for accessibility", type, type.getKind()));
}
}
- /** Returns true if the given element can be referenced from code in the given package. */
- //TODO(gak): account for protected
- static boolean isElementAccessibleFrom(Element element, String packageName) {
- return element.accept(new ElementAccessibilityVisitor(packageName), null);
+ /** Returns true if the given element can be referenced from any package. */
+ public static boolean isElementPubliclyAccessible(Element element) {
+ return element.accept(new ElementAccessibilityVisitor(), null);
}
- /** Returns true if the given element can be referenced from any package. */
- static boolean isElementPubliclyAccessible(Element element) {
- return element.accept(new ElementAccessibilityVisitor(), null);
+ /** Returns true if the given element can be referenced from code in the given package. */
+ // TODO(gak): account for protected
+ public static boolean isElementAccessibleFrom(Element element, String packageName) {
+ return element.accept(new ElementAccessibilityVisitor(packageName), null);
}
private static boolean isElementAccessibleFrom(Element element, Optional<String> packageName) {
@@ -172,7 +170,7 @@
}
/** Returns true if the given element can be referenced from other code in its own package. */
- static boolean isElementAccessibleFromOwnPackage(Element element) {
+ public static boolean isElementAccessibleFromOwnPackage(Element element) {
return isElementAccessibleFrom(
element, MoreElements.getPackage(element).getQualifiedName().toString());
}
@@ -208,9 +206,8 @@
case ANONYMOUS:
case LOCAL:
return false;
- default:
- throw new AssertionError();
}
+ throw new AssertionError();
}
boolean accessibleMember(Element element) {
@@ -266,15 +263,14 @@
};
/** Returns true if the raw type of {@code type} is accessible from the given package. */
- static boolean isRawTypeAccessible(TypeMirror type, String requestingPackage) {
+ public static boolean isRawTypeAccessible(TypeMirror type, String requestingPackage) {
return type.accept(RAW_TYPE_ACCESSIBILITY_VISITOR, Optional.of(requestingPackage));
}
/** Returns true if the raw type of {@code type} is accessible from any package. */
- static boolean isRawTypePubliclyAccessible(TypeMirror type) {
+ public static boolean isRawTypePubliclyAccessible(TypeMirror type) {
return type.accept(RAW_TYPE_ACCESSIBILITY_VISITOR, Optional.empty());
}
private Accessibility() {}
}
-
diff --git a/java/dagger/internal/codegen/langmodel/BUILD b/java/dagger/internal/codegen/langmodel/BUILD
new file mode 100644
index 0000000..16fa5d8
--- /dev/null
+++ b/java/dagger/internal/codegen/langmodel/BUILD
@@ -0,0 +1,31 @@
+# Copyright (C) 2017 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Description:
+# Dagger-specific extensions to the javax.lang.model APIs
+
+package(default_visibility = ["//:src"])
+
+java_library(
+ name = "langmodel",
+ srcs = glob(["*.java"]),
+ plugins = ["//java/dagger/internal/codegen:bootstrap_compiler_plugin"],
+ tags = ["maven:merged"],
+ deps = [
+ "//java/dagger:core",
+ "@google_bazel_common//third_party/java/auto:common",
+ "@google_bazel_common//third_party/java/guava",
+ "@google_bazel_common//third_party/java/javapoet",
+ ],
+)
diff --git a/java/dagger/internal/codegen/DaggerElements.java b/java/dagger/internal/codegen/langmodel/DaggerElements.java
similarity index 67%
rename from java/dagger/internal/codegen/DaggerElements.java
rename to java/dagger/internal/codegen/langmodel/DaggerElements.java
index 5faab26..873ad3d 100644
--- a/java/dagger/internal/codegen/DaggerElements.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerElements.java
@@ -14,17 +14,14 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.langmodel;
import static com.google.auto.common.MoreElements.asExecutable;
import static com.google.auto.common.MoreElements.getLocalAndInheritedMethods;
import static com.google.auto.common.MoreElements.hasModifiers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.asList;
-import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.Formatter.formatArgumentInList;
import static java.util.Comparator.comparing;
-import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;
import static javax.lang.model.element.Modifier.ABSTRACT;
@@ -55,26 +52,24 @@
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor8;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor8;
import javax.lang.model.util.Types;
/** Extension of {@link Elements} that adds Dagger-specific methods. */
@Reusable
-final class DaggerElements implements Elements {
+public final class DaggerElements implements Elements {
private final Elements elements;
private final Types types;
- DaggerElements(Elements elements, Types types) {
+ public DaggerElements(Elements elements, Types types) {
this.elements = checkNotNull(elements);
this.types = checkNotNull(types);
}
- DaggerElements(ProcessingEnvironment processingEnv) {
+ public DaggerElements(ProcessingEnvironment processingEnv) {
this(processingEnv.getElementUtils(), processingEnv.getTypeUtils());
}
@@ -82,21 +77,21 @@
* Returns {@code true} if {@code encloser} is equal to {@code enclosed} or recursively encloses
* it.
*/
- static boolean elementEncloses(TypeElement encloser, Element enclosed) {
+ public static boolean elementEncloses(TypeElement encloser, Element enclosed) {
return Iterables.contains(GET_ENCLOSED_ELEMENTS.breadthFirst(encloser), enclosed);
}
private static final Traverser<Element> GET_ENCLOSED_ELEMENTS =
Traverser.forTree(Element::getEnclosedElements);
- ImmutableSet<ExecutableElement> getUnimplementedMethods(TypeElement type) {
+ public ImmutableSet<ExecutableElement> getUnimplementedMethods(TypeElement type) {
return FluentIterable.from(getLocalAndInheritedMethods(type, types, elements))
.filter(hasModifiers(ABSTRACT))
.toSet();
}
/** Returns the type element for a class. */
- TypeElement getTypeElement(Class<?> clazz) {
+ public TypeElement getTypeElement(Class<?> clazz) {
return getTypeElement(clazz.getCanonicalName());
}
@@ -106,87 +101,12 @@
}
/** Returns the type element for a class name. */
- TypeElement getTypeElement(ClassName className) {
+ public TypeElement getTypeElement(ClassName className) {
return getTypeElement(className.withoutAnnotations().toString());
}
- /**
- * Returns a useful string form for an element.
- *
- * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
- *
- * <p>Parameters are given with their enclosing executable, with other parameters elided.
- */
- static String elementToString(Element element) {
- return element.accept(ELEMENT_TO_STRING, null);
- }
-
- private static final ElementVisitor<String, Void> ELEMENT_TO_STRING =
- new ElementKindVisitor8<String, Void>() {
- @Override
- public String visitExecutable(ExecutableElement executableElement, Void aVoid) {
- return enclosingTypeAndMemberName(executableElement)
- .append(
- executableElement.getParameters().stream()
- .map(parameter -> parameter.asType().toString())
- .collect(joining(", ", "(", ")")))
- .toString();
- }
-
- @Override
- public String visitVariableAsParameter(VariableElement parameter, Void aVoid) {
- ExecutableElement methodOrConstructor = asExecutable(parameter.getEnclosingElement());
- return enclosingTypeAndMemberName(methodOrConstructor)
- .append('(')
- .append(
- formatArgumentInList(
- methodOrConstructor.getParameters().indexOf(parameter),
- methodOrConstructor.getParameters().size(),
- parameter.getSimpleName()))
- .append(')')
- .toString();
- }
-
- @Override
- public String visitVariableAsField(VariableElement field, Void aVoid) {
- return enclosingTypeAndMemberName(field).toString();
- }
-
- @Override
- public String visitType(TypeElement type, Void aVoid) {
- return type.getQualifiedName().toString();
- }
-
- @Override
- protected String defaultAction(Element element, Void aVoid) {
- throw new UnsupportedOperationException(
- "Can't determine string for " + element.getKind() + " element " + element);
- }
-
- private StringBuilder enclosingTypeAndMemberName(Element element) {
- StringBuilder name = new StringBuilder(element.getEnclosingElement().accept(this, null));
- if (!element.getSimpleName().contentEquals("<init>")) {
- name.append('.').append(element.getSimpleName());
- }
- return name;
- }
- };
-
- /** A formatter that calls {@link #elementToString(Element)}. */
- static Formatter<Element> elementFormatter() {
- return ELEMENT_FORMATTER;
- }
-
- private static final Formatter<Element> ELEMENT_FORMATTER =
- new Formatter<Element>() {
- @Override
- public String format(Element element) {
- return elementToString(element);
- }
- };
-
/** Returns the argument or the closest enclosing element that is a {@link TypeElement}. */
- static TypeElement closestEnclosingTypeElement(Element element) {
+ public static TypeElement closestEnclosingTypeElement(Element element) {
return element.accept(CLOSEST_ENCLOSING_TYPE_ELEMENT, null);
}
@@ -207,7 +127,7 @@
* Compares elements according to their declaration order among siblings. Only valid to compare
* elements enclosed by the same parent.
*/
- static final Comparator<Element> DECLARATION_ORDER =
+ public static final Comparator<Element> DECLARATION_ORDER =
comparing(element -> siblings(element).indexOf(element));
// For parameter elements, element.getEnclosingElement().getEnclosedElements() is empty. So
@@ -219,11 +139,11 @@
}
/**
- * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose
- * {@linkplain AnnotationMirror#getAnnotationType() annotation type} has the same canonical name
- * as any of that of {@code annotationClasses}.
+ * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
+ * AnnotationMirror#getAnnotationType() annotation type} has the same canonical name as any of
+ * that of {@code annotationClasses}.
*/
- static boolean isAnyAnnotationPresent(
+ public static boolean isAnyAnnotationPresent(
Element element, Iterable<? extends Class<? extends Annotation>> annotationClasses) {
for (Class<? extends Annotation> annotation : annotationClasses) {
if (MoreElements.isAnnotationPresent(element, annotation)) {
@@ -234,7 +154,7 @@
}
@SafeVarargs
- static boolean isAnyAnnotationPresent(
+ public static boolean isAnyAnnotationPresent(
Element element,
Class<? extends Annotation> first,
Class<? extends Annotation>... otherAnnotations) {
@@ -245,10 +165,8 @@
* Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
* AnnotationMirror#getAnnotationType() annotation type} is equivalent to {@code annotationType}.
*/
- static boolean isAnnotationPresent(Element element, TypeMirror annotationType) {
- return element
- .getAnnotationMirrors()
- .stream()
+ public static boolean isAnnotationPresent(Element element, TypeMirror annotationType) {
+ return element.getAnnotationMirrors().stream()
.map(AnnotationMirror::getAnnotationType)
.anyMatch(candidate -> MoreTypes.equivalence().equivalent(candidate, annotationType));
}
@@ -258,7 +176,7 @@
* rest}, checking each annotation type in order.
*/
@SafeVarargs
- static Optional<AnnotationMirror> getAnyAnnotation(
+ public static Optional<AnnotationMirror> getAnyAnnotation(
Element element, Class<? extends Annotation> first, Class<? extends Annotation>... rest) {
return getAnyAnnotation(element, asList(first, rest));
}
@@ -267,11 +185,9 @@
* Returns the annotation present on {@code element} whose type is in {@code annotations},
* checking each annotation type in order.
*/
- static Optional<AnnotationMirror> getAnyAnnotation(
+ public static Optional<AnnotationMirror> getAnyAnnotation(
Element element, Collection<? extends Class<? extends Annotation>> annotations) {
- return element
- .getAnnotationMirrors()
- .stream()
+ return element.getAnnotationMirrors().stream()
.filter(hasAnnotationTypeIn(annotations))
.map((AnnotationMirror a) -> a) // Avoid returning Optional<? extends AnnotationMirror>.
.findFirst();
@@ -279,13 +195,11 @@
/** Returns the annotations present on {@code element} of all types. */
@SafeVarargs
- static ImmutableSet<AnnotationMirror> getAllAnnotations(
+ public static ImmutableSet<AnnotationMirror> getAllAnnotations(
Element element, Class<? extends Annotation> first, Class<? extends Annotation>... rest) {
- return element
- .getAnnotationMirrors()
- .stream()
- .filter(hasAnnotationTypeIn(asList(first, rest)))
- .collect(toImmutableSet());
+ return ImmutableSet.copyOf(
+ Iterables.filter(
+ element.getAnnotationMirrors(), hasAnnotationTypeIn(asList(first, rest))::test));
}
/**
@@ -294,7 +208,7 @@
* safer alternative to calling {@link Element#getAnnotation} as it avoids any interaction with
* annotation proxies.
*/
- static Optional<AnnotationMirror> getAnnotationMirror(
+ public static Optional<AnnotationMirror> getAnnotationMirror(
Element element, Class<? extends Annotation> annotationClass) {
return Optional.ofNullable(MoreElements.getAnnotationMirror(element, annotationClass).orNull());
}
@@ -308,7 +222,7 @@
MoreTypes.asTypeElement(annotation.getAnnotationType()).getQualifiedName().toString());
}
- static ImmutableSet<String> suppressedWarnings(Element element) {
+ public static ImmutableSet<String> suppressedWarnings(Element element) {
SuppressWarnings suppressedWarnings = element.getAnnotation(SuppressWarnings.class);
if (suppressedWarnings == null) {
return ImmutableSet.of();
@@ -320,7 +234,7 @@
* Invokes {@link Elements#getTypeElement(CharSequence)}, throwing {@link TypeNotPresentException}
* if it is not accessible in the current compilation.
*/
- TypeElement checkTypePresent(String typeName) {
+ public TypeElement checkTypePresent(String typeName) {
TypeElement type = elements.getTypeElement(typeName);
if (type == null) {
throw new TypeNotPresentException(typeName, null);
diff --git a/java/dagger/internal/codegen/DaggerTypes.java b/java/dagger/internal/codegen/langmodel/DaggerTypes.java
similarity index 92%
rename from java/dagger/internal/codegen/DaggerTypes.java
rename to java/dagger/internal/codegen/langmodel/DaggerTypes.java
index 57f763f..e588fbd 100644
--- a/java/dagger/internal/codegen/DaggerTypes.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerTypes.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.langmodel;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -49,13 +49,12 @@
import javax.lang.model.util.Types;
/** Extension of {@link Types} that adds Dagger-specific methods. */
-final class DaggerTypes implements Types {
-
+public final class DaggerTypes implements Types {
private final Types types;
private final DaggerElements elements;
@Inject
- DaggerTypes(Types types, DaggerElements elements) {
+ public DaggerTypes(Types types, DaggerElements elements) {
this.types = checkNotNull(types);
this.elements = checkNotNull(elements);
}
@@ -64,7 +63,7 @@
* Returns the non-{@link Object} superclass of the type with the proper type parameters. An empty
* {@link Optional} is returned if there is no non-{@link Object} superclass.
*/
- Optional<DeclaredType> nonObjectSuperclass(DeclaredType type) {
+ public Optional<DeclaredType> nonObjectSuperclass(DeclaredType type) {
return Optional.ofNullable(MoreTypes.nonObjectSuperclass(types, elements, type).orNull());
}
@@ -72,7 +71,7 @@
* Returns the {@linkplain #directSupertypes(TypeMirror) supertype}s of a type in breadth-first
* order.
*/
- Iterable<TypeMirror> supertypes(TypeMirror type) {
+ public Iterable<TypeMirror> supertypes(TypeMirror type) {
return Traverser.<TypeMirror>forGraph(this::directSupertypes).breadthFirst(type);
}
@@ -84,7 +83,7 @@
* @throws IllegalArgumentException if {@code type} is not a declared type or has zero or more
* than one type arguments.
*/
- TypeMirror unwrapType(TypeMirror type) {
+ public TypeMirror unwrapType(TypeMirror type) {
TypeMirror unwrapped = unwrapTypeOrDefault(type, null);
checkArgument(unwrapped != null, "%s is a raw type", type);
return unwrapped;
@@ -98,7 +97,7 @@
* @throws IllegalArgumentException if {@code type} is not a declared type or has more than one
* type argument.
*/
- TypeMirror unwrapTypeOrObject(TypeMirror type) {
+ public TypeMirror unwrapTypeOrObject(TypeMirror type) {
return unwrapTypeOrDefault(type, elements.getTypeElement(Object.class).asType());
}
@@ -118,7 +117,7 @@
* <p>For example, if {@code type} is {@code List<Number>} and {@code wrappingClass} is {@code
* Set.class}, this will return {@code Set<List<Number>>}.
*/
- DeclaredType wrapType(TypeMirror type, Class<?> wrappingClass) {
+ public DeclaredType wrapType(TypeMirror type, Class<?> wrappingClass) {
return types.getDeclaredType(elements.getTypeElement(wrappingClass), type);
}
@@ -133,7 +132,7 @@
*
* @throws IllegalArgumentException if {@code} has more than one type argument.
*/
- DeclaredType rewrapType(TypeMirror type, Class<?> wrappingClass) {
+ public DeclaredType rewrapType(TypeMirror type, Class<?> wrappingClass) {
List<? extends TypeMirror> typeArguments = MoreTypes.asDeclared(type).getTypeArguments();
TypeElement wrappingType = elements.getTypeElement(wrappingClass);
switch (typeArguments.size()) {
@@ -155,7 +154,7 @@
* <li>Otherwise returns {@link Object}.
* </ul>
*/
- protected TypeMirror publiclyAccessibleType(TypeMirror type) {
+ public TypeMirror publiclyAccessibleType(TypeMirror type) {
return accessibleType(
type, Accessibility::isTypePubliclyAccessible, Accessibility::isRawTypePubliclyAccessible);
}
@@ -169,7 +168,7 @@
* <li>Otherwise returns {@link Object}.
* </ul>
*/
- protected TypeMirror accessibleType(TypeMirror type, ClassName requestingClass) {
+ public TypeMirror accessibleType(TypeMirror type, ClassName requestingClass) {
return accessibleType(
type,
t -> Accessibility.isTypeAccessibleFrom(t, requestingClass.packageName()),
@@ -194,7 +193,7 @@
* Throws {@link TypeNotPresentException} if {@code type} is an {@link
* javax.lang.model.type.ErrorType}.
*/
- static void checkTypePresent(TypeMirror type) {
+ public static void checkTypePresent(TypeMirror type) {
type.accept(
// TODO(ronshapiro): Extract a base class that visits all components of a complex type
// and put it in auto.common
@@ -221,11 +220,11 @@
private static final ImmutableSet<Class<?>> FUTURE_TYPES =
ImmutableSet.of(ListenableFuture.class, FluentFuture.class);
- static boolean isFutureType(TypeMirror type) {
+ public static boolean isFutureType(TypeMirror type) {
return FUTURE_TYPES.stream().anyMatch(t -> MoreTypes.isTypeOf(t, type));
}
- static boolean hasTypeVariable(TypeMirror type) {
+ public static boolean hasTypeVariable(TypeMirror type) {
return type.accept(
new SimpleTypeVisitor8<Boolean, Void>() {
@Override
diff --git a/java/dagger/internal/codegen/serialization/BUILD b/java/dagger/internal/codegen/serialization/BUILD
new file mode 100644
index 0000000..2bc02b4
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/BUILD
@@ -0,0 +1,41 @@
+# Copyright (C) 2019 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Description:
+# Serialized forms of types used in the Dagger processor.
+
+package(default_visibility = ["//:src"])
+
+proto_library(
+ name = "serialization_proto",
+ srcs = ["serialization.proto"],
+ visibility = ["//visibility:private"],
+)
+
+java_proto_library(
+ name = "serialization_java_proto",
+ visibility = ["//visibility:private"],
+ deps = [":serialization_proto"],
+)
+
+java_library(
+ name = "serialization",
+ srcs = glob(["*.java"]),
+ exports = [":serialization_java_proto"],
+ deps = [
+ "@google_bazel_common//third_party/java/guava",
+ "@google_bazel_common//third_party/java/javapoet",
+ "@google_bazel_common//third_party/java/protobuf",
+ ],
+)
diff --git a/java/dagger/internal/codegen/serialization/ProtoSerialization.java b/java/dagger/internal/codegen/serialization/ProtoSerialization.java
new file mode 100644
index 0000000..1449e9d
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/ProtoSerialization.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.serialization;
+
+import static com.google.common.io.BaseEncoding.base64;
+
+import com.google.common.io.BaseEncoding;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Message;
+import com.squareup.javapoet.CodeBlock;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.util.SimpleAnnotationValueVisitor8;
+
+/**
+ * Serializes and deserializes {@link Message}s using {@link BaseEncoding#base64()} for use in
+ * annotation values.
+ */
+public final class ProtoSerialization {
+ /** Returns a {@link CodeBlock} of {@code message} serialized as a String. */
+ public static CodeBlock toAnnotationValue(Message message) {
+ return CodeBlock.of("$S", base64().encode(message.toByteArray()));
+ }
+
+ /**
+ * Returns a {@link Message T} from the deserialized the String {@code value}.
+ *
+ * @throws IllegalArgumentException if {@code value} represents an {@link AnnotationValue} who's
+ * type is not {@link String}
+ */
+ public static <T extends Message> T fromAnnotationValue(
+ AnnotationValue value, T defaultInstance) {
+ byte[] bytes = base64().decode(value.accept(STRING_VALUE, null));
+ Message message;
+ try {
+ message = defaultInstance.getParserForType().parseFrom(bytes);
+ } catch (InvalidProtocolBufferException e) {
+ throw new InconsistentSerializedProtoException(e);
+ }
+ @SuppressWarnings("unchecked") // guaranteed by proto API
+ T t = (T) message;
+ return t;
+ }
+
+ private static final AnnotationValueVisitor<String, Void> STRING_VALUE =
+ new SimpleAnnotationValueVisitor8<String, Void>() {
+ @Override
+ public String visitString(String s, Void ignored) {
+ return s;
+ }
+
+ @Override
+ protected String defaultAction(Object o, Void ignored) {
+ throw new IllegalArgumentException(o + " is not a String");
+ }
+ };
+
+ /**
+ * An exception thrown when the proto that's serialized in a compiled subcomponent implementation
+ * is from a different version than the current compiler's.
+ */
+ public static final class InconsistentSerializedProtoException extends RuntimeException {
+ InconsistentSerializedProtoException(Throwable cause) {
+ super(cause);
+ }
+ }
+}
diff --git a/java/dagger/internal/codegen/serialization/serialization.proto b/java/dagger/internal/codegen/serialization/serialization.proto
new file mode 100644
index 0000000..e6c9577
--- /dev/null
+++ b/java/dagger/internal/codegen/serialization/serialization.proto
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Serialized forms of types used in the Dagger processor. The wire format of
+// these types is not guaranteed to remain compatible over time; serialization
+// is only expected to function correctly within an individual version of the
+// Dagger processor.
+
+syntax = "proto3";
+
+package dagger.internal.codegen.serialization;
+option java_package = "dagger.internal.codegen.serialization";
+option java_multiple_files = true;
+
+// TODO(ronshapiro): consider exposing some of these in
+// dagger.model.serialization
+
+// Serialized form of `dagger.internal.codegen.BindingRequest`
+message BindingRequestProto {
+ KeyProto key = 1;
+ RequestKindWrapper.RequestKind request_kind = 2;
+ FrameworkTypeWrapper.FrameworkType framework_type = 3;
+}
+
+message RequestKindWrapper {
+ // Serialized form of `dagger.model.RequestKind`
+ enum RequestKind {
+ UNKNOWN = 0;
+ INSTANCE = 1;
+ PROVIDER = 2;
+ LAZY = 3;
+ PROVIDER_OF_LAZY = 4;
+ MEMBERS_INJECTION = 5;
+ PRODUCER = 6;
+ PRODUCED = 7;
+ FUTURE = 8;
+ }
+}
+
+message FrameworkTypeWrapper {
+ // Serialized form of `dagger.internal.codegen.FrameworkType`
+ enum FrameworkType {
+ UNKNOWN = 0;
+ PROVIDER = 1;
+ PRODUCER_NODE = 2;
+ }
+}
+
+// Serialized form of `dagger.model.Key`
+message KeyProto {
+ TypeProto type = 1;
+ AnnotationProto qualifier = 2;
+ MultibindingContributionIdentifier multibinding_contribution_identifier =
+ 3;
+
+ // Serialized form of `dagger.model.Key.MultibindingContributionIdentifier`
+ message MultibindingContributionIdentifier {
+ string module = 1;
+ string binding_element = 2;
+ }
+}
+
+// Serialized form of `javax.lang.model.type.TypeMirror`
+message TypeProto {
+ PrimitiveKind primitive_kind = 1;
+
+ // The qualified name of the type. Absent if this is an inner type.
+ string qualified_name = 2;
+
+ // The enclosing type if this is an inner type, otherwise absent.
+ TypeProto enclosing_type = 3;
+
+ // Simple name of the type if this is an inner type, otherwise absent.
+ string simple_name = 4;
+
+ repeated TypeProto type_arguments = 5;
+
+ message Wildcard {
+ TypeProto extends_bound = 1;
+ TypeProto super_bound = 2;
+ }
+ Wildcard wildcard = 6;
+
+ int32 array_dimensions = 7;
+
+ // Kinds of primitive types
+ enum PrimitiveKind {
+ UNKNOWN = 0;
+ BOOLEAN = 1;
+ BYTE = 2;
+ SHORT = 3;
+ CHAR = 4;
+ INT = 5;
+ FLOAT = 6;
+ LONG = 7;
+ DOUBLE = 8;
+ }
+}
+
+// Serialized form of `javax.lang.model.element.AnnotationMirror`
+message AnnotationProto {
+ TypeProto annotation_type = 1;
+ map<string, AnnotationValueProto> values = 2;
+}
+
+// Serialized form of `javax.lang.model.element.AnnotationValue`
+message AnnotationValueProto {
+ Kind kind = 1;
+ bool boolean_value = 2;
+ int32 int_value = 3;
+ int64 long_value = 4;
+ float float_value = 5;
+ double double_value = 6;
+ string string_value = 7;
+ TypeProto class_literal = 8;
+ TypeProto enum_type = 9;
+ string enum_name = 10;
+ AnnotationProto nested_annotation = 11;
+
+ repeated AnnotationValueProto array_values = 12;
+
+ // The type of annotation value
+ enum Kind {
+ UNKNOWN = 0;
+ BOOLEAN = 1;
+ BYTE = 2;
+ SHORT = 3;
+ CHAR = 4;
+ INT = 5;
+ FLOAT = 6;
+ LONG = 7;
+ DOUBLE = 8;
+ STRING = 9;
+ CLASS_LITERAL = 10;
+ ENUM = 11;
+ ANNOTATION = 12;
+ ARRAY = 13;
+ }
+}
+
+// Serialized form of `dagger.internal.codegen.ComponentRequirement`
+message ComponentRequirementProto {
+ oneof requirement {
+ TypeProto dependency = 1;
+ TypeProto module = 2;
+ BoundInstanceRequirement bound_instance = 3;
+ }
+
+ message BoundInstanceRequirement {
+ KeyProto key = 1;
+ bool nullable = 2;
+ string variable_name = 3;
+ }
+}
diff --git a/java/dagger/model/BindingGraph.java b/java/dagger/model/BindingGraph.java
index 681cfaf..748bf38 100644
--- a/java/dagger/model/BindingGraph.java
+++ b/java/dagger/model/BindingGraph.java
@@ -106,14 +106,13 @@
}
/**
- * Returns {@code true} if this graph was constructed from a module for module binding validation.
+ * Returns {@code true} if this graph was constructed from a module for full binding graph
+ * validation.
*
- * @see <a href="https://google.github.io/dagger/compiler-options#module-binding-validation">Module binding
- * validation</a>
* @deprecated use {@link #isFullBindingGraph()} to tell if this is a full binding graph, or
* {@link ComponentNode#isRealComponent() rootComponentNode().isRealComponent()} to tell if
- * the root component node is really a component or derived from a module. Dagger will soon
- * generate full binding graphs for components and subcomponents as well as modules.
+ * the root component node is really a component or derived from a module. Dagger can generate
+ * full binding graphs for components and subcomponents as well as modules.
*/
@Deprecated
public final boolean isModuleBindingGraph() {
@@ -124,6 +123,9 @@
* Returns {@code true} if this is a full binding graph, which contains all bindings installed in
* the component, or {@code false} if it is a reachable binding graph, which contains only
* bindings that are reachable from at least one {@linkplain #entryPointEdges() entry point}.
+ *
+ * @see <a href="https://dagger.dev/compiler-options#full-binding-graph-validation">Full binding
+ * graph validation</a>
*/
public abstract boolean isFullBindingGraph();
@@ -424,6 +426,13 @@
public final String toString() {
return String.format("missing binding for %s in %s", key(), componentPath());
}
+
+ @Memoized
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(Object o);
}
/**
diff --git a/java/dagger/model/Key.java b/java/dagger/model/Key.java
index 53ee391..03dd41c 100644
--- a/java/dagger/model/Key.java
+++ b/java/dagger/model/Key.java
@@ -27,6 +27,8 @@
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.CheckReturnValue;
import com.squareup.javapoet.CodeBlock;
import java.util.List;
import java.util.Objects;
@@ -176,6 +178,7 @@
}
/** A builder for {@link Key}s. */
+ @CanIgnoreReturnValue
@AutoValue.Builder
public abstract static class Builder {
abstract Builder wrappedType(Equivalence.Wrapper<TypeMirror> wrappedType);
@@ -203,6 +206,7 @@
public abstract Builder multibindingContributionIdentifier(
MultibindingContributionIdentifier identifier);
+ @CheckReturnValue
public abstract Key build();
}
@@ -222,9 +226,27 @@
*/
@Deprecated
public MultibindingContributionIdentifier(
+ // TODO(ronshapiro): reverse the order of these parameters
ExecutableElement bindingMethod, TypeElement contributingModule) {
- this.module = contributingModule.getQualifiedName().toString();
- this.bindingElement = bindingMethod.getSimpleName().toString();
+ this(
+ bindingMethod.getSimpleName().toString(),
+ contributingModule.getQualifiedName().toString());
+ }
+
+ // TODO(ronshapiro,dpb): create KeyProxies so that these constructors don't need to be public.
+ @Deprecated
+ public MultibindingContributionIdentifier(String bindingElement, String module) {
+ this.module = module;
+ this.bindingElement = bindingElement;
+ }
+
+ /**
+ * @deprecated This is only meant to be called from code in {@code dagger.internal.codegen}.
+ * It is not part of a specified API and may change at any point.
+ */
+ @Deprecated
+ public String module() {
+ return module;
}
/**
diff --git a/java/dagger/model/Scope.java b/java/dagger/model/Scope.java
index 7d255e1..f48fa16 100644
--- a/java/dagger/model/Scope.java
+++ b/java/dagger/model/Scope.java
@@ -90,7 +90,7 @@
/** Returns a debug representation of the scope. */
@Override
- public String toString() {
+ public final String toString() {
return scopeAnnotation().toString();
}
}
diff --git a/java/dagger/model/testing/BindingGraphSubject.java b/java/dagger/model/testing/BindingGraphSubject.java
index f251eb5..dc17c1d 100644
--- a/java/dagger/model/testing/BindingGraphSubject.java
+++ b/java/dagger/model/testing/BindingGraphSubject.java
@@ -36,8 +36,11 @@
return assertAbout(BindingGraphSubject::new).that(bindingGraph);
}
+ private final BindingGraph actual;
+
private BindingGraphSubject(FailureMetadata metadata, @NullableDecl BindingGraph actual) {
super(metadata, actual);
+ this.actual = actual;
}
/**
@@ -82,21 +85,15 @@
private BindingSubject bindingWithKeyString(String keyString) {
ImmutableSet<Binding> bindings = getBindingNodes(keyString);
- if (bindings.isEmpty()) {
- fail("has binding with key", keyString);
- }
// TODO(dpb): Handle multiple bindings for the same key.
- if (bindings.size() > 1) {
- failWithBadResults(
- "has only one binding with key", keyString, "has the following bindings:", bindings);
- }
+ check("bindingsWithKey(%s)", keyString).that(bindings).hasSize(1);
return check("bindingWithKey(%s)", keyString)
.about(BindingSubject::new)
.that(getOnlyElement(bindings));
}
private ImmutableSet<Binding> getBindingNodes(String keyString) {
- return actual().bindings().stream()
+ return actual.bindings().stream()
.filter(binding -> binding.key().toString().equals(keyString))
.collect(toImmutableSet());
}
@@ -112,8 +109,11 @@
/** A Truth subject for a {@link Binding}. */
public final class BindingSubject extends Subject<BindingSubject, Binding> {
+ private final Binding actual;
+
BindingSubject(FailureMetadata metadata, @NullableDecl Binding actual) {
super(metadata, actual);
+ this.actual = actual;
}
/**
@@ -137,14 +137,14 @@
}
private void dependsOnBindingWithKeyString(String keyString) {
- if (actualBindingGraph().requestedBindings(actual()).stream()
+ if (actualBindingGraph().requestedBindings(actual).stream()
.noneMatch(binding -> binding.key().toString().equals(keyString))) {
- fail("depends on binding with key", keyString);
+ failWithActual("expected to depend on binding with key", keyString);
}
}
private BindingGraph actualBindingGraph() {
- return BindingGraphSubject.this.actual();
+ return BindingGraphSubject.this.actual;
}
}
}
diff --git a/java/dagger/multibindings/ElementsIntoSet.java b/java/dagger/multibindings/ElementsIntoSet.java
index 72cc86d..5ed68c6 100644
--- a/java/dagger/multibindings/ElementsIntoSet.java
+++ b/java/dagger/multibindings/ElementsIntoSet.java
@@ -28,7 +28,7 @@
* Set<T>} produced from the accumulation of values will be immutable. An example use is to provide
* a default empty set binding, which is otherwise not possible using {@link IntoSet}.
*
- * @see <a href="https://google.github.io/dagger/multibindings#set-multibindings">Set multibinding</a>
+ * @see <a href="https://dagger.dev/multibindings#set-multibindings">Set multibinding</a>
*/
@Documented
@Target(METHOD)
diff --git a/java/dagger/multibindings/IntoMap.java b/java/dagger/multibindings/IntoMap.java
index 3066b58..d760229 100644
--- a/java/dagger/multibindings/IntoMap.java
+++ b/java/dagger/multibindings/IntoMap.java
@@ -29,7 +29,7 @@
* key/value pair. The {@code Map<K, Provider<V>>} produced from the accumulation of values will be
* immutable.
*
- * @see <a href="https://google.github.io/dagger/multibindings#map-multibindings">Map multibinding</a>
+ * @see <a href="https://dagger.dev/multibindings#map-multibindings">Map multibinding</a>
*/
@Documented
@Target(METHOD)
diff --git a/java/dagger/multibindings/IntoSet.java b/java/dagger/multibindings/IntoSet.java
index f42860f..b4fdcc4 100644
--- a/java/dagger/multibindings/IntoSet.java
+++ b/java/dagger/multibindings/IntoSet.java
@@ -28,7 +28,7 @@
* value is contributed to the set. The object graph will pass dependencies to the method as
* parameters. The {@code Set<T>} produced from the accumulation of values will be immutable.
*
- * @see <a href="https://google.github.io/dagger/multibindings#set-multibindings">Set multibinding</a>
+ * @see <a href="https://dagger.dev/multibindings#set-multibindings">Set multibinding</a>
*/
@Documented
@Target(METHOD)
diff --git a/java/dagger/multibindings/Multibinds.java b/java/dagger/multibindings/Multibinds.java
index 1517b26..e37b39e 100644
--- a/java/dagger/multibindings/Multibinds.java
+++ b/java/dagger/multibindings/Multibinds.java
@@ -48,7 +48,7 @@
* <p>A given set or map multibinding can be declared any number of times without error. Dagger
* never implements or calls any {@code @Multibinds} methods.
*
- * @see <a href="https://google.github.io/dagger/multibindings">Multibindings</a>
+ * @see <a href="https://dagger.dev/multibindings">Multibindings</a>
*/
@Documented
@Target(METHOD)
diff --git a/java/dagger/multibindings/package-info.java b/java/dagger/multibindings/package-info.java
index e806d9e..d6fe1e1 100644
--- a/java/dagger/multibindings/package-info.java
+++ b/java/dagger/multibindings/package-info.java
@@ -18,6 +18,6 @@
* This package contains the API by which Dagger allows you to bind several objects into a
* collection that can be injected without depending directly on each of the individual bindings.
*
- * @see <a href="https://google.github.io/dagger/multibindings">Multibindings in the Dagger User's Guide</a>
+ * @see <a href="https://dagger.dev/multibindings">Multibindings in the Dagger User's Guide</a>
*/
package dagger.multibindings;
diff --git a/java/dagger/package-info.java b/java/dagger/package-info.java
index 99cd44b..b680a85 100644
--- a/java/dagger/package-info.java
+++ b/java/dagger/package-info.java
@@ -15,7 +15,7 @@
*/
/**
- * This package contains the public API for the <a href="https://google.github.io/dagger/">Dagger 2</a> dependency
+ * This package contains the public API for the <a href="https://dagger.dev/">Dagger 2</a> dependency
* injection framework. By building upon <a href="https://jcp.org/en/jsr/detail?id=330">JSR 330</a>,
* Dagger 2 provides an annotation-driven API for dependency injection whose implementation is
* entirely generated at compile time by <a
diff --git a/java/dagger/producers/monitoring/ProducerTimingRecorder.java b/java/dagger/producers/monitoring/ProducerTimingRecorder.java
index 90fe29a..f4894c9 100644
--- a/java/dagger/producers/monitoring/ProducerTimingRecorder.java
+++ b/java/dagger/producers/monitoring/ProducerTimingRecorder.java
@@ -41,11 +41,12 @@
* <p>If the producer was skipped due to any of its inputs failing, then this will not be called.
*
* @param startedNanos the wall-clock time, in nanoseconds, when the producer method started
- * executing, measured from when the first method on the
- * {@linkplain ProductionComponent production component} was called.
+ * executing, measured from when the first method on the {@linkplain ProductionComponent
+ * production component} was called.
* @param durationNanos the wall-clock time, in nanoseconds, that the producer method took to
* execute.
*/
+ @SuppressWarnings("GoodTime") // should accept a java.time.Duration x2 (?)
public void recordMethod(long startedNanos, long durationNanos) {}
/**
@@ -56,6 +57,7 @@
* @param latencyNanos the wall-clock time, in nanoseconds, of the producer's latency, measured
* from when the producer method started to when the future finished.
*/
+ @SuppressWarnings("GoodTime") // should accept a java.time.Duration
public void recordSuccess(long latencyNanos) {}
/**
@@ -65,6 +67,7 @@
* @param latencyNanos the wall-clock time, in nanoseconds, of the producer's latency, measured
* from when the producer method started to when the future finished.
*/
+ @SuppressWarnings("GoodTime") // should accept a java.time.Duration
public void recordFailure(Throwable exception, long latencyNanos) {}
/**
diff --git a/java/dagger/producers/package-info.java b/java/dagger/producers/package-info.java
index 10185ef..9693ae9 100644
--- a/java/dagger/producers/package-info.java
+++ b/java/dagger/producers/package-info.java
@@ -21,6 +21,6 @@
* in Java.
*
* <p>Extended documentation on Dagger Producers can be found at <a
- * href="https://google.github.io/dagger/producers">https://google.github.io/dagger/producers</a>.
+ * href="https://dagger.dev/producers">https://dagger.dev/producers</a>.
*/
package dagger.producers;
diff --git a/javatests/dagger/android/AndroidInjectionTest.java b/javatests/dagger/android/AndroidInjectionTest.java
index a24ff5b..19b6e84 100644
--- a/javatests/dagger/android/AndroidInjectionTest.java
+++ b/javatests/dagger/android/AndroidInjectionTest.java
@@ -122,7 +122,7 @@
} catch (Exception e) {
assertThat(e)
.hasMessageThat()
- .contains("Application does not implement dagger.android.HasActivityInjector");
+ .contains("Application does not implement dagger.android.HasAndroidInjector");
}
}
diff --git a/javatests/dagger/android/support/functional/BUILD b/javatests/dagger/android/support/functional/BUILD
index ffb9361..130b971 100644
--- a/javatests/dagger/android/support/functional/BUILD
+++ b/javatests/dagger/android/support/functional/BUILD
@@ -27,12 +27,14 @@
manifest = "AndroidManifest.xml",
resource_files = glob(["res/**"]),
deps = [
+ "@androidsdk//com.android.support:support-fragment-25.0.0",
+ "@androidsdk//com.android.support:appcompat-v7-25.0.0",
+ "@google_bazel_common//third_party/java/guava",
+ "//:dagger_with_compiler",
"//:android",
"//:android-support",
- "//:dagger_with_compiler",
- "@androidsdk//com.android.support:appcompat-v7-25.0.0",
- "@androidsdk//com.android.support:support-fragment-25.0.0",
- "@google_bazel_common//third_party/java/guava",
+ # TODO(ronshapiro): figure out why strict deps is failing without this
+ "@google_bazel_common//third_party/java/jsr250_annotations",
],
)
diff --git a/javatests/dagger/android/support/functional/InjectorsTest.java b/javatests/dagger/android/support/functional/InjectorsTest.java
index e66d702..c5cb150 100644
--- a/javatests/dagger/android/support/functional/InjectorsTest.java
+++ b/javatests/dagger/android/support/functional/InjectorsTest.java
@@ -232,7 +232,7 @@
TestActivityWithScope activityWithScope =
Robolectric.setupActivity(TestActivityWithScope.class);
assertThat(activityWithScope.scopedStringProvider.get())
- .isSameAs(activityWithScope.scopedStringProvider.get());
+ .isSameInstanceAs(activityWithScope.scopedStringProvider.get());
OuterClass.TestInnerClassActivity innerClassActivity =
Robolectric.setupActivity(OuterClass.TestInnerClassActivity.class);
diff --git a/javatests/dagger/functional/BasicTest.java b/javatests/dagger/functional/BasicTest.java
index 39dee30..80fc5e6 100644
--- a/javatests/dagger/functional/BasicTest.java
+++ b/javatests/dagger/functional/BasicTest.java
@@ -83,30 +83,31 @@
}
@Theory public void primitiveArrays(BasicComponent basicComponent) {
- assertThat(basicComponent.getByteArray()).isSameAs(BOUND_BYTE_ARRAY);
- assertThat(basicComponent.getCharArray()).isSameAs(BOUND_CHAR_ARRAY);
- assertThat(basicComponent.getShortArray()).isSameAs(BOUND_SHORT_ARRAY);
- assertThat(basicComponent.getIntArray()).isSameAs(BOUND_INT_ARRAY);
- assertThat(basicComponent.getLongArray()).isSameAs(BOUND_LONG_ARRAY);
- assertThat(basicComponent.getBooleanArray()).isSameAs(BOUND_BOOLEAN_ARRAY);
- assertThat(basicComponent.getFloatArray()).isSameAs(BOUND_FLOAT_ARRAY);
- assertThat(basicComponent.getDoubleArray()).isSameAs(BOUND_DOUBLE_ARRAY);
+ assertThat(basicComponent.getByteArray()).isSameInstanceAs(BOUND_BYTE_ARRAY);
+ assertThat(basicComponent.getCharArray()).isSameInstanceAs(BOUND_CHAR_ARRAY);
+ assertThat(basicComponent.getShortArray()).isSameInstanceAs(BOUND_SHORT_ARRAY);
+ assertThat(basicComponent.getIntArray()).isSameInstanceAs(BOUND_INT_ARRAY);
+ assertThat(basicComponent.getLongArray()).isSameInstanceAs(BOUND_LONG_ARRAY);
+ assertThat(basicComponent.getBooleanArray()).isSameInstanceAs(BOUND_BOOLEAN_ARRAY);
+ assertThat(basicComponent.getFloatArray()).isSameInstanceAs(BOUND_FLOAT_ARRAY);
+ assertThat(basicComponent.getDoubleArray()).isSameInstanceAs(BOUND_DOUBLE_ARRAY);
}
@Theory public void primitiveArrayProviders(BasicComponent basicComponent) {
- assertThat(basicComponent.getByteArrayProvider().get()).isSameAs(BOUND_BYTE_ARRAY);
- assertThat(basicComponent.getCharArrayProvider().get()).isSameAs(BOUND_CHAR_ARRAY);
- assertThat(basicComponent.getShortArrayProvider().get()).isSameAs(BOUND_SHORT_ARRAY);
- assertThat(basicComponent.getIntArrayProvider().get()).isSameAs(BOUND_INT_ARRAY);
- assertThat(basicComponent.getLongArrayProvider().get()).isSameAs(BOUND_LONG_ARRAY);
- assertThat(basicComponent.getBooleanArrayProvider().get()).isSameAs(BOUND_BOOLEAN_ARRAY);
- assertThat(basicComponent.getFloatArrayProvider().get()).isSameAs(BOUND_FLOAT_ARRAY);
- assertThat(basicComponent.getDoubleArrayProvider().get()).isSameAs(BOUND_DOUBLE_ARRAY);
+ assertThat(basicComponent.getByteArrayProvider().get()).isSameInstanceAs(BOUND_BYTE_ARRAY);
+ assertThat(basicComponent.getCharArrayProvider().get()).isSameInstanceAs(BOUND_CHAR_ARRAY);
+ assertThat(basicComponent.getShortArrayProvider().get()).isSameInstanceAs(BOUND_SHORT_ARRAY);
+ assertThat(basicComponent.getIntArrayProvider().get()).isSameInstanceAs(BOUND_INT_ARRAY);
+ assertThat(basicComponent.getLongArrayProvider().get()).isSameInstanceAs(BOUND_LONG_ARRAY);
+ assertThat(basicComponent.getBooleanArrayProvider().get())
+ .isSameInstanceAs(BOUND_BOOLEAN_ARRAY);
+ assertThat(basicComponent.getFloatArrayProvider().get()).isSameInstanceAs(BOUND_FLOAT_ARRAY);
+ assertThat(basicComponent.getDoubleArrayProvider().get()).isSameInstanceAs(BOUND_DOUBLE_ARRAY);
}
@Theory public void noOpMembersInjection(BasicComponent basicComponent) {
Object object = new Object();
- assertThat(basicComponent.noOpMembersInjection(object)).isSameAs(object);
+ assertThat(basicComponent.noOpMembersInjection(object)).isSameInstanceAs(object);
}
@Theory public void basicObject_noDeps(BasicComponent basicComponent) {
@@ -130,9 +131,9 @@
basicComponent.lazyInjectedThingProvider();
Lazy<InjectedThing> lazyInjectedThing1 = lazyInjectedThingProvider.get();
Lazy<InjectedThing> lazyInjectedThing2 = lazyInjectedThingProvider.get();
- assertThat(lazyInjectedThing2).isNotSameAs(lazyInjectedThing1);
- assertThat(lazyInjectedThing1.get()).isSameAs(lazyInjectedThing1.get());
- assertThat(lazyInjectedThing2.get()).isSameAs(lazyInjectedThing2.get());
- assertThat(lazyInjectedThing2.get()).isNotSameAs(lazyInjectedThing1.get());
+ assertThat(lazyInjectedThing2).isNotSameInstanceAs(lazyInjectedThing1);
+ assertThat(lazyInjectedThing1.get()).isSameInstanceAs(lazyInjectedThing1.get());
+ assertThat(lazyInjectedThing2.get()).isSameInstanceAs(lazyInjectedThing2.get());
+ assertThat(lazyInjectedThing2.get()).isNotSameInstanceAs(lazyInjectedThing1.get());
}
}
diff --git a/javatests/dagger/functional/GenericTest.java b/javatests/dagger/functional/GenericTest.java
index be17446..3e4a271 100644
--- a/javatests/dagger/functional/GenericTest.java
+++ b/javatests/dagger/functional/GenericTest.java
@@ -130,26 +130,26 @@
@Test public void singletonScopesAppliesToEachResolvedType() {
SingletonGenericComponent component = DaggerSingletonGenericComponent.create();
ScopedGeneric<A> a = component.scopedGenericA();
- assertThat(a).isSameAs(component.scopedGenericA());
+ assertThat(a).isSameInstanceAs(component.scopedGenericA());
assertThat(a.t).isNotNull();
ScopedGeneric<B> b = component.scopedGenericB();
- assertThat(b).isSameAs(component.scopedGenericB());
+ assertThat(b).isSameInstanceAs(component.scopedGenericB());
assertThat(b.t).isNotNull();
- assertThat(a).isNotSameAs(b);
+ assertThat(a).isNotSameInstanceAs(b);
}
@Test // See https://github.com/google/dagger/issues/671
public void scopedSimpleGenerics() {
SingletonGenericComponent component = DaggerSingletonGenericComponent.create();
ScopedSimpleGeneric<A> a = component.scopedSimpleGenericA();
- assertThat(a).isSameAs(component.scopedSimpleGenericA());
+ assertThat(a).isSameInstanceAs(component.scopedSimpleGenericA());
ScopedSimpleGeneric<B> b = component.scopedSimpleGenericB();
- assertThat(b).isSameAs(component.scopedSimpleGenericB());
+ assertThat(b).isSameInstanceAs(component.scopedSimpleGenericB());
- assertThat(a).isNotSameAs(b);
+ assertThat(a).isNotSameInstanceAs(b);
}
@Test public void genericModules() {
diff --git a/javatests/dagger/functional/LazyMapsTest.java b/javatests/dagger/functional/LazyMapsTest.java
index a3e289a..a441653 100644
--- a/javatests/dagger/functional/LazyMapsTest.java
+++ b/javatests/dagger/functional/LazyMapsTest.java
@@ -36,7 +36,7 @@
String firstGet = laziesMap.get("key").get();
assertThat(firstGet).isEqualTo("value-1");
- assertThat(firstGet).isSameAs(laziesMap.get("key").get());
+ assertThat(firstGet).isSameInstanceAs(laziesMap.get("key").get());
assertThat(component.mapOfLazy().get("key").get()).isEqualTo("value-2");
}
diff --git a/javatests/dagger/functional/ReusableTest.java b/javatests/dagger/functional/ReusableTest.java
index 8149ff4..221b288 100644
--- a/javatests/dagger/functional/ReusableTest.java
+++ b/javatests/dagger/functional/ReusableTest.java
@@ -33,16 +33,16 @@
ChildTwo childTwo = parent.childTwo();
Object reusableInParent = parent.reusableInParent();
- assertThat(parent.reusableInParent()).isSameAs(reusableInParent);
- assertThat(childOne.reusableInParent()).isSameAs(reusableInParent);
- assertThat(childTwo.reusableInParent()).isSameAs(reusableInParent);
+ assertThat(parent.reusableInParent()).isSameInstanceAs(reusableInParent);
+ assertThat(childOne.reusableInParent()).isSameInstanceAs(reusableInParent);
+ assertThat(childTwo.reusableInParent()).isSameInstanceAs(reusableInParent);
Object reusableFromChildOne = childOne.reusableInChild();
- assertThat(childOne.reusableInChild()).isSameAs(reusableFromChildOne);
+ assertThat(childOne.reusableInChild()).isSameInstanceAs(reusableFromChildOne);
Object reusableFromChildTwo = childTwo.reusableInChild();
- assertThat(childTwo.reusableInChild()).isSameAs(reusableFromChildTwo);
+ assertThat(childTwo.reusableInChild()).isSameInstanceAs(reusableFromChildTwo);
- assertThat(reusableFromChildTwo).isNotSameAs(reusableFromChildOne);
+ assertThat(reusableFromChildTwo).isNotSameInstanceAs(reusableFromChildOne);
}
}
diff --git a/javatests/dagger/functional/binds/BindsTest.java b/javatests/dagger/functional/binds/BindsTest.java
index 11695bc..999c303 100644
--- a/javatests/dagger/functional/binds/BindsTest.java
+++ b/javatests/dagger/functional/binds/BindsTest.java
@@ -44,7 +44,7 @@
@Test
public void bindWithScope() {
assertThat(component.qualifiedFooOfStrings())
- .isSameAs(component.qualifiedFooOfStrings());
+ .isSameInstanceAs(component.qualifiedFooOfStrings());
}
@Test
diff --git a/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java b/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
index f6c2818..b77ee3e 100644
--- a/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
+++ b/javatests/dagger/functional/cycle/DoubleCheckCycleTest.java
@@ -95,7 +95,7 @@
assertThat(callCount.get()).isEqualTo(1);
Object second = component.getObject();
assertThat(callCount.get()).isEqualTo(1);
- assertThat(first).isSameAs(second);
+ assertThat(first).isSameInstanceAs(second);
}
@Test
@@ -122,7 +122,7 @@
assertThat(callCount.get()).isEqualTo(2);
Object second = component.getReentrantObject();
assertThat(callCount.get()).isEqualTo(2);
- assertThat(first).isSameAs(second);
+ assertThat(first).isSameInstanceAs(second);
}
@Test
diff --git a/javatests/dagger/functional/cycle/LongCycleTest.java b/javatests/dagger/functional/cycle/LongCycleTest.java
index 4c986b2..a6244b1 100644
--- a/javatests/dagger/functional/cycle/LongCycleTest.java
+++ b/javatests/dagger/functional/cycle/LongCycleTest.java
@@ -17,6 +17,7 @@
package dagger.functional.cycle;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static java.util.Arrays.stream;
@@ -50,6 +51,8 @@
stream(DaggerLongCycle_LongCycleComponent.class.getDeclaredMethods())
.map(Method::getName)
.anyMatch(name -> name.equals("initialize2"));
- assertThat(hasInitialize2).named("LongCycleComponent impl has an initialize2 method").isTrue();
+ assertWithMessage("LongCycleComponent impl has an initialize2 method")
+ .that(hasInitialize2)
+ .isTrue();
}
}
diff --git a/javatests/dagger/functional/factory/FactoryMixedParametersTest.java b/javatests/dagger/functional/factory/FactoryMixedParametersTest.java
index 3c8e2ca..733c673 100644
--- a/javatests/dagger/functional/factory/FactoryMixedParametersTest.java
+++ b/javatests/dagger/functional/factory/FactoryMixedParametersTest.java
@@ -66,7 +66,7 @@
assertThat(component.getDouble()).isEqualTo(3.0);
assertThat(component.object()).isEqualTo("bar");
assertThat(component.getLong()).isEqualTo(2L);
- assertThat(component.randomProvider().get()).isSameAs(random);
- assertThat(component.randomProvider().get()).isSameAs(random);
+ assertThat(component.randomProvider().get()).isSameInstanceAs(random);
+ assertThat(component.randomProvider().get()).isSameInstanceAs(random);
}
}
diff --git a/javatests/dagger/functional/producers/ProducerFactoryTest.java b/javatests/dagger/functional/producers/ProducerFactoryTest.java
index 7b65203..c85e342 100644
--- a/javatests/dagger/functional/producers/ProducerFactoryTest.java
+++ b/javatests/dagger/functional/producers/ProducerFactoryTest.java
@@ -155,7 +155,7 @@
producer.get().get();
fail();
} catch (ExecutionException e) {
- assertThat(e).hasCauseThat().isSameAs(t);
+ assertThat(e).hasCauseThat().isSameInstanceAs(t);
order.verify(monitor).failed(t);
}
diff --git a/javatests/dagger/functional/producers/binds/BindsProducersTest.java b/javatests/dagger/functional/producers/binds/BindsProducersTest.java
index a8c61fe..0949f02 100644
--- a/javatests/dagger/functional/producers/binds/BindsProducersTest.java
+++ b/javatests/dagger/functional/producers/binds/BindsProducersTest.java
@@ -46,7 +46,7 @@
@Test
public void bindWithScope() throws Exception {
assertThat(component.qualifiedFooOfStrings().get())
- .isSameAs(component.qualifiedFooOfStrings().get());
+ .isSameInstanceAs(component.qualifiedFooOfStrings().get());
}
@Test
diff --git a/javatests/dagger/functional/producers/cancellation/ProducerTester.java b/javatests/dagger/functional/producers/cancellation/ProducerTester.java
index 61ddaef..35cf8e9 100644
--- a/javatests/dagger/functional/producers/cancellation/ProducerTester.java
+++ b/javatests/dagger/functional/producers/cancellation/ProducerTester.java
@@ -17,7 +17,7 @@
package dagger.functional.producers.cancellation;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.AbstractFuture;
@@ -93,7 +93,7 @@
/** Asserts that no nodes in this tester have been started. */
void assertNoStartedNodes() {
for (TestFuture future : futures.values()) {
- assertThat(future.isStarted()).named("%s is started", future).isFalse();
+ assertWithMessage("%s is started", future).that(future.isStarted()).isFalse();
}
}
@@ -101,7 +101,7 @@
ImmutableSet.Builder<TestFuture> builder = ImmutableSet.builder();
for (String node : nodes) {
TestFuture future = getOrCreate(node);
- assertThat(assertion.test(future)).named("%s is %s", future, assertion).isTrue();
+ assertWithMessage("%s is %s", future, assertion).that(assertion.test(future)).isTrue();
builder.add(future);
}
return new Only(builder.build(), assertion);
@@ -128,7 +128,7 @@
void only() {
for (TestFuture future : futures.values()) {
if (!expected.contains(future)) {
- assertThat(assertion.test(future)).named("%s is %s", future, assertion).isFalse();
+ assertWithMessage("%s is %s", future, assertion).that(assertion.test(future)).isFalse();
}
}
}
diff --git a/javatests/dagger/functional/producers/monitoring/MonitoringTest.java b/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
index 3c01198..543835f 100644
--- a/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
+++ b/javatests/dagger/functional/producers/monitoring/MonitoringTest.java
@@ -153,7 +153,7 @@
output.get();
fail();
} catch (ExecutionException e) {
- assertThat(Throwables.getRootCause(e)).isSameAs(cause);
+ assertThat(Throwables.getRootCause(e)).isSameInstanceAs(cause);
}
}
diff --git a/javatests/dagger/functional/producers/provisions/ProvisionsTest.java b/javatests/dagger/functional/producers/provisions/ProvisionsTest.java
index 06f3074..47ed2a2 100644
--- a/javatests/dagger/functional/producers/provisions/ProvisionsTest.java
+++ b/javatests/dagger/functional/producers/provisions/ProvisionsTest.java
@@ -31,6 +31,6 @@
public void provisionsOnlyAreHeldInOneProducer() throws Exception {
TestComponent component = DaggerProvisions_TestComponent.create();
Output output = component.output().get();
- assertThat(output.injectedClass1).isSameAs(output.injectedClass2);
+ assertThat(output.injectedClass1).isSameInstanceAs(output.injectedClass2);
}
}
diff --git a/javatests/dagger/functional/producers/scope/ScopeTest.java b/javatests/dagger/functional/producers/scope/ScopeTest.java
index aaa4219..9cfd2c2 100644
--- a/javatests/dagger/functional/producers/scope/ScopeTest.java
+++ b/javatests/dagger/functional/producers/scope/ScopeTest.java
@@ -29,6 +29,6 @@
public void scope() throws Exception {
SetComponent component = DaggerSetComponent.create();
assertThat(component.set().get()).hasSize(1);
- assertThat(component.scopedObject()).isSameAs(component.scopedObject());
+ assertThat(component.scopedObject()).isSameInstanceAs(component.scopedObject());
}
}
diff --git a/javatests/dagger/functional/subcomponent/SubcomponentTest.java b/javatests/dagger/functional/subcomponent/SubcomponentTest.java
index 428de64..c34de0a 100644
--- a/javatests/dagger/functional/subcomponent/SubcomponentTest.java
+++ b/javatests/dagger/functional/subcomponent/SubcomponentTest.java
@@ -53,21 +53,22 @@
@Test
public void scopePropagatesUpward_class() {
assertThat(childComponent.requiresSingleton().singletonType())
- .isSameAs(childComponent.requiresSingleton().singletonType());
+ .isSameInstanceAs(childComponent.requiresSingleton().singletonType());
assertThat(childComponent.requiresSingleton().singletonType())
- .isSameAs(childComponent.newGrandchildComponent().requiresSingleton().singletonType());
+ .isSameInstanceAs(
+ childComponent.newGrandchildComponent().requiresSingleton().singletonType());
}
@Test
public void scopePropagatesUpward_provides() {
- assertThat(childComponent
- .requiresSingleton().unscopedTypeBoundAsSingleton())
- .isSameAs(childComponent
- .requiresSingleton().unscopedTypeBoundAsSingleton());
- assertThat(childComponent
- .requiresSingleton().unscopedTypeBoundAsSingleton())
- .isSameAs(childComponent.newGrandchildComponent()
- .requiresSingleton().unscopedTypeBoundAsSingleton());
+ assertThat(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton())
+ .isSameInstanceAs(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton());
+ assertThat(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton())
+ .isSameInstanceAs(
+ childComponent
+ .newGrandchildComponent()
+ .requiresSingleton()
+ .unscopedTypeBoundAsSingleton());
}
@Test
@@ -88,11 +89,9 @@
public void unscopedProviders() {
assume().that(System.getProperty("dagger.mode")).doesNotContain("FastInit");
assertThat(parentGetters.getUnscopedTypeProvider())
- .isSameAs(childComponent.getUnscopedTypeProvider());
+ .isSameInstanceAs(childComponent.getUnscopedTypeProvider());
assertThat(parentGetters.getUnscopedTypeProvider())
- .isSameAs(childComponent
- .newGrandchildComponent()
- .getUnscopedTypeProvider());
+ .isSameInstanceAs(childComponent.newGrandchildComponent().getUnscopedTypeProvider());
}
@Test
diff --git a/javatests/dagger/functional/subcomponent/repeat/RepeatedModuleTest.java b/javatests/dagger/functional/subcomponent/repeat/RepeatedModuleTest.java
index 7b447eb..9bf3a39 100644
--- a/javatests/dagger/functional/subcomponent/repeat/RepeatedModuleTest.java
+++ b/javatests/dagger/functional/subcomponent/repeat/RepeatedModuleTest.java
@@ -37,7 +37,7 @@
public void repeatedModuleHasSameStateInSubcomponent() {
SubcomponentWithRepeatedModule childComponent =
parentComponent.newChildComponentBuilder().build();
- assertThat(parentComponent.state()).isSameAs(childComponent.state());
+ assertThat(parentComponent.state()).isSameInstanceAs(childComponent.state());
}
@Test
@@ -46,7 +46,7 @@
parentComponent.newChildComponentWithoutRepeatedModule();
SubcomponentWithRepeatedModule grandchildComponent =
childComponent.newGrandchildBuilder().build();
- assertThat(parentComponent.state()).isSameAs(grandchildComponent.state());
+ assertThat(parentComponent.state()).isSameInstanceAs(grandchildComponent.state());
}
@Test
diff --git a/javatests/dagger/internal/DoubleCheckTest.java b/javatests/dagger/internal/DoubleCheckTest.java
index 20abbe5..e36c1bc 100644
--- a/javatests/dagger/internal/DoubleCheckTest.java
+++ b/javatests/dagger/internal/DoubleCheckTest.java
@@ -63,13 +63,13 @@
@Test
public void doubleWrapping_provider() {
assertThat(DoubleCheck.provider(DOUBLE_CHECK_OBJECT_PROVIDER))
- .isSameAs(DOUBLE_CHECK_OBJECT_PROVIDER);
+ .isSameInstanceAs(DOUBLE_CHECK_OBJECT_PROVIDER);
}
@Test
public void doubleWrapping_lazy() {
assertThat(DoubleCheck.lazy(DOUBLE_CHECK_OBJECT_PROVIDER))
- .isSameAs(DOUBLE_CHECK_OBJECT_PROVIDER);
+ .isSameInstanceAs(DOUBLE_CHECK_OBJECT_PROVIDER);
}
@Test
@@ -142,7 +142,7 @@
return object;
});
doubleCheckReference.set(doubleCheck);
- assertThat(doubleCheck.get()).isSameAs(object);
+ assertThat(doubleCheck.get()).isSameInstanceAs(object);
}
@Test public void reentranceReturningDifferentInstances_throwsIllegalStateException() {
@@ -165,6 +165,6 @@
@Test
public void instanceFactoryAsLazyDoesNotWrap() {
Factory<Object> factory = InstanceFactory.create(new Object());
- assertThat(DoubleCheck.lazy(factory)).isSameAs(factory);
+ assertThat(DoubleCheck.lazy(factory)).isSameInstanceAs(factory);
}
}
diff --git a/javatests/dagger/internal/codegen/AccessibilityTest.java b/javatests/dagger/internal/codegen/AccessibilityTest.java
deleted file mode 100644
index bfe73f3..0000000
--- a/javatests/dagger/internal/codegen/AccessibilityTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2015 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen;
-
-import static com.google.common.truth.Truth.assertThat;
-import static dagger.internal.codegen.Accessibility.isElementAccessibleFrom;
-
-import com.google.testing.compile.CompilationRule;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.Elements;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-@SuppressWarnings("unused") // contains a variety things used by the compilation rule for testing
-public class AccessibilityTest {
- /* test data */
- public AccessibilityTest() {}
- protected AccessibilityTest(Object o) {}
- AccessibilityTest(Object o1, Object o2) {}
- private AccessibilityTest(Object o1, Object o2, Object o3) {}
-
- public String publicField;
- protected String protectedField;
- String packagePrivateField;
- private String privateField;
-
- public void publicMethod() {}
- protected void protectedMethod() {}
- void packagePrivateMethod() {}
- private void privateMethod() {}
-
- public static final class PublicNestedClass {}
- protected static final class ProtectedNestedClass {}
- static final class PackagePrivateNestedClass {}
- private static final class PrivateNestedClass {}
-
- @Rule
- public final CompilationRule compilationRule = new CompilationRule();
-
- private TypeElement testElement;
-
- @Before
- public void setUp() {
- Elements elements = compilationRule.getElements();
- testElement = elements.getTypeElement(AccessibilityTest.class.getCanonicalName());
- }
-
- @Test
- public void isElementAccessibleFrom_publicType() {
- assertThat(isElementAccessibleFrom(testElement, "literally.anything")).isTrue();
- }
-
- @Test
- public void isElementAccessibleFrom_publicMethod() {
- Element member = getMemberNamed("publicMethod");
- assertThat(isElementAccessibleFrom(member, "literally.anything")).isTrue();
- }
-
- @Test
- public void isElementAccessibleFrom_protectedMethod() {
- Element member = getMemberNamed("protectedMethod");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isTrue();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- @Test
- public void isElementAccessibleFrom_packagePrivateMethod() {
- Element member = getMemberNamed("packagePrivateMethod");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isTrue();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- @Test
- public void isElementAccessibleFrom_privateMethod() {
- Element member = getMemberNamed( "privateMethod");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isFalse();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- @Test
- public void isElementAccessibleFrom_publicField() {
- Element member = getMemberNamed("publicField");
- assertThat(isElementAccessibleFrom(member, "literally.anything")).isTrue();
- }
-
- @Test
- public void isElementAccessibleFrom_protectedField() {
- Element member = getMemberNamed("protectedField");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isTrue();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- @Test
- public void isElementAccessibleFrom_packagePrivateField() {
- Element member = getMemberNamed("packagePrivateField");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isTrue();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- @Test
- public void isElementAccessibleFrom_privateField() {
- Element member = getMemberNamed("privateField");
- assertThat(isElementAccessibleFrom(member, "dagger.internal.codegen")).isFalse();
- assertThat(isElementAccessibleFrom(member, "not.dagger.internal.codegen")).isFalse();
- }
-
- private Element getMemberNamed(String memberName) {
- for (Element enclosedElement : testElement.getEnclosedElements()) {
- if (enclosedElement.getSimpleName().contentEquals(memberName)) {
- return enclosedElement;
- }
- }
- throw new IllegalArgumentException();
- }
-}
-
diff --git a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java
index c92beb3..bb967b1 100644
--- a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java
+++ b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsMultibindingsTest.java
@@ -118,12 +118,16 @@
"package test;",
"",
"import dagger.internal.GenerationOptions;",
+ "import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATION_OPTIONS_ANNOTATION,
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Set<InAncestor> contributionsInAncestor();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -652,6 +656,9 @@
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract RequiresInAncestorSet missingWithSetDependency();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -791,6 +798,10 @@
" return ImmutableSet.<Multibound>of(",
" LeafModule_ContributionFactory.contribution());",
" }",
+ "",
+ " @Override",
+ " public abstract MissingInLeaf_WillDependOnFrameworkInstance",
+ " willDependOnFrameworkInstance();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -903,12 +914,16 @@
"package test;",
"",
"import dagger.internal.GenerationOptions;",
+ "import java.util.Set;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATION_OPTIONS_ANNOTATION,
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Set<Object> set();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -994,7 +1009,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -1010,7 +1025,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -1291,12 +1306,16 @@
"package test;",
"",
"import dagger.internal.GenerationOptions;",
+ "import java.util.Map;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATION_OPTIONS_ANNOTATION,
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Map<String, InAncestor> contributionsInAncestor();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -2010,6 +2029,10 @@
" return ImmutableMap.<Integer, Multibound>of(",
" 111, LeafModule_ContributionFactory.contribution());",
" }",
+ "",
+ " @Override",
+ " public abstract MissingInLeaf_WillDependOnFrameworkInstance",
+ " willDependOnFrameworkInstance();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
diff --git a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
index 4b51fe2..1bd221a 100644
--- a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
+++ b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
@@ -24,6 +24,7 @@
import static dagger.internal.codegen.GeneratedLines.IMPORT_GENERATED_ANNOTATION;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ObjectArrays;
import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
import javax.tools.JavaFileObject;
@@ -66,6 +67,9 @@
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract MissingInLeaf missingFromComponentMethod();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -164,6 +168,9 @@
" protected DaggerLeaf() {}",
"",
" @Override",
+ " public abstract MissingInLeaf missingComponentMethod();",
+ "",
+ " @Override",
" public DependsOnComponentMethod dependsOnComponentMethod() {",
" return new DependsOnComponentMethod(missingComponentMethod());",
" }",
@@ -472,7 +479,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -488,7 +495,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -636,7 +643,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -652,7 +659,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -750,6 +757,9 @@
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
+ " @Override",
+ " public abstract Leaf.Builder leaf();",
+ "",
" protected abstract class LeafImpl extends DaggerLeaf {",
" protected LeafImpl() {}",
" }",
@@ -779,7 +789,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -795,7 +805,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -938,7 +948,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -954,7 +964,7 @@
" return new MaybeLeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -1098,7 +1108,11 @@
" return Optional.<SatisfiedInAncestor>empty();",
" }",
"}");
- Compilation compilation = compile(filesToCompile.build());
+ Compilation compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
@@ -1154,7 +1168,11 @@
"",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
@@ -1208,7 +1226,11 @@
" return Optional.<SatisfiedInGrandAncestor>empty();",
" }",
"}");
- Compilation compilation = compile(filesToCompile.build());
+ Compilation compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
@@ -1242,7 +1264,11 @@
" protected LeafImpl() {}",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
@@ -1302,7 +1328,11 @@
" }",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGreatAncestor")
@@ -1371,7 +1401,11 @@
" return Optional.<SatisfiedInAncestor>empty();",
" }",
"}");
- Compilation compilation = compile(filesToCompile.build());
+ Compilation compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerLeaf")
@@ -1426,7 +1460,11 @@
" }",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
@@ -1455,12 +1493,17 @@
"package test;",
"",
"import dagger.internal.GenerationOptions;",
+ "import java.util.Optional;",
IMPORT_GENERATED_ANNOTATION,
"",
GENERATION_OPTIONS_ANNOTATION,
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Optional<SatisfiedInGrandAncestor>",
+ " boundInAncestorSatisfiedInGrandAncestor();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -1515,7 +1558,11 @@
" }",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerAncestor")
@@ -1575,7 +1622,11 @@
" }",
" }",
"}");
- compilation = compile(filesToCompile.build());
+ compilation =
+ compile(
+ filesToCompile.build()
+ , CompilerMode.JAVA7
+ );
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile("test.DaggerGrandAncestor")
@@ -2037,7 +2088,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -2053,7 +2104,7 @@
" return new LeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
@@ -2191,7 +2242,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -2207,7 +2258,7 @@
" return new LeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
@@ -2379,7 +2430,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -2395,7 +2446,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -2630,7 +2681,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root, CancellationListener {",
+ "final class DaggerRoot implements Root, CancellationListener {",
" private Provider<Executor> productionImplementationExecutorProvider;",
" private Provider<Root> rootProvider;",
" private Provider<ProductionComponentMonitor> monitorProvider;",
@@ -3153,6 +3204,10 @@
" return LeafModule_FromModuleFactory.fromModule(leafModule());",
" }",
"",
+ " @Override",
+ " public abstract InducesDependenciesOnBuilderFields",
+ " inducesDependenciesOnBuilderFields();",
+ "",
" protected LeafModule leafModule() {",
" return leafModule;",
" }",
@@ -3233,6 +3288,9 @@
"public abstract class DaggerAncestor implements Ancestor {",
" protected DaggerAncestor() {}",
"",
+ " @Override",
+ " public abstract Leaf.Builder leaf();",
+ "",
" protected abstract class LeafImpl extends DaggerLeaf {",
" private String inducedInSubclass;",
"",
@@ -3283,7 +3341,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -3299,7 +3357,7 @@
" return new AncestorImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -3477,7 +3535,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -3493,7 +3551,7 @@
" return new LeafBuilder();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -3632,7 +3690,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private final RepeatedModule repeatedModule;",
"",
" private DaggerRoot(RepeatedModule repeatedModuleParam) {",
@@ -3652,7 +3710,7 @@
" return new LeafBuilder();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private RepeatedModule repeatedModule;",
"",
" private Builder() {}",
@@ -3741,6 +3799,9 @@
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Object bindsWithMissingDependencyInLeaf();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -3781,7 +3842,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -3797,7 +3858,7 @@
" return new LeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -3915,7 +3976,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -3931,7 +3992,7 @@
" return new LeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -4117,7 +4178,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private DaggerRoot() {}",
"",
" public static Builder builder() {",
@@ -4133,7 +4194,7 @@
" return new LeafImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public Root build() {",
@@ -4287,6 +4348,9 @@
" return LeafModule_DepOnFooThingFactory.depOnFooThing(getThing());",
" }",
"",
+ " @Override",
+ " public abstract WillInduceSetOfRunnable willInduceSetOfRunnable();",
+ "",
" protected abstract Thing getThing();",
"}");
Compilation compilation = compile(filesToCompile.build());
@@ -4434,6 +4498,9 @@
GENERATED_ANNOTATION,
"public abstract class DaggerMaybeLeaf implements MaybeLeaf {",
" protected DaggerMaybeLeaf() {}",
+ "",
+ " @Override",
+ " public abstract Inducer inducer();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -4567,6 +4634,9 @@
GENERATED_ANNOTATION,
"public abstract class DaggerLeaf implements Leaf {",
" protected DaggerLeaf() {}",
+ "",
+ " @Override",
+ " public abstract AtInjectRootScoped shouldBeEffectivelyMissingInLeaf();",
"}");
Compilation compilation = compile(filesToCompile.build());
assertThat(compilation).succeededWithoutWarnings();
@@ -4595,7 +4665,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" protected final class LeafImpl extends DaggerLeaf {",
" @Override",
" public AtInjectRootScoped shouldBeEffectivelyMissingInLeaf() {",
@@ -4709,7 +4779,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" protected final class LeafImpl extends DaggerLeaf {",
" @Override",
" public Modified modified() {",
@@ -4928,7 +4998,7 @@
"import a.Mod;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" private final class HasUnusedModuleLeafBuilder",
" extends DaggerHasUnusedModuleLeaf.Builder {",
" @Override",
@@ -5085,7 +5155,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" protected final class LeafImpl extends DaggerLeaf {",
" private LeafImpl() {}",
"",
@@ -5386,7 +5456,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root {",
+ "final class DaggerRoot implements Root {",
" protected final class AncestorImpl extends DaggerAncestor {",
" protected final class LeafImpl extends DaggerAncestor.LeafImpl {",
" @Override",
@@ -5536,7 +5606,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRoot implements Root, CancellationListener {",
+ "final class DaggerRoot implements Root, CancellationListener {",
" private Producer<Dependency> dependencyProducer;",
" private Producer<Injected> replaceInjectWithProducesProducer;",
"",
@@ -5598,7 +5668,10 @@
}
}
- private static Compilation compile(Iterable<JavaFileObject> files) {
- return compilerWithOptions(AHEAD_OF_TIME_SUBCOMPONENTS_MODE).compile(files);
+ private static Compilation compile(Iterable<JavaFileObject> files, CompilerMode... modes) {
+ return compilerWithOptions(
+ ObjectArrays.concat(
+ new CompilerMode[] {AHEAD_OF_TIME_SUBCOMPONENTS_MODE}, modes, CompilerMode.class))
+ .compile(files);
}
}
diff --git a/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java b/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java
new file mode 100644
index 0000000..fda5859
--- /dev/null
+++ b/javatests/dagger/internal/codegen/AnnotationProtoConverterTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.auto.common.AnnotationMirrors;
+import com.google.testing.compile.CompilationRule;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.lang.model.element.AnnotationMirror;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests {@link TypeProtoConverter}. */
+@RunWith(JUnit4.class)
+public class AnnotationProtoConverterTest {
+ @Rule public CompilationRule compilationRule = new CompilationRule();
+
+ private DaggerElements elements;
+ private DaggerTypes types;
+ private AnnotationProtoConverter annotationProtoConverter;
+
+ @Before
+ public void setUp() {
+ this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+ this.types = new DaggerTypes(compilationRule.getTypes(), elements);
+ this.annotationProtoConverter =
+ new AnnotationProtoConverter(new TypeProtoConverter(types, elements));
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface TestAnnotation {
+ byte b();
+ boolean bool();
+ short s();
+ char c();
+ int i();
+ long l();
+ double d();
+ float f();
+
+ String string();
+ RetentionPolicy enumValue();
+ Class<?> classValue();
+ HasDefaults[] nestedAnnotations();
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface HasDefaults {
+ int value() default 2;
+ }
+
+ @TestAnnotation(
+ b = 1,
+ bool = true,
+ s = 2,
+ c = 'c',
+ i = 4,
+ l = 5,
+ d = 6.0d,
+ f = 7.0f,
+ string = "hello, world",
+ enumValue = RetentionPolicy.CLASS,
+ classValue = AnnotationProtoConverter.class,
+ nestedAnnotations = {@HasDefaults, @HasDefaults(8)})
+ static class TestSubject {}
+
+ @Test
+ public void conversion() {
+ AnnotationMirror actual =
+ getOnlyElement(elements.getTypeElement(TestSubject.class).getAnnotationMirrors());
+ AnnotationMirror translated =
+ annotationProtoConverter.fromProto(AnnotationProtoConverter.toProto(actual));
+ assertThat(AnnotationMirrors.equivalence().equivalent(actual, translated)).isTrue();
+ }
+}
diff --git a/javatests/dagger/internal/codegen/BUILD b/javatests/dagger/internal/codegen/BUILD
index bb902ba..ad214ff 100644
--- a/javatests/dagger/internal/codegen/BUILD
+++ b/javatests/dagger/internal/codegen/BUILD
@@ -33,6 +33,9 @@
"//java/dagger/internal/codegen:processor",
"//java/dagger/internal/codegen:validation",
"//java/dagger/internal/codegen:writing",
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
+ "//java/dagger/internal/codegen/serialization",
"//java/dagger/model",
"//java/dagger/model/testing",
"//java/dagger/producers",
diff --git a/javatests/dagger/internal/codegen/BindsInstanceValidationTest.java b/javatests/dagger/internal/codegen/BindsInstanceValidationTest.java
index 063cd73..2496d8b 100644
--- a/javatests/dagger/internal/codegen/BindsInstanceValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsInstanceValidationTest.java
@@ -152,12 +152,12 @@
Compilation compilation = daggerCompiler().compile(bindsFrameworkType);
assertThat(compilation).failed();
assertThat(compilation)
- .hadErrorContaining("@BindsInstance parameters may not be framework types")
+ .hadErrorContaining("@BindsInstance parameters must not be framework types")
.inFile(bindsFrameworkType)
.onLine(8);
assertThat(compilation)
- .hadErrorContaining("@BindsInstance parameters may not be framework types")
+ .hadErrorContaining("@BindsInstance parameters must not be framework types")
.inFile(bindsFrameworkType)
.onLine(9);
}
diff --git a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
index c3de6c0..6ba9e3e 100644
--- a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
@@ -30,7 +30,6 @@
import java.lang.annotation.Retention;
import java.util.Collection;
import javax.inject.Qualifier;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -86,7 +85,6 @@
}
@Test
- @Ignore("TODO: @Binds methods do not check explicitly for void")
public void returnsVoid() {
assertThatMethod("@Binds abstract void returnsVoid(Object impl);").hasError("void");
}
diff --git a/javatests/dagger/internal/codegen/CompilerMode.java b/javatests/dagger/internal/codegen/CompilerMode.java
index 4dcc215..23aa312 100644
--- a/javatests/dagger/internal/codegen/CompilerMode.java
+++ b/javatests/dagger/internal/codegen/CompilerMode.java
@@ -23,7 +23,11 @@
enum CompilerMode {
DEFAULT_MODE,
FAST_INIT_MODE("-Adagger.fastInit=enabled"),
- AHEAD_OF_TIME_SUBCOMPONENTS_MODE("-Adagger.experimentalAheadOfTimeSubcomponents=enabled");
+ AHEAD_OF_TIME_SUBCOMPONENTS_MODE(
+ "-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
+ "-Adagger.emitModifiableMetadataAnnotations=disabled"),
+ JAVA7("-source", "7", "-target", "7"),
+ ;
/** Returns the compiler modes as a list of parameters for parameterized tests */
static final ImmutableList<Object[]> TEST_PARAMETERS =
diff --git a/javatests/dagger/internal/codegen/ComponentBuilderTest.java b/javatests/dagger/internal/codegen/ComponentBuilderTest.java
index 66c54bd..f280bdd 100644
--- a/javatests/dagger/internal/codegen/ComponentBuilderTest.java
+++ b/javatests/dagger/internal/codegen/ComponentBuilderTest.java
@@ -88,7 +88,7 @@
"import dagger.internal.Preconditions;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private static final class Builder implements TestComponent.Builder {",
" private TestModule testModule;",
"",
diff --git a/javatests/dagger/internal/codegen/ComponentCreatorTest.java b/javatests/dagger/internal/codegen/ComponentCreatorTest.java
index 9571b4b..6f4ea8d 100644
--- a/javatests/dagger/internal/codegen/ComponentCreatorTest.java
+++ b/javatests/dagger/internal/codegen/ComponentCreatorTest.java
@@ -96,7 +96,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private static final class Builder implements SimpleComponent.Builder {",
" @Override",
" public SimpleComponent build() {",
@@ -150,7 +150,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final TestModule testModule;",
"",
" private DaggerTestComponent(TestModule testModuleParam) {",
@@ -348,7 +348,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private final Object object;",
"",
" private DaggerSimpleComponent(Object objectParam) {",
@@ -449,7 +449,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private final Integer i;",
"",
" private DaggerSimpleComponent(Integer iParam) {",
diff --git a/javatests/dagger/internal/codegen/ComponentFactoryTest.java b/javatests/dagger/internal/codegen/ComponentFactoryTest.java
index 6674126..403498b 100644
--- a/javatests/dagger/internal/codegen/ComponentFactoryTest.java
+++ b/javatests/dagger/internal/codegen/ComponentFactoryTest.java
@@ -87,7 +87,7 @@
"import dagger.internal.Preconditions;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private static final class Factory implements TestComponent.Factory {",
" @Override",
" public TestComponent newTestComponent(TestModule mod) {",
diff --git a/javatests/dagger/internal/codegen/ComponentProcessorTest.java b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
index bdf8a87..2b79b6f 100644
--- a/javatests/dagger/internal/codegen/ComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
@@ -186,7 +186,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {")
+ "final class DaggerSimpleComponent implements SimpleComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Provider<SomeInjectableType> someInjectableTypeProvider;")
@@ -233,7 +233,7 @@
.addLines(
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public SimpleComponent build() {",
@@ -303,7 +303,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {")
+ "final class DaggerSimpleComponent implements SimpleComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Object someInjectableType = new MemoizedSentinel();",
@@ -423,7 +423,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerOuterType_SimpleComponent",
+ "final class DaggerOuterType_SimpleComponent",
" implements OuterType.SimpleComponent {",
" private DaggerOuterType_SimpleComponent() {}",
"",
@@ -507,7 +507,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final TestModule testModule;",
"",
" private DaggerTestComponent(TestModule testModuleParam) {",
@@ -523,7 +523,7 @@
" return new A(getB());",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private TestModule testModule;",
"",
" public Builder testModule(TestModule testModule) {",
@@ -611,7 +611,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private B getB() {",
" return TestModule_BFactory.b(new C());",
" }",
@@ -709,8 +709,8 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
- " public static final class Builder {",
+ "final class DaggerTestComponent implements TestComponent {",
+ " static final class Builder {",
"",
" @Deprecated",
" public Builder testModule(TestModule testModule) {",
@@ -894,7 +894,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
"",
" private DaggerParent() {}",
"",
@@ -911,7 +911,7 @@
" return ParentModule_NotSubcomponentFactory.notSubcomponent();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
"",
" private Builder() {}",
"",
@@ -1008,7 +1008,7 @@
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" @Override",
" public void inject(SomeInjectedType instance) {",
" injectSomeInjectedType(instance);",
@@ -1065,7 +1065,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private Provider<SimpleComponent> simpleComponentProvider;",
"",
" @SuppressWarnings(\"unchecked\")",
@@ -1130,7 +1130,7 @@
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" @Override",
" public SomeInjectedType createAndInject() {",
" return injectSomeInjectedType(",
@@ -1199,7 +1199,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerBComponent implements BComponent {")
+ "final class DaggerBComponent implements BComponent {")
.addLinesIn(
DEFAULT_MODE,
" private Provider<A> aProvider;")
@@ -1239,7 +1239,7 @@
.addLines(
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private AComponent aComponent;",
"",
" public Builder aComponent(AComponent aComponent) {",
@@ -1344,7 +1344,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final TestModule testModule;",
" private final other.test.TestModule testModule2;",
"",
@@ -1365,7 +1365,7 @@
" return other.test.TestModule_AFactory.a(testModule2);",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private TestModule testModule;",
" private other.test.TestModule testModule2;",
"",
@@ -1470,7 +1470,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerBComponent implements BComponent {",
+ "final class DaggerBComponent implements BComponent {",
" private final AComponent aComponent;",
"",
" private DaggerBComponent(AComponent aComponentParam) {",
@@ -1557,7 +1557,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private B getB() {",
" return new B(new C());",
" }",
@@ -1638,7 +1638,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private DaggerSimpleComponent() {}",
"",
" public static Builder builder() {",
@@ -1654,7 +1654,7 @@
" return new SomeInjectableType();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public SimpleComponent build() {",
@@ -1708,7 +1708,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" @Override",
" public SomeInjectableType someInjectableType() {",
" return new SomeInjectableType();",
@@ -2083,7 +2083,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private DaggerParent() {",
" }",
"",
@@ -2095,7 +2095,7 @@
" return new Builder().build();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
@@ -2246,7 +2246,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public String nonNullableString() {",
" return TestModule_NonNullableStringFactory.nonNullableString());",
@@ -2337,7 +2337,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Integer nonNullableInteger() {",
" return TestModule.primitiveInteger();",
@@ -2413,7 +2413,7 @@
"test.DaggerParent",
"package test;",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private String getString() {",
" return TestModule_StringFactory.string(numberProvider.get());",
" }",
@@ -2483,7 +2483,7 @@
"test.DaggerParent",
"package test;",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private final class ChildImpl implements Child {",
" @Override",
" public String string() {",
@@ -2550,7 +2550,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Injected injected() {",
// Ensure that the qualified @Provides method is used. It's also probably more likely
@@ -2623,7 +2623,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public String unqualified() {",
// Ensure that the unqualified @Provides method is used. It's also probably more likely
@@ -2654,6 +2654,50 @@
.containsElementsIn(generatedComponent);
}
+ @Test
+ public void publicComponentType() {
+ JavaFileObject publicComponent =
+ JavaFileObjects.forSourceLines(
+ "test.PublicComponent",
+ "package test;",
+ "",
+ "import dagger.Component;",
+ "",
+ "@Component",
+ "public interface PublicComponent {}");
+ Compilation compilation = daggerCompiler().compile(publicComponent);
+ assertThat(compilation).succeeded();
+ assertThat(compilation)
+ .generatedSourceFile("test.DaggerPublicComponent")
+ .hasSourceEquivalentTo(
+ JavaFileObjects.forSourceLines(
+ "test.DaggerPublicComponent",
+ "package test;",
+ "",
+ IMPORT_GENERATED_ANNOTATION,
+ "",
+ GENERATED_ANNOTATION,
+ "public final class DaggerPublicComponent implements PublicComponent {",
+ " private DaggerPublicComponent() {}",
+ "",
+ " public static Builder builder() {",
+ " return new Builder();",
+ " }",
+ "",
+ " public static PublicComponent create() {",
+ " return new Builder().build();",
+ " }",
+ "",
+ " public static final class Builder {",
+ " private Builder() {}",
+ "",
+ " public PublicComponent build() {",
+ " return new DaggerPublicComponent();",
+ " }",
+ " }",
+ "}"));
+ }
+
/**
* A {@link ComponentProcessor} that excludes elements using a {@link Predicate}.
*/
diff --git a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
index 3375d7a..85e2d7b 100644
--- a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
+++ b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
@@ -77,7 +77,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final Integer i;",
" private final List<String> list;",
"",
@@ -175,7 +175,7 @@
"import other.OtherPackageModule_LFactory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final ParentModule parentModule;",
" private final OtherPackageModule otherPackageModule;",
"",
@@ -248,7 +248,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final Dep dep;",
"",
" private DaggerTestComponent(Dep depParam) {",
@@ -362,7 +362,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final ParentModule parentModule;",
"",
" private DaggerTestComponent(ParentModule parentModuleParam) {",
@@ -390,7 +390,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final ParentModule parentModule;",
"",
" private DaggerTestComponent(ParentModule parentModuleParam) {",
diff --git a/javatests/dagger/internal/codegen/ComponentValidationTest.java b/javatests/dagger/internal/codegen/ComponentValidationTest.java
index 2208b4a..169a318 100644
--- a/javatests/dagger/internal/codegen/ComponentValidationTest.java
+++ b/javatests/dagger/internal/codegen/ComponentValidationTest.java
@@ -23,7 +23,6 @@
import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
import javax.tools.JavaFileObject;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -139,9 +138,7 @@
assertThat(compilation).hadErrorContaining("wildcard type").inFile(testComponent).onLine(10);
}
- // TODO(b/34107586): Fix and enable test.
@Test
- @Ignore
public void invalidComponentDependencies() {
JavaFileObject testComponent =
JavaFileObjects.forSourceLines(
diff --git a/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java b/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
index c01da44..1fcf7bc 100644
--- a/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
+++ b/javatests/dagger/internal/codegen/DaggerModuleMethodSubject.java
@@ -74,6 +74,7 @@
}
}
+ private final String actual;
private final ImmutableList.Builder<String> imports =
new ImmutableList.Builder<String>()
.add(
@@ -89,6 +90,7 @@
private DaggerModuleMethodSubject(FailureMetadata failureMetadata, String subject) {
super(failureMetadata, subject);
+ this.actual = subject;
}
/**
@@ -155,7 +157,7 @@
}
private int methodLine(String source) {
- String beforeMethod = source.substring(0, source.indexOf(actual()));
+ String beforeMethod = source.substring(0, source.indexOf(actual));
int methodLine = 1;
for (int nextNewlineIndex = beforeMethod.indexOf('\n');
nextNewlineIndex >= 0;
@@ -174,7 +176,7 @@
writer.println(importLine);
}
writer.println();
- writer.printf(declaration, "TestModule", "\n" + actual() + "\n");
+ writer.printf(declaration, "TestModule", "\n" + actual + "\n");
writer.println();
return stringWriter.toString();
}
diff --git a/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java b/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
index fd20350..2f4aecf 100644
--- a/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
+++ b/javatests/dagger/internal/codegen/DelegateBindingExpressionTest.java
@@ -145,7 +145,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Object regularScoped = new MemoizedSentinel();",
@@ -224,7 +224,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Object regularScoped = new MemoizedSentinel();",
@@ -300,7 +300,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Object regularScoped = new MemoizedSentinel();",
@@ -403,7 +403,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
DEFAULT_MODE,
" @SuppressWarnings(\"rawtypes\")",
@@ -512,7 +512,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
DEFAULT_MODE,
" @SuppressWarnings(\"rawtypes\")",
@@ -603,7 +603,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
DEFAULT_MODE,
" @Override",
@@ -705,7 +705,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
DEFAULT_MODE,
" @Override",
@@ -811,7 +811,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerRequestsSubtypeAsProvider",
+ "final class DaggerRequestsSubtypeAsProvider",
" implements RequestsSubtypeAsProvider {")
.addLinesIn(
DEFAULT_MODE,
@@ -904,7 +904,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
DEFAULT_MODE,
" private Provider<String> provideStringProvider;",
diff --git a/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java b/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
index a24b7fe..4a4e0a5 100644
--- a/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
+++ b/javatests/dagger/internal/codegen/DependencyCycleValidationTest.java
@@ -18,10 +18,12 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.TestUtils.endsWithMessage;
import static dagger.internal.codegen.TestUtils.message;
import com.google.testing.compile.Compilation;
import com.google.testing.compile.JavaFileObjects;
+import java.util.regex.Pattern;
import javax.tools.JavaFileObject;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,45 +31,46 @@
@RunWith(JUnit4.class)
public class DependencyCycleValidationTest {
- @Test public void cyclicDependency() {
- JavaFileObject component =
- JavaFileObjects.forSourceLines(
- "test.Outer",
- "package test;",
- "",
- "import dagger.Binds;",
- "import dagger.Component;",
- "import dagger.Module;",
- "import dagger.Provides;",
- "import javax.inject.Inject;",
- "",
- "final class Outer {",
- " static class A {",
- " @Inject A(C cParam) {}",
- " }",
- "",
- " static class B {",
- " @Inject B(A aParam) {}",
- " }",
- "",
- " static class C {",
- " @Inject C(B bParam) {}",
- " }",
- "",
- " @Module",
- " interface MModule {",
- " @Binds Object object(C c);",
- " }",
- "",
- " @Component",
- " interface CComponent {",
- " C getC();",
- " }",
- "}");
+ private static final JavaFileObject SIMPLE_CYCLIC_DEPENDENCY =
+ JavaFileObjects.forSourceLines(
+ "test.Outer",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Component;",
+ "import dagger.Module;",
+ "import dagger.Provides;",
+ "import javax.inject.Inject;",
+ "",
+ "final class Outer {",
+ " static class A {",
+ " @Inject A(C cParam) {}",
+ " }",
+ "",
+ " static class B {",
+ " @Inject B(A aParam) {}",
+ " }",
+ "",
+ " static class C {",
+ " @Inject C(B bParam) {}",
+ " }",
+ "",
+ " @Module",
+ " interface MModule {",
+ " @Binds Object object(C c);",
+ " }",
+ "",
+ " @Component",
+ " interface CComponent {",
+ " C getC();",
+ " }",
+ "}");
- Compilation compilation =
- daggerCompiler().withOptions("-Adagger.moduleBindingValidation=ERROR").compile(component);
+ @Test
+ public void cyclicDependency() {
+ Compilation compilation = daggerCompiler().compile(SIMPLE_CYCLIC_DEPENDENCY);
assertThat(compilation).failed();
+
assertThat(compilation)
.hadErrorContaining(
message(
@@ -80,21 +83,44 @@
" test.Outer.C(bParam)",
" test.Outer.C is provided at",
" test.Outer.CComponent.getC()"))
- .inFile(component)
+ .inFile(SIMPLE_CYCLIC_DEPENDENCY)
.onLineContaining("interface CComponent");
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void cyclicDependencyWithModuleBindingValidation() {
+ // Cycle errors should not show a dependency trace to an entry point when doing full binding
+ // graph validation. So ensure that the message doesn't end with "test.Outer.C is provided at
+ // test.Outer.CComponent.getC()", as the previous test's message does.
+ Pattern moduleBindingValidationError =
+ endsWithMessage(
+ "Found a dependency cycle:",
+ " test.Outer.C is injected at",
+ " test.Outer.A(cParam)",
+ " test.Outer.A is injected at",
+ " test.Outer.B(aParam)",
+ " test.Outer.B is injected at",
+ " test.Outer.C(bParam)");
+
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(SIMPLE_CYCLIC_DEPENDENCY);
+ assertThat(compilation).failed();
+
assertThat(compilation)
- .hadErrorContaining(
- message(
- "Found a dependency cycle:",
- " test.Outer.C is injected at",
- " test.Outer.A(cParam)",
- " test.Outer.A is injected at",
- " test.Outer.B(aParam)",
- " test.Outer.B is injected at",
- " test.Outer.C(bParam)"))
- .inFile(component)
+ .hadErrorContainingMatch(moduleBindingValidationError)
+ .inFile(SIMPLE_CYCLIC_DEPENDENCY)
.onLineContaining("interface MModule");
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(moduleBindingValidationError)
+ .inFile(SIMPLE_CYCLIC_DEPENDENCY)
+ .onLineContaining("interface CComponent");
+
+ assertThat(compilation).hadErrorCount(2);
}
@Test public void cyclicDependencyNotIncludingEntryPoint() {
diff --git a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
index f5863a3..14a6fb9 100644
--- a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
+++ b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
@@ -33,19 +33,19 @@
@RunWith(Parameterized.class)
public class DuplicateBindingsValidationTest {
- @Parameters(name = "moduleBindingValidation={0}")
+ @Parameters(name = "fullBindingGraphValidation={0}")
public static ImmutableList<Object[]> parameters() {
return ImmutableList.copyOf(new Object[][] {{false}, {true}});
}
- private final boolean moduleBindingValidation;
+ private final boolean fullBindingGraphValidation;
- public DuplicateBindingsValidationTest(boolean moduleBindingValidation) {
- this.moduleBindingValidation = moduleBindingValidation;
+ public DuplicateBindingsValidationTest(boolean fullBindingGraphValidation) {
+ this.fullBindingGraphValidation = fullBindingGraphValidation;
}
@Test public void duplicateExplicitBindings_ProvidesAndComponentProvision() {
- assumeFalse(moduleBindingValidation);
+ assumeFalse(fullBindingGraphValidation);
JavaFileObject component = JavaFileObjects.forSourceLines("test.Outer",
"package test;",
@@ -82,7 +82,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -134,7 +134,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -145,7 +145,7 @@
.inFile(component)
.onLineContaining("interface TestComponent");
- if (moduleBindingValidation) {
+ if (fullBindingGraphValidation) {
assertThat(compilation)
.hadErrorContaining(
message(
@@ -157,7 +157,7 @@
}
// The duplicate bindngs are also requested from B, but we don't want to report them again.
- assertThat(compilation).hadErrorCount(moduleBindingValidation ? 2 : 1);
+ assertThat(compilation).hadErrorCount(fullBindingGraphValidation ? 2 : 1);
}
@Test
@@ -200,7 +200,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -211,7 +211,7 @@
.inFile(component)
.onLineContaining("interface TestComponent");
- if (moduleBindingValidation) {
+ if (fullBindingGraphValidation) {
assertThat(compilation)
.hadErrorContaining(
message(
@@ -268,7 +268,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -284,7 +284,7 @@
" @Provides Set<String> test.Outer.TestModule2.stringSet()"))
.inFile(component)
.onLineContaining(
- moduleBindingValidation ? "class TestModule3" : "interface TestComponent");
+ fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
}
@Test
@@ -337,7 +337,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -356,7 +356,7 @@
" @Provides Map<String,String> test.Outer.TestModule2.stringMap()"))
.inFile(component)
.onLineContaining(
- moduleBindingValidation ? "class TestModule3" : "interface TestComponent");
+ fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
}
@Test
@@ -394,7 +394,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -407,7 +407,7 @@
" @Provides Set<String> test.Outer.TestModule2.stringSet()"))
.inFile(component)
.onLineContaining(
- moduleBindingValidation ? "class TestModule3" : "interface TestComponent");
+ fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
}
@Test
@@ -447,7 +447,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -461,7 +461,7 @@
" @Provides Map<String,String> test.Outer.TestModule2.stringMap()"))
.inFile(component)
.onLineContaining(
- moduleBindingValidation ? "class TestModule3" : "interface TestComponent");
+ fullBindingGraphValidation ? "class TestModule3" : "interface TestComponent");
}
@Test public void duplicateBindings_TruncateAfterLimit() {
@@ -574,7 +574,7 @@
"}");
Compilation compilation =
- daggerCompiler().withOptions(moduleBindingValidationOption()).compile(component);
+ daggerCompiler().withOptions(fullBindingGraphValidationOption()).compile(component);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -592,7 +592,7 @@
" @Provides test.Outer.A test.Outer.Module10.provideA()",
" and 2 others"))
.inFile(component)
- .onLineContaining(moduleBindingValidation ? "class Modules" : "interface TestComponent");
+ .onLineContaining(fullBindingGraphValidation ? "class Modules" : "interface TestComponent");
}
@Test
@@ -647,7 +647,7 @@
Compilation compilation =
daggerCompiler()
- .withOptions(moduleBindingValidationOption())
+ .withOptions(fullBindingGraphValidationOption())
.compile(aComponent, bComponent);
assertThat(compilation).failed();
assertThat(compilation)
@@ -657,7 +657,7 @@
" @Provides Object test.A.AModule.abConflict()",
" @Provides Object test.B.BModule.abConflict()"))
.inFile(aComponent)
- .onLineContaining(moduleBindingValidation ? "class AModule" : "interface A {");
+ .onLineContaining(fullBindingGraphValidation ? "class AModule" : "interface A {");
}
@Test
@@ -728,7 +728,7 @@
Compilation compilation =
daggerCompiler()
- .withOptions(moduleBindingValidationOption())
+ .withOptions(fullBindingGraphValidationOption())
.compile(aComponent, bComponent, cComponent);
assertThat(compilation).failed();
assertThat(compilation)
@@ -738,7 +738,7 @@
" @Provides Object test.A.AModule.acConflict()",
" @Provides Object test.C.CModule.acConflict()"))
.inFile(aComponent)
- .onLineContaining(moduleBindingValidation ? "class AModule" : "interface A {");
+ .onLineContaining(fullBindingGraphValidation ? "class AModule" : "interface A {");
}
@Test
@@ -804,7 +804,7 @@
Compilation compilation =
daggerCompiler()
- .withOptions(moduleBindingValidationOption())
+ .withOptions(fullBindingGraphValidationOption())
.compile(aComponent, bComponent, cComponent);
assertThat(compilation).failed();
assertThat(compilation)
@@ -813,13 +813,13 @@
"java.lang.Object is bound multiple times:",
" @Provides Object test.B.BModule.bcConflict()",
" @Provides Object test.C.CModule.bcConflict()"))
- .inFile(moduleBindingValidation ? bComponent : aComponent)
- .onLineContaining(moduleBindingValidation ? "class BModule" : "interface A {");
+ .inFile(fullBindingGraphValidation ? bComponent : aComponent)
+ .onLineContaining(fullBindingGraphValidation ? "class BModule" : "interface A {");
}
@Test
public void childProvidesConflictsWithParentInjects() {
- assumeFalse(moduleBindingValidation);
+ assumeFalse(fullBindingGraphValidation);
JavaFileObject foo =
JavaFileObjects.forSourceLines(
@@ -992,7 +992,7 @@
Compilation compilation =
daggerCompiler()
- .withOptions("-Adagger.nullableValidation=WARNING", moduleBindingValidationOption())
+ .withOptions("-Adagger.nullableValidation=WARNING", fullBindingGraphValidationOption())
.compile(parentConflictsWithChild, child);
assertThat(compilation).failed();
assertThat(compilation)
@@ -1004,11 +1004,13 @@
+ " test.ParentConflictsWithChild.ParentModule.nullableParentChildConflict()"))
.inFile(parentConflictsWithChild)
.onLineContaining(
- moduleBindingValidation ? "class ParentModule" : "interface ParentConflictsWithChild");
+ fullBindingGraphValidation
+ ? "class ParentModule"
+ : "interface ParentConflictsWithChild");
}
- private String moduleBindingValidationOption() {
- return "-Adagger.moduleBindingValidation=" + (moduleBindingValidation ? "ERROR" : "NONE");
+ private String fullBindingGraphValidationOption() {
+ return "-Adagger.fullBindingGraphValidation=" + (fullBindingGraphValidation ? "ERROR" : "NONE");
}
@Test
diff --git a/javatests/dagger/internal/codegen/ElidedFactoriesTest.java b/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
index f8a9ab5..58ddb82 100644
--- a/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
+++ b/javatests/dagger/internal/codegen/ElidedFactoriesTest.java
@@ -85,7 +85,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private DaggerSimpleComponent() {}",
"",
" public static Builder builder() {",
@@ -101,7 +101,7 @@
" return new DependsOnInjected(new InjectedType());",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {",
" }",
"",
@@ -186,7 +186,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private volatile Object scopedType = new MemoizedSentinel();",
" private volatile Provider<DependsOnScoped> dependsOnScopedProvider;",
"",
@@ -232,7 +232,7 @@
" return new NeedsProvider(getDependsOnScopedProvider());",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public SimpleComponent build() {",
@@ -268,7 +268,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private Provider<ScopedType> scopedTypeProvider;",
" private Provider<DependsOnScoped> dependsOnScopedProvider;",
"",
@@ -296,7 +296,7 @@
" return new NeedsProvider(dependsOnScopedProvider);",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {",
" }",
"",
@@ -380,7 +380,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private volatile Object scopedType = new MemoizedSentinel();",
"",
" private DaggerSimpleComponent() {}",
@@ -412,7 +412,7 @@
" return new SubImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public SimpleComponent build() {",
@@ -441,7 +441,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerSimpleComponent implements SimpleComponent {",
+ "final class DaggerSimpleComponent implements SimpleComponent {",
" private Provider<ScopedType> scopedTypeProvider;",
"",
" private DaggerSimpleComponent() {",
@@ -466,7 +466,7 @@
" return new SubImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public SimpleComponent build() {",
diff --git a/javatests/dagger/internal/codegen/FrameworkFieldTest.java b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
index 6905f6a..cbc8c03 100644
--- a/javatests/dagger/internal/codegen/FrameworkFieldTest.java
+++ b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
@@ -17,10 +17,10 @@
package dagger.internal.codegen;
import static com.google.common.truth.Truth.assertThat;
-import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTOR;
-import static dagger.internal.codegen.TypeNames.PROVIDER;
-import static dagger.internal.codegen.TypeNames.membersInjectorOf;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.MEMBERS_INJECTOR;
+import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
+import static dagger.internal.codegen.javapoet.TypeNames.membersInjectorOf;
+import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
import com.google.testing.compile.CompilationRule;
import com.squareup.javapoet.ClassName;
diff --git a/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java b/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java
new file mode 100644
index 0000000..944e307
--- /dev/null
+++ b/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2018 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.testing.compile.CompilationSubject.assertThat;
+import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.TestUtils.endsWithMessage;
+
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import java.util.regex.Pattern;
+import javax.tools.JavaFileObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FullBindingGraphValidationTest {
+ private static final JavaFileObject MODULE_WITH_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.ModuleWithErrors",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module",
+ "interface ModuleWithErrors {",
+ " @Binds Object object1(String string);",
+ " @Binds Object object2(Long l);",
+ " @Binds Number missingDependency(Integer i);",
+ "}");
+
+ // Make sure the error doesn't show other bindings or a dependency trace afterwards.
+ private static final Pattern MODULE_WITH_ERRORS_MESSAGE =
+ endsWithMessage(
+ "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+ " @Binds Object test.ModuleWithErrors.object1(String)",
+ " @Binds Object test.ModuleWithErrors.object2(Long)");
+
+ @Test
+ public void moduleWithErrors_validationTypeNone() {
+ Compilation compilation = daggerCompiler().compile(MODULE_WITH_ERRORS);
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void moduleWithErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(MODULE_WITH_ERRORS);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithErrors");
+
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void moduleWithErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(MODULE_WITH_ERRORS);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithErrors");
+
+ assertThat(compilation).hadWarningCount(1);
+ }
+
+ private static final JavaFileObject INCLUDES_MODULE_WITH_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.IncludesModuleWithErrors",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module(includes = ModuleWithErrors.class)",
+ "interface IncludesModuleWithErrors {}");
+
+ @Test
+ public void includesModuleWithErrors_validationTypeNone() {
+ Compilation compilation =
+ daggerCompiler().compile(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS);
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void includesModuleWithErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithErrors");
+
+ assertThat(compilation)
+ .hadErrorContainingMatch("test.ModuleWithErrors has errors")
+ .inFile(INCLUDES_MODULE_WITH_ERRORS)
+ .onLineContaining("ModuleWithErrors.class");
+
+ assertThat(compilation).hadErrorCount(2);
+ }
+
+ @Test
+ public void includesModuleWithErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithErrors");
+
+ // TODO(b/130284666)
+ assertThat(compilation)
+ .hadWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE)
+ .inFile(INCLUDES_MODULE_WITH_ERRORS)
+ .onLineContaining("interface IncludesModuleWithErrors");
+
+ assertThat(compilation).hadWarningCount(2);
+ }
+
+ private static final JavaFileObject A_MODULE =
+ JavaFileObjects.forSourceLines(
+ "test.AModule",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module",
+ "interface AModule {",
+ " @Binds Object object(String string);",
+ "}");
+
+ private static final JavaFileObject COMBINED_WITH_A_MODULE_HAS_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.CombinedWithAModuleHasErrors",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module(includes = AModule.class)",
+ "interface CombinedWithAModuleHasErrors {",
+ " @Binds Object object(Long l);",
+ "}");
+
+ // Make sure the error doesn't show other bindings or a dependency trace afterwards.
+ private static final Pattern COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE =
+ endsWithMessage(
+ "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+ " @Binds Object test.AModule.object(String)",
+ " @Binds Object test.CombinedWithAModuleHasErrors.object(Long)");
+
+ @Test
+ public void moduleIncludingModuleWithCombinedErrors_validationTypeNone() {
+ Compilation compilation = daggerCompiler().compile(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS);
+
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void moduleIncludingModuleWithCombinedErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE)
+ .inFile(COMBINED_WITH_A_MODULE_HAS_ERRORS)
+ .onLineContaining("interface CombinedWithAModuleHasErrors");
+
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void moduleIncludingModuleWithCombinedErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE)
+ .inFile(COMBINED_WITH_A_MODULE_HAS_ERRORS)
+ .onLineContaining("interface CombinedWithAModuleHasErrors");
+
+ assertThat(compilation).hadWarningCount(1);
+ }
+
+ private static final JavaFileObject SUBCOMPONENT_WITH_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.SubcomponentWithErrors",
+ "package test;",
+ "",
+ "import dagger.BindsInstance;",
+ "import dagger.Subcomponent;",
+ "",
+ "@Subcomponent(modules = AModule.class)",
+ "interface SubcomponentWithErrors {",
+ " @Subcomponent.Builder",
+ " interface Builder {",
+ " @BindsInstance Builder object(Object object);",
+ " SubcomponentWithErrors build();",
+ " }",
+ "}");
+
+ // Make sure the error doesn't show other bindings or a dependency trace afterwards.
+ private static final Pattern SUBCOMPONENT_WITH_ERRORS_MESSAGE =
+ endsWithMessage(
+ "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+ " @Binds Object test.AModule.object(String)",
+ " @BindsInstance test.SubcomponentWithErrors.Builder"
+ + " test.SubcomponentWithErrors.Builder.object(Object)");
+
+ @Test
+ public void subcomponentWithErrors_validationTypeNone() {
+ Compilation compilation = daggerCompiler().compile(SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void subcomponentWithErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface SubcomponentWithErrors");
+
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void subcomponentWithErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface SubcomponentWithErrors");
+
+ assertThat(compilation).hadWarningCount(1);
+ }
+
+ private static final JavaFileObject MODULE_WITH_SUBCOMPONENT_WITH_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.ModuleWithSubcomponentWithErrors",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module(subcomponents = SubcomponentWithErrors.class)",
+ "interface ModuleWithSubcomponentWithErrors {}");
+
+ @Test
+ public void moduleWithSubcomponentWithErrors_validationTypeNone() {
+ Compilation compilation =
+ daggerCompiler()
+ .compile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void moduleWithSubcomponentWithErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithSubcomponentWithErrors");
+
+ // TODO(b/130283677)
+ assertThat(compilation)
+ .hadErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface SubcomponentWithErrors");
+
+ assertThat(compilation).hadErrorCount(2);
+ }
+
+ @Test
+ public void moduleWithSubcomponentWithErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface ModuleWithSubcomponentWithErrors");
+
+ // TODO(b/130283677)
+ assertThat(compilation)
+ .hadWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE)
+ .inFile(SUBCOMPONENT_WITH_ERRORS)
+ .onLineContaining("interface SubcomponentWithErrors");
+
+ assertThat(compilation).hadWarningCount(2);
+ }
+
+ private static final JavaFileObject A_SUBCOMPONENT =
+ JavaFileObjects.forSourceLines(
+ "test.ASubcomponent",
+ "package test;",
+ "",
+ "import dagger.BindsInstance;",
+ "import dagger.Subcomponent;",
+ "",
+ "@Subcomponent(modules = AModule.class)",
+ "interface ASubcomponent {",
+ " @Subcomponent.Builder",
+ " interface Builder {",
+ " ASubcomponent build();",
+ " }",
+ "}");
+
+ private static final JavaFileObject COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS =
+ JavaFileObjects.forSourceLines(
+ "test.CombinedWithASubcomponentHasErrors",
+ "package test;",
+ "",
+ "import dagger.Binds;",
+ "import dagger.Module;",
+ "",
+ "@Module(subcomponents = ASubcomponent.class)",
+ "interface CombinedWithASubcomponentHasErrors {",
+ " @Binds Object object(Number number);",
+ "}");
+
+ // Make sure the error doesn't show other bindings or a dependency trace afterwards.
+ private static final Pattern COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE =
+ endsWithMessage(
+ "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
+ " @Binds Object test.AModule.object(String)",
+ " @Binds Object test.CombinedWithASubcomponentHasErrors.object(Number)");
+
+ @Test
+ public void moduleWithSubcomponentWithCombinedErrors_validationTypeNone() {
+ Compilation compilation =
+ daggerCompiler().compile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE);
+
+ assertThat(compilation).succeededWithoutWarnings();
+ }
+
+ @Test
+ public void moduleWithSubcomponentWithCombinedErrors_validationTypeError() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContainingMatch(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE)
+ .inFile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS)
+ .onLineContaining("interface CombinedWithASubcomponentHasErrors");
+
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void moduleWithSubcomponentWithCombinedErrors_validationTypeWarning() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions("-Adagger.fullBindingGraphValidation=WARNING")
+ .compile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContainingMatch(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE)
+ .inFile(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS)
+ .onLineContaining("interface CombinedWithASubcomponentHasErrors");
+
+ assertThat(compilation).hadWarningCount(1);
+ }
+
+ @Test
+ public void bothAliasesDifferentValues() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions(
+ "-Adagger.moduleBindingValidation=NONE",
+ "-Adagger.fullBindingGraphValidation=ERROR")
+ .compile(MODULE_WITH_ERRORS);
+
+ assertThat(compilation).failed();
+
+ assertThat(compilation)
+ .hadErrorContaining(
+ "Only one of the equivalent options "
+ + "(-Adagger.fullBindingGraphValidation, -Adagger.moduleBindingValidation)"
+ + " should be used; prefer -Adagger.fullBindingGraphValidation");
+
+ assertThat(compilation).hadErrorCount(1);
+ }
+
+ @Test
+ public void bothAliasesSameValue() {
+ Compilation compilation =
+ daggerCompiler()
+ .withOptions(
+ "-Adagger.moduleBindingValidation=NONE", "-Adagger.fullBindingGraphValidation=NONE")
+ .compile(MODULE_WITH_ERRORS);
+
+ assertThat(compilation).succeeded();
+
+ assertThat(compilation)
+ .hadWarningContaining(
+ "Only one of the equivalent options "
+ + "(-Adagger.fullBindingGraphValidation, -Adagger.moduleBindingValidation)"
+ + " should be used; prefer -Adagger.fullBindingGraphValidation");
+ }
+}
diff --git a/javatests/dagger/internal/codegen/GeneratedLines.java b/javatests/dagger/internal/codegen/GeneratedLines.java
index ce8fdab..2aa17ac 100644
--- a/javatests/dagger/internal/codegen/GeneratedLines.java
+++ b/javatests/dagger/internal/codegen/GeneratedLines.java
@@ -16,7 +16,7 @@
package dagger.internal.codegen;
-import static dagger.internal.codegen.CodeBlocks.stringLiteral;
+import static dagger.internal.codegen.javapoet.CodeBlocks.stringLiteral;
import com.squareup.javapoet.CodeBlock;
@@ -27,7 +27,7 @@
public static final String GENERATED_ANNOTATION =
"@Generated("
+ "value = \"dagger.internal.codegen.ComponentProcessor\", "
- + "comments = \"https://google.github.io/dagger\")";
+ + "comments = \"https://dagger.dev\")";
public static final String IMPORT_GENERATED_ANNOTATION =
isBeforeJava9()
diff --git a/javatests/dagger/internal/codegen/KeyFactoryTest.java b/javatests/dagger/internal/codegen/KeyFactoryTest.java
index 69dfeaa..d526ec9 100644
--- a/javatests/dagger/internal/codegen/KeyFactoryTest.java
+++ b/javatests/dagger/internal/codegen/KeyFactoryTest.java
@@ -17,6 +17,7 @@
package dagger.internal.codegen;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import com.google.auto.common.MoreTypes;
@@ -25,6 +26,8 @@
import com.google.testing.compile.CompilationRule;
import dagger.Module;
import dagger.Provides;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.model.Key;
import dagger.model.Key.MultibindingContributionIdentifier;
import dagger.multibindings.ElementsIntoSet;
@@ -61,7 +64,9 @@
@Before public void setUp() {
this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
this.types = new DaggerTypes(compilationRule.getTypes(), elements);
- this.keyFactory = new KeyFactory(types, elements);
+ TypeProtoConverter typeProtoConverter = new TypeProtoConverter(types, elements);
+ this.keyFactory = new KeyFactory(
+ types, elements, typeProtoConverter, new AnnotationProtoConverter(typeProtoConverter));
}
@Test public void forInjectConstructorWithResolvedType() {
@@ -250,7 +255,7 @@
assertThat(intType.getKind().isPrimitive()).isTrue();
TypeMirror integerType = integerMethod.getReturnType();
assertThat(integerType.getKind().isPrimitive()).isFalse();
- assertThat(types.isSameType(intType, integerType)).named("type equality").isFalse();
+ assertWithMessage("type equality").that(types.isSameType(intType, integerType)).isFalse();
Key intKey = keyFactory.forProvidesMethod(intMethod, primitiveHolder);
Key integerKey = keyFactory.forProvidesMethod(integerMethod, boxedPrimitiveHolder);
assertThat(intKey).isEqualTo(integerKey);
diff --git a/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java b/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
index 4cb93a9..ad48712 100644
--- a/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingComponentProcessorTest.java
@@ -129,7 +129,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final MapModuleOne mapModuleOne;",
" private final MapModuleTwo mapModuleTwo;",
" private volatile Provider<Handler> provideAdminHandlerProvider;",
@@ -206,7 +206,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<Handler> provideAdminHandlerProvider;",
" private Provider<Handler> provideLoginHandlerProvider;",
" private Provider<Map<PathEnum, Provider<Handler>>>",
@@ -358,7 +358,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<Map<Class<?>, Integer>> mapOfClassOfAndIntegerProvider;",
"",
" @SuppressWarnings(\"rawtypes\")",
@@ -537,7 +537,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final MapModuleOne mapModuleOne;",
" private final MapModuleTwo mapModuleTwo;",
" private volatile Provider<Handler> provideAdminHandlerProvider;",
@@ -614,7 +614,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<Handler> provideAdminHandlerProvider;",
" private Provider<Handler> provideLoginHandlerProvider;",
" private Provider<Map<String, Provider<Handler>>>",
@@ -738,7 +738,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final MapModuleOne mapModuleOne;",
" private final MapModuleTwo mapModuleTwo;",
" private volatile Provider<Handler> provideAdminHandlerProvider;",
@@ -824,7 +824,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<Handler> provideAdminHandlerProvider;",
" private Provider<Handler> provideLoginHandlerProvider;",
" private Provider<Map<WrappedClassKey, Provider<Handler>>>",
@@ -952,7 +952,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final MapModuleOne mapModuleOne;",
" private final MapModuleTwo mapModuleTwo;",
" private volatile Provider<Map<PathEnum, Handler>>",
@@ -1003,7 +1003,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<Handler> provideAdminHandlerProvider;",
" private Provider<Handler> provideLoginHandlerProvider;",
" private Provider<Map<PathEnum, Handler>> mapOfPathEnumAndHandlerProvider;",
@@ -1081,7 +1081,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final MapModule mapModule;",
"",
" @Override",
diff --git a/javatests/dagger/internal/codegen/MapBindingExpressionTest.java b/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
index 174ada8..11f6bc1 100644
--- a/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingExpressionTest.java
@@ -93,7 +93,7 @@
"import dagger.internal.MapBuilder;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Provider<Integer> provideIntProvider;",
@@ -275,7 +275,7 @@
"import other.UsesInaccessible_Factory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public UsesInaccessible usesInaccessible() {",
" return UsesInaccessible_Factory.newInstance(",
@@ -338,7 +338,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private final ParentModule parentModule;",
"",
" private final class ChildImpl implements Child {",
diff --git a/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java b/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
index 5b0ab6f..aa1a715 100644
--- a/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
+++ b/javatests/dagger/internal/codegen/MapBindingExpressionWithGuavaTest.java
@@ -19,6 +19,7 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
+import static dagger.internal.codegen.Compilers.compilerWithOptions;
import static dagger.internal.codegen.Compilers.daggerCompiler;
import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
@@ -128,7 +129,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Provider<Integer> provideIntProvider;",
@@ -194,7 +195,7 @@
DEFAULT_MODE, //
" 0, MapModule_ProvideIntFactory.create());")
.addLinesIn(
- FAST_INIT_MODE,
+ FAST_INIT_MODE, //
" 0, getProvideIntProvider());")
.addLines(
" }",
@@ -403,7 +404,7 @@
"import other.UsesInaccessible_Factory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public UsesInaccessible usesInaccessible() {",
" return UsesInaccessible_Factory.newInstance((Map) ImmutableMap.of());",
@@ -466,7 +467,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private final ParentModule parentModule;",
"",
" private final class ChildImpl implements Child {",
@@ -522,7 +523,7 @@
"import dagger.producers.internal.CancellationListener;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent, "
+ "final class DaggerTestComponent implements TestComponent, "
+ "CancellationListener {",
" @Override",
" public ListenableFuture<Map<String, String>> stringMap() {",
@@ -534,8 +535,10 @@
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {}",
"}");
Compilation compilation =
- daggerCompiler()
- .withOptions(compilerMode.javacopts())
+ compilerWithOptions(
+ compilerMode
+ , CompilerMode.JAVA7
+ )
.compile(mapModuleFile, componentFile);
assertThat(compilation).succeeded();
assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
index b2ed614..04b0986 100644
--- a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java
@@ -71,7 +71,7 @@
assertThat(compilation).hadErrorCount(1);
compilation =
- daggerCompiler().withOptions("-Adagger.moduleBindingValidation=ERROR").compile(module);
+ daggerCompiler().withOptions("-Adagger.fullBindingGraphValidation=ERROR").compile(module);
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining(
@@ -213,7 +213,7 @@
compilation =
daggerCompiler()
- .withOptions("-Adagger.moduleBindingValidation=ERROR")
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
.compile(module, stringKeyTwoFile);
assertThat(compilation).failed();
assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/MembersInjectionTest.java b/javatests/dagger/internal/codegen/MembersInjectionTest.java
index 88a7706..edaedaf 100644
--- a/javatests/dagger/internal/codegen/MembersInjectionTest.java
+++ b/javatests/dagger/internal/codegen/MembersInjectionTest.java
@@ -88,7 +88,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Child child() {",
" return new Child();",
@@ -148,7 +148,7 @@
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Child child() {",
" return injectChild(Child_Factory.newInstance());",
@@ -1277,7 +1277,7 @@
"import other.UsesInaccessible_Factory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Object getInaccessible() {",
" return injectInaccessible(Inaccessible_Factory.newInstance());",
" }",
@@ -1376,7 +1376,7 @@
"import other.UsesInaccessibles_MembersInjector;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Object listOfInaccessible = new MemoizedSentinel();",
@@ -1506,7 +1506,7 @@
"import other.Supertype_MembersInjector;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Object getSubtype() {",
" return injectSubtype(Subtype_Factory.newInstance());",
" }",
diff --git a/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java b/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
index 16db6cf..687c29a 100644
--- a/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
+++ b/javatests/dagger/internal/codegen/MethodSignatureFormatterTest.java
@@ -23,6 +23,8 @@
import com.google.common.collect.Iterables;
import com.google.testing.compile.CompilationRule;
import dagger.internal.codegen.MethodSignatureFormatterTest.OuterClass.InnerClass;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.inject.Singleton;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
diff --git a/javatests/dagger/internal/codegen/ModuleBindingValidationTest.java b/javatests/dagger/internal/codegen/ModuleBindingValidationTest.java
deleted file mode 100644
index 0121072..0000000
--- a/javatests/dagger/internal/codegen/ModuleBindingValidationTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2018 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen;
-
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.internal.codegen.Compilers.daggerCompiler;
-import static dagger.internal.codegen.TestUtils.message;
-
-import com.google.common.collect.ImmutableList;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import java.util.regex.Pattern;
-import javax.tools.JavaFileObject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class ModuleBindingValidationTest {
- private static final JavaFileObject INCLUDING_MODULE =
- JavaFileObjects.forSourceLines(
- "test.IncludingModule",
- "package test;",
- "",
- "import dagger.Module;",
- "",
- "@Module(includes = TestModule.class)",
- "interface IncludingModule {}");
-
- private static final JavaFileObject MODULE =
- JavaFileObjects.forSourceLines(
- "test.TestModule",
- "package test;",
- "",
- "import dagger.Binds;",
- "import dagger.Module;",
- "",
- "@Module(subcomponents = Child.class)",
- "interface TestModule {",
- " @Binds Object toString(String string);",
- " @Binds Object toLong(Long l);",
- "}");
-
- private static final JavaFileObject CHILD =
- JavaFileObjects.forSourceLines(
- "test.Child",
- "package test;",
- "",
- "import dagger.BindsInstance;",
- "import dagger.Subcomponent;",
- "",
- "@Subcomponent(modules = ChildModule.class)",
- "interface Child {",
- " @Subcomponent.Builder",
- " interface Builder {",
- " @BindsInstance Builder object(Object object);",
- " Child build();",
- " }",
- "}");
-
- private static final JavaFileObject CHILD_MODULE =
- JavaFileObjects.forSourceLines(
- "test.ChildModule",
- "package test;",
- "",
- "import dagger.Module;",
- "import dagger.Binds;",
- "",
- "@Module",
- "interface ChildModule {",
- " @Binds Object toNumber(Number number);",
- "}");
-
- // Make sure the module-level errors don't show a dependency trace afterwards (note the $).
- private static final String MODULE_MESSAGE =
- Pattern.quote(
- message(
- "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
- " @Binds Object test.TestModule.toLong(Long)",
- " @Binds Object test.TestModule.toString(String)"))
- + "$";
-
- // Make sure the module-level errors don't show a dependency trace afterwards (note the $).
- private static final String CHILD_MESSAGE =
- Pattern.quote(
- message(
- "[Dagger/DuplicateBindings] java.lang.Object is bound multiple times:",
- " @BindsInstance test.Child.Builder test.Child.Builder.object(Object)",
- " @Binds Object test.ChildModule.toNumber(Number)",
- " @Binds Object test.TestModule.toLong(Long)",
- " @Binds Object test.TestModule.toString(String)"))
- + "$";
-
- private static final ImmutableList<JavaFileObject> SOURCES =
- ImmutableList.of(MODULE, INCLUDING_MODULE, CHILD, CHILD_MODULE);
-
- @Test
- public void error() {
- Compilation compilation =
- daggerCompiler().withOptions("-Adagger.moduleBindingValidation=ERROR").compile(SOURCES);
- assertThat(compilation).failed();
-
- // Some javacs report only one error for each source line.
- // Assert that one of the expected errors is reported.
- assertThat(compilation)
- .hadErrorContainingMatch(CHILD_MESSAGE + "|" + MODULE_MESSAGE)
- .inFile(MODULE)
- .onLineContaining("interface TestModule");
-
- assertThat(compilation)
- .hadErrorContaining("test.TestModule has errors")
- .inFile(INCLUDING_MODULE)
- .onLineContaining("TestModule.class");
-
- }
-
- @Test
- public void warning() {
- Compilation compilation =
- daggerCompiler().withOptions("-Adagger.moduleBindingValidation=WARNING").compile(SOURCES);
- assertThat(compilation).succeeded();
-
- assertThat(compilation)
- .hadWarningContainingMatch(MODULE_MESSAGE)
- .inFile(MODULE)
- .onLineContaining("interface TestModule");
-
- assertThat(compilation)
- .hadWarningContainingMatch(CHILD_MESSAGE)
- .inFile(MODULE)
- .onLineContaining("interface TestModule");
-
- // TODO(dpb): When warning, don't repeat in including modules.
- assertThat(compilation)
- .hadWarningContainingMatch(MODULE_MESSAGE)
- .inFile(INCLUDING_MODULE)
- .onLineContaining("interface IncludingModule");
-
- assertThat(compilation)
- .hadWarningContainingMatch(CHILD_MESSAGE)
- .inFile(INCLUDING_MODULE)
- .onLineContaining("interface IncludingModule");
-
- // If module binding validation reports warnings, the warnings occur twice:
- // once for TestModule and once for IncludingModule, which includes it.
- assertThat(compilation).hadWarningCount(4);
- }
-
- @Test
- public void none() {
- Compilation compilation =
- daggerCompiler().withOptions("-Adagger.moduleBindingValidation=NONE").compile(SOURCES);
- assertThat(compilation).succeededWithoutWarnings();
- }
-}
diff --git a/javatests/dagger/internal/codegen/NullableBindingValidationTest.java b/javatests/dagger/internal/codegen/NullableBindingValidationTest.java
index eb0dc23..24d5636 100644
--- a/javatests/dagger/internal/codegen/NullableBindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/NullableBindingValidationTest.java
@@ -407,7 +407,7 @@
Compilation compilation =
daggerCompiler()
- .withOptions("-Adagger.moduleBindingValidation=ERROR")
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
.compile(module, NULLABLE);
assertThat(compilation).failed();
assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
index 2803b21..b765166 100644
--- a/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/OptionalBindingRequestFulfillmentTest.java
@@ -19,7 +19,7 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
-import static dagger.internal.codegen.Compilers.daggerCompiler;
+import static dagger.internal.codegen.Compilers.compilerWithOptions;
import static dagger.internal.codegen.GeneratedLines.GENERATED_ANNOTATION;
import com.google.testing.compile.Compilation;
@@ -71,7 +71,7 @@
"",
"public class Maybe {",
" @Module",
- " public interface MaybeModule {",
+ " public static class MaybeModule {",
" @Provides static Maybe provideMaybe() { return new Maybe(); }",
" }",
"}");
@@ -111,7 +111,7 @@
"import com.google.common.base.Optional;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {")
+ "final class DaggerTestComponent implements TestComponent {")
.addLinesIn(
FAST_INIT_MODE,
" private volatile Provider<Maybe> provideMaybeProvider;",
@@ -135,10 +135,10 @@
" public Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {",
" return Optional.of(ProviderOfLazy.create(")
.addLinesIn(
- DEFAULT_MODE,
+ DEFAULT_MODE, //
" Maybe_MaybeModule_ProvideMaybeFactory.create()));")
.addLinesIn(
- FAST_INIT_MODE,
+ FAST_INIT_MODE, //
" getMaybeProvider()));")
.addLines(
" }",
@@ -176,8 +176,10 @@
"}")
.build();
Compilation compilation =
- daggerCompiler()
- .withOptions(compilerMode.javacopts())
+ compilerWithOptions(
+ compilerMode
+ , CompilerMode.JAVA7
+ )
.compile(module, maybe, definitelyNot, component);
assertThat(compilation).succeeded();
assertThat(compilation)
@@ -212,7 +214,7 @@
"",
"public class Maybe {",
" @Module",
- " public interface MaybeModule {",
+ " public static class MaybeModule {",
" @Provides static Maybe provideMaybe() { return new Maybe(); }",
" }",
"}");
@@ -249,8 +251,7 @@
"import dagger.producers.internal.CancellationListener;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent, "
- + "CancellationListener {",
+ "final class DaggerTestComponent implements TestComponent, CancellationListener {",
" @Override",
" public ListenableFuture<Optional<Maybe>> maybe() {",
" return Futures.immediateFuture(",
@@ -268,8 +269,10 @@
"}");
Compilation compilation =
- daggerCompiler()
- .withOptions(compilerMode.javacopts())
+ compilerWithOptions(
+ compilerMode
+ , CompilerMode.JAVA7
+ )
.compile(module, maybe, definitelyNot, component);
assertThat(compilation).succeeded();
assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
index 8c29e50..9a852c7 100644
--- a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
@@ -167,7 +167,7 @@
compilation =
daggerCompiler()
- .withOptions("-Adagger.moduleBindingValidation=ERROR")
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
.compile(producerModuleFile);
assertThat(compilation).failed();
assertThat(compilation)
@@ -249,7 +249,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestClass_SimpleComponent",
+ "final class DaggerTestClass_SimpleComponent",
" implements TestClass.SimpleComponent, CancellationListener {",
" private final TestClass.BModule bModule;",
" private volatile Object productionImplementationExecutor =",
@@ -374,7 +374,7 @@
" Producers.cancel(bProducer, mayInterruptIfRunning);",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private TestClass.AModule aModule;",
" private TestClass.BModule bModule;",
"",
@@ -444,7 +444,7 @@
"import javax.inject.Provider;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestClass_SimpleComponent",
+ "final class DaggerTestClass_SimpleComponent",
" implements TestClass.SimpleComponent, CancellationListener {",
" private Producer<TestClass.A> aEntryPoint;",
" private Provider<Executor> executorProvider;",
@@ -506,7 +506,7 @@
" Producers.cancel(bProducer, mayInterruptIfRunning);",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private TestClass.AModule aModule;",
" private TestClass.BModule bModule;",
"",
@@ -652,7 +652,7 @@
.addLines(
"package test;",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent, CancellationListener {",
+ "final class DaggerParent implements Parent, CancellationListener {",
" private final class ChildImpl implements Child, CancellationListener {",
" @Override",
" public ProductionScoped productionScoped() {")
diff --git a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
index 7106dd9..8453e03 100644
--- a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
+++ b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
@@ -154,7 +154,7 @@
compilation =
daggerCompiler()
- .withOptions("-Adagger.moduleBindingValidation=ERROR")
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
.compile(EXECUTOR_MODULE, component);
assertThat(compilation).failed();
assertThat(compilation)
diff --git a/javatests/dagger/internal/codegen/ScopingValidationTest.java b/javatests/dagger/internal/codegen/ScopingValidationTest.java
index c832206..9efcc2a 100644
--- a/javatests/dagger/internal/codegen/ScopingValidationTest.java
+++ b/javatests/dagger/internal/codegen/ScopingValidationTest.java
@@ -243,7 +243,7 @@
compilation =
daggerCompiler()
- .withOptions("-Adagger.moduleBindingValidation=ERROR")
+ .withOptions("-Adagger.fullBindingGraphValidation=ERROR")
.compile(componentFile, scopeFile, scopeWithAttribute, typeFile, moduleFile);
// The @Inject binding for ScopedType should not appear here, but the @Singleton binding should.
assertThat(compilation)
@@ -259,11 +259,11 @@
}
@Test
- public void moduleBindingValidationDoesNotReportForOneScope() {
+ public void fullBindingGraphValidationDoesNotReportForOneScope() {
Compilation compilation =
daggerCompiler()
.withOptions(
- "-Adagger.moduleBindingValidation=ERROR",
+ "-Adagger.fullBindingGraphValidation=ERROR",
"-Adagger.moduleHasDifferentScopesValidation=ERROR")
.compile(
JavaFileObjects.forSourceLines(
@@ -284,11 +284,11 @@
}
@Test
- public void moduleBindingValidationDoesNotReportInjectBindings() {
+ public void fullBindingGraphValidationDoesNotReportInjectBindings() {
Compilation compilation =
daggerCompiler()
.withOptions(
- "-Adagger.moduleBindingValidation=ERROR",
+ "-Adagger.fullBindingGraphValidation=ERROR",
"-Adagger.moduleHasDifferentScopesValidation=ERROR")
.compile(
JavaFileObjects.forSourceLines(
diff --git a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
index 890ceb8..3fb0e9c 100644
--- a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentTest.java
@@ -97,7 +97,7 @@
"import dagger.internal.SetBuilder;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Set<String> strings() {",
" return SetBuilder.<String>newSetBuilder(2)",
@@ -192,7 +192,7 @@
"import other.UsesInaccessible_Factory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Set getSetOfInaccessible2() {",
" return SetBuilder.newSetBuilder(1)",
" .addAll(TestModule_EmptySetFactory.emptySet())",
@@ -267,7 +267,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private DaggerParent() {}",
"",
" public static Builder builder() {",
@@ -283,7 +283,7 @@
" return new ChildImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" @Deprecated",
diff --git a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
index d39e60b..7a47393 100644
--- a/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
+++ b/javatests/dagger/internal/codegen/SetBindingRequestFulfillmentWithGuavaTest.java
@@ -100,7 +100,7 @@
"import com.google.common.collect.ImmutableSet;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Set<String> strings() {",
" return ImmutableSet.<String>builderWithExpectedSize(2)",
@@ -204,7 +204,7 @@
"import other.UsesInaccessible_Factory;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Set getSetOfInaccessible2() {",
" return ImmutableSet.copyOf(TestModule_EmptySetFactory.emptySet());",
" }",
@@ -275,7 +275,7 @@
"import com.google.common.collect.ImmutableSet;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParent implements Parent {",
+ "final class DaggerParent implements Parent {",
" private final class ChildImpl implements Child {",
" @Override",
" public Set<Object> objectSet() {",
@@ -334,7 +334,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent, "
+ "final class DaggerTestComponent implements TestComponent, "
+ "CancellationListener {",
" private DaggerTestComponent() {}",
"",
@@ -359,7 +359,7 @@
" @Override",
" public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {}",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" private Builder() {}",
"",
" public TestComponent build() {",
diff --git a/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java b/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
index d02676f..de0067f 100644
--- a/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentCreatorRequestFulfillmentTest.java
@@ -101,7 +101,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerC implements C {",
+ "final class DaggerC implements C {",
" @Override",
" public Sub.Builder sBuilder() {",
" return new SubBuilder();",
diff --git a/javatests/dagger/internal/codegen/SubcomponentValidationTest.java b/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
index 66ae11f..ad08160 100644
--- a/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
+++ b/javatests/dagger/internal/codegen/SubcomponentValidationTest.java
@@ -464,7 +464,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParentComponent implements ParentComponent {")
+ "final class DaggerParentComponent implements ParentComponent {")
.addLinesIn(
DEFAULT_MODE,
" @SuppressWarnings(\"unchecked\")",
@@ -664,7 +664,7 @@
"import test.subpackage.Sub;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParentComponent implements ParentComponent {",
+ "final class DaggerParentComponent implements ParentComponent {",
" @Override",
" public Foo.Sub newInstanceSubcomponent() {",
" return new F_SubImpl();",
@@ -675,7 +675,7 @@
" return new NoConflictImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" public ParentComponent build() {",
" return new DaggerParentComponent();",
" }",
@@ -747,13 +747,13 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParentComponent implements ParentComponent {",
+ "final class DaggerParentComponent implements ParentComponent {",
" @Override",
" public Sub newSubcomponent() {",
" return new t_SubImpl();",
" }",
"",
- " public static final class Builder {",
+ " static final class Builder {",
" public ParentComponent build() {",
" return new DaggerParentComponent();",
" }",
@@ -812,7 +812,7 @@
"DaggerParentComponent",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParentComponent implements ParentComponent {",
+ "final class DaggerParentComponent implements ParentComponent {",
" @Override",
" public Sub newSubcomponent() {",
" return new $_SubImpl();",
@@ -889,7 +889,7 @@
"import top1.a.b.c.d.E;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerParentComponent implements ParentComponent {",
+ "final class DaggerParentComponent implements ParentComponent {",
" @Override",
" public E.F.Sub top1() {",
" return new F_SubImpl();",
@@ -946,7 +946,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerC implements C {",
+ "final class DaggerC implements C {",
" @Override",
" public Foo.C newInstanceC() {",
" return new F_CImpl();",
@@ -1008,7 +1008,7 @@
IMPORT_GENERATED_ANNOTATION,
"",
GENERATED_ANNOTATION,
- "public final class DaggerC implements C {",
+ "final class DaggerC implements C {",
" @Override",
" public C.Foo.Sub.Builder fooBuilder() {",
" return new F_SubBuilder();",
diff --git a/javatests/dagger/internal/codegen/SwitchingProviderTest.java b/javatests/dagger/internal/codegen/SwitchingProviderTest.java
index 932daf4..2898f2e 100644
--- a/javatests/dagger/internal/codegen/SwitchingProviderTest.java
+++ b/javatests/dagger/internal/codegen/SwitchingProviderTest.java
@@ -69,7 +69,7 @@
"test.DaggerTestComponent",
"package test;",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private final class SwitchingProvider<T> implements Provider<T> {",
" @SuppressWarnings(\"unchecked\")",
" private T get0() {",
@@ -249,7 +249,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private volatile Provider<String> sProvider;",
"",
" private Provider<String> getStringProvider() {",
@@ -334,7 +334,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private volatile Object charSequence = new MemoizedSentinel();",
" private volatile Provider<CharSequence> cProvider;",
"",
@@ -425,7 +425,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @Override",
" public Provider<Set<String>> setProvider() {",
" return SetFactory.<String>empty();",
@@ -470,7 +470,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" private Provider<MembersInjector<Foo>> fooMembersInjectorProvider;",
"",
" @SuppressWarnings(\"unchecked\")",
@@ -541,7 +541,7 @@
"package test;",
"",
GENERATED_ANNOTATION,
- "public final class DaggerTestComponent implements TestComponent {",
+ "final class DaggerTestComponent implements TestComponent {",
" @SuppressWarnings(\"rawtypes\")",
" private static final Provider ABSENT_JDK_OPTIONAL_PROVIDER =",
" InstanceFactory.create(Optional.empty());",
diff --git a/javatests/dagger/internal/codegen/TestUtils.java b/javatests/dagger/internal/codegen/TestUtils.java
index c02a5f9..69b27511 100644
--- a/javatests/dagger/internal/codegen/TestUtils.java
+++ b/javatests/dagger/internal/codegen/TestUtils.java
@@ -17,6 +17,7 @@
package dagger.internal.codegen;
import com.google.common.base.Joiner;
+import java.util.regex.Pattern;
/** Utility methods useful for codegen tests. */
final class TestUtils {
@@ -24,10 +25,19 @@
private static final Joiner MESSAGE_JOINER = Joiner.on("\n ");
/**
- * Returns the lines joined by newline plus two spaces. Useful for passing to {@link
+ * Returns the lines joined by {@code "\n "}. Useful for passing to {@link
* com.google.testing.compile.CompilationSubject#hadErrorContaining(String)}, etc.
*/
static String message(String... lines) {
return MESSAGE_JOINER.join(lines);
}
+
+ /**
+ * Returns a pattern that matches strings that end with the lines joined by {@code "\n "}. Useful
+ * for passing to {@link
+ * com.google.testing.compile.CompilationSubject#hadErrorContainingMatch(Pattern)}, etc.
+ */
+ static Pattern endsWithMessage(String... lines) {
+ return Pattern.compile(Pattern.quote(message(lines)) + "$");
+ }
}
diff --git a/javatests/dagger/internal/codegen/TypeProtoConverterTest.java b/javatests/dagger/internal/codegen/TypeProtoConverterTest.java
new file mode 100644
index 0000000..8c8628c
--- /dev/null
+++ b/javatests/dagger/internal/codegen/TypeProtoConverterTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+
+import com.google.testing.compile.CompilationRule;
+import dagger.internal.Factory;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
+import dagger.internal.codegen.serialization.TypeProto;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.lang.model.type.TypeMirror;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests {@link TypeProtoConverter}. */
+@RunWith(JUnit4.class)
+public class TypeProtoConverterTest {
+ @Rule public CompilationRule compilationRule = new CompilationRule();
+
+ private DaggerElements elements;
+ private DaggerTypes types;
+ private TypeProtoConverter typeProtoConverter;
+
+ @Before
+ public void setUp() {
+ this.elements = new DaggerElements(compilationRule.getElements(), compilationRule.getTypes());
+ this.types = new DaggerTypes(compilationRule.getTypes(), elements);
+ this.typeProtoConverter = new TypeProtoConverter(types, elements);
+ }
+
+ static class Outer<O> {
+ @SuppressWarnings("ClassCanBeStatic") // We want to specifically test inner classes
+ class Inner<I> {}
+ }
+
+ @SuppressWarnings({"rawtypes", "unused"})
+ static class TypeMirrorConversionSubjects {
+ private Map rawMap;
+ private List<String> listOfString;
+ private List<HashMap<String, Integer>> listOfHashMapOfStringToInteger;
+ private Map<HashMap<String, Integer>, Set<Factory>> mapOfHashMapOfStringToIntegerToSetOfFactory;
+ private Map<HashMap<String, Integer>, Set<Factory>>[][]
+ arrayOfArrayOfMapOfHashMapOfStringToIntegerToSetOfFactory;
+ private Map<HashMap<?, Integer>, ?> mapOfHashMapOfWildcardToIntegerToWildcard;
+ private List<? extends String> listOfWildcardExtendsString;
+ private List<? extends Set<? super String>> listOfWildcardExtendsSetOfWildcardSuperString;
+ private Outer<Object>.Inner<Integer> outerOfObjectDotInnerOfInteger;
+ private List<int[]> listOfIntArray;
+ private List<? extends CharSequence[]> listOfWildcardExtendsCharSequenceArray;
+ }
+
+ @Test
+ public void typeMirrorProtoConversions() {
+ assertProtoConversionEquality(fieldType("rawMap"));
+ assertProtoConversionEquality(fieldType("listOfString"));
+ assertProtoConversionEquality(fieldType("listOfHashMapOfStringToInteger"));
+ assertProtoConversionEquality(fieldType("mapOfHashMapOfStringToIntegerToSetOfFactory"));
+ assertProtoConversionEquality(
+ fieldType("arrayOfArrayOfMapOfHashMapOfStringToIntegerToSetOfFactory"));
+ assertProtoConversionEquality(fieldType("mapOfHashMapOfWildcardToIntegerToWildcard"));
+ assertProtoConversionEquality(fieldType("listOfWildcardExtendsString"));
+ assertProtoConversionEquality(fieldType("listOfWildcardExtendsSetOfWildcardSuperString"));
+ assertProtoConversionEquality(fieldType("outerOfObjectDotInnerOfInteger"));
+ assertProtoConversionEquality(fieldType("listOfIntArray"));
+ assertProtoConversionEquality(fieldType("listOfWildcardExtendsCharSequenceArray"));
+ }
+
+ private TypeMirror fieldType(String fieldName) {
+ return fieldsIn(
+ elements.getTypeElement(TypeMirrorConversionSubjects.class).getEnclosedElements())
+ .stream()
+ .filter(field -> field.getSimpleName().contentEquals(fieldName))
+ .findFirst()
+ .get()
+ .asType();
+ }
+
+ /**
+ * Converts {@link TypeMirror} to a {@link dagger.internal.codegen.serialization.TypeProto} and
+ * back to a {@link TypeMirror}. Asserts that the round-trip conversion is lossless.
+ */
+ private void assertProtoConversionEquality(TypeMirror typeMirror) {
+ TypeProto toProto = TypeProtoConverter.toProto(typeMirror);
+ TypeMirror fromProto = typeProtoConverter.fromProto(toProto);
+ assertWithMessage("expected: %s\nactual : %s", typeMirror, fromProto)
+ .that(types.isSameType(typeMirror, fromProto))
+ .isTrue();
+ }
+}
diff --git a/javatests/dagger/internal/codegen/javapoet/BUILD b/javatests/dagger/internal/codegen/javapoet/BUILD
new file mode 100644
index 0000000..99c11bd
--- /dev/null
+++ b/javatests/dagger/internal/codegen/javapoet/BUILD
@@ -0,0 +1,37 @@
+# Copyright (C) 2017 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Description:
+# Tests for dagger.internal.codegen.javapoet
+
+package(default_visibility = ["//:src"])
+
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
+load("//:test_defs.bzl", "GenJavaTests")
+
+GenJavaTests(
+ name = "javapoet_tests",
+ srcs = glob(["*.java"]),
+ functional = False,
+ javacopts = DOCLINT_HTML_AND_SYNTAX,
+ deps = [
+ "//java/dagger/internal/codegen/javapoet",
+ "//java/dagger/internal/codegen/langmodel",
+ "@google_bazel_common//third_party/java/auto:common",
+ "@google_bazel_common//third_party/java/compile_testing",
+ "@google_bazel_common//third_party/java/javapoet",
+ "@google_bazel_common//third_party/java/junit",
+ "@google_bazel_common//third_party/java/truth",
+ ],
+)
diff --git a/javatests/dagger/internal/codegen/CodeBlocksTest.java b/javatests/dagger/internal/codegen/javapoet/CodeBlocksTest.java
similarity index 93%
rename from javatests/dagger/internal/codegen/CodeBlocksTest.java
rename to javatests/dagger/internal/codegen/javapoet/CodeBlocksTest.java
index ec8df91..ee3681e 100644
--- a/javatests/dagger/internal/codegen/CodeBlocksTest.java
+++ b/javatests/dagger/internal/codegen/javapoet/CodeBlocksTest.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import static com.google.common.truth.Truth.assertThat;
-import static dagger.internal.codegen.CodeBlocks.javadocLinkTo;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.CodeBlocks.javadocLinkTo;
+import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
import static javax.lang.model.element.ElementKind.METHOD;
import com.google.testing.compile.CompilationRule;
diff --git a/javatests/dagger/internal/codegen/ExpressionTest.java b/javatests/dagger/internal/codegen/javapoet/ExpressionTest.java
similarity index 86%
rename from javatests/dagger/internal/codegen/ExpressionTest.java
rename to javatests/dagger/internal/codegen/javapoet/ExpressionTest.java
index e6fe0d1..acfa460 100644
--- a/javatests/dagger/internal/codegen/ExpressionTest.java
+++ b/javatests/dagger/internal/codegen/javapoet/ExpressionTest.java
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package dagger.internal.codegen;
+package dagger.internal.codegen.javapoet;
import static com.google.common.truth.Truth.assertThat;
import com.google.auto.common.MoreTypes;
import com.google.testing.compile.CompilationRule;
+import dagger.internal.codegen.langmodel.DaggerElements;
+import dagger.internal.codegen.langmodel.DaggerTypes;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
@@ -53,11 +55,11 @@
Expression castTo = expression.castTo(supertype);
- assertThat(castTo.type()).isSameAs(supertype);
+ assertThat(castTo.type()).isSameInstanceAs(supertype);
assertThat(castTo.codeBlock().toString())
.isEqualTo(
- "(dagger.internal.codegen.ExpressionTest.Supertype) "
- + "new dagger.internal.codegen.ExpressionTest.Subtype() {}");
+ "(dagger.internal.codegen.javapoet.ExpressionTest.Supertype) "
+ + "new dagger.internal.codegen.javapoet.ExpressionTest.Subtype() {}");
}
@Test
diff --git a/javatests/dagger/producers/ProducedTest.java b/javatests/dagger/producers/ProducedTest.java
index c2028f2..5804141 100644
--- a/javatests/dagger/producers/ProducedTest.java
+++ b/javatests/dagger/producers/ProducedTest.java
@@ -35,7 +35,7 @@
Object o = new Object();
assertThat(Produced.successful(5).get()).isEqualTo(5);
assertThat(Produced.successful("monkey").get()).isEqualTo("monkey");
- assertThat(Produced.successful(o).get()).isSameAs(o);
+ assertThat(Produced.successful(o).get()).isSameInstanceAs(o);
}
@Test public void failedProduced() {
@@ -44,7 +44,7 @@
Produced.failed(cause).get();
fail();
} catch (ExecutionException e) {
- assertThat(e).hasCauseThat().isSameAs(cause);
+ assertThat(e).hasCauseThat().isSameInstanceAs(cause);
}
}
diff --git a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
index ab09ace..b29cb3c 100644
--- a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
+++ b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
@@ -101,7 +101,7 @@
future.get();
fail();
} catch (ExecutionException e) {
- assertThat(e).hasCauseThat().isSameAs(t);
+ assertThat(e).hasCauseThat().isSameInstanceAs(t);
}
verify(monitor).failed(t);
verifyNoMoreInteractions(monitor);
diff --git a/javatests/dagger/producers/internal/MapOfProducerProducerTest.java b/javatests/dagger/producers/internal/MapOfProducerProducerTest.java
index 11fa2d3..f4be15c 100644
--- a/javatests/dagger/producers/internal/MapOfProducerProducerTest.java
+++ b/javatests/dagger/producers/internal/MapOfProducerProducerTest.java
@@ -61,7 +61,7 @@
map.get(42).get().get();
fail();
} catch (ExecutionException e) {
- assertThat(e).hasCauseThat().isSameAs(cause);
+ assertThat(e).hasCauseThat().isSameInstanceAs(cause);
}
}
}
diff --git a/javatests/dagger/producers/internal/MapProducerTest.java b/javatests/dagger/producers/internal/MapProducerTest.java
index 72bd9eb..f74bc41 100644
--- a/javatests/dagger/producers/internal/MapProducerTest.java
+++ b/javatests/dagger/producers/internal/MapProducerTest.java
@@ -55,7 +55,7 @@
mapProducer.get().get();
fail();
} catch (ExecutionException e) {
- assertThat(e).hasCauseThat().isSameAs(cause);
+ assertThat(e).hasCauseThat().isSameInstanceAs(cause);
}
}
}
diff --git a/javatests/dagger/producers/monitoring/TimingRecordersTest.java b/javatests/dagger/producers/monitoring/TimingRecordersTest.java
index ef0f218..4e5d74f 100644
--- a/javatests/dagger/producers/monitoring/TimingRecordersTest.java
+++ b/javatests/dagger/producers/monitoring/TimingRecordersTest.java
@@ -67,7 +67,8 @@
ProductionComponentTimingRecorder.Factory factory =
TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
ImmutableList.<ProductionComponentTimingRecorder.Factory>of());
- assertThat(factory).isSameAs(TimingRecorders.noOpProductionComponentTimingRecorderFactory());
+ assertThat(factory)
+ .isSameInstanceAs(TimingRecorders.noOpProductionComponentTimingRecorderFactory());
}
@Test
@@ -77,7 +78,7 @@
TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
ImmutableList.of(mockProductionComponentTimingRecorderFactory));
assertThat(factory.create(new Object()))
- .isSameAs(TimingRecorders.noOpProductionComponentTimingRecorder());
+ .isSameInstanceAs(TimingRecorders.noOpProductionComponentTimingRecorder());
}
@Test
@@ -88,7 +89,7 @@
TimingRecorders.delegatingProductionComponentTimingRecorderFactory(
ImmutableList.of(mockProductionComponentTimingRecorderFactory));
assertThat(factory.create(new Object()))
- .isSameAs(TimingRecorders.noOpProductionComponentTimingRecorder());
+ .isSameInstanceAs(TimingRecorders.noOpProductionComponentTimingRecorder());
}
@Test
@@ -102,7 +103,7 @@
ImmutableList.of(mockProductionComponentTimingRecorderFactory));
ProductionComponentTimingRecorder recorder = factory.create(new Object());
assertThat(recorder.producerTimingRecorderFor(ProducerToken.create(Object.class)))
- .isSameAs(ProducerTimingRecorder.noOp());
+ .isSameInstanceAs(ProducerTimingRecorder.noOp());
}
@Test
@@ -116,7 +117,7 @@
ImmutableList.of(mockProductionComponentTimingRecorderFactory));
ProductionComponentTimingRecorder recorder = factory.create(new Object());
assertThat(recorder.producerTimingRecorderFor(ProducerToken.create(Object.class)))
- .isSameAs(ProducerTimingRecorder.noOp());
+ .isSameInstanceAs(ProducerTimingRecorder.noOp());
}
@Test
@@ -192,7 +193,7 @@
mockProductionComponentTimingRecorderFactoryB,
mockProductionComponentTimingRecorderFactoryC));
assertThat(factory.create(new Object()))
- .isSameAs(TimingRecorders.noOpProductionComponentTimingRecorder());
+ .isSameInstanceAs(TimingRecorders.noOpProductionComponentTimingRecorder());
}
@Test
@@ -210,7 +211,7 @@
mockProductionComponentTimingRecorderFactoryB,
mockProductionComponentTimingRecorderFactoryC));
assertThat(factory.create(new Object()))
- .isSameAs(TimingRecorders.noOpProductionComponentTimingRecorder());
+ .isSameInstanceAs(TimingRecorders.noOpProductionComponentTimingRecorder());
}
@Test
diff --git a/javatests/dagger/producers/monitoring/internal/MonitorsTest.java b/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
index 5ed6b9d..47ccccb 100644
--- a/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
+++ b/javatests/dagger/producers/monitoring/internal/MonitorsTest.java
@@ -60,7 +60,7 @@
ProductionComponentMonitor.Factory factory =
Monitors.delegatingProductionComponentMonitorFactory(
ImmutableList.<ProductionComponentMonitor.Factory>of());
- assertThat(factory).isSameAs(ProductionComponentMonitor.Factory.noOp());
+ assertThat(factory).isSameInstanceAs(ProductionComponentMonitor.Factory.noOp());
}
@Test
@@ -69,7 +69,7 @@
ProductionComponentMonitor.Factory factory =
Monitors.delegatingProductionComponentMonitorFactory(
ImmutableList.of(mockProductionComponentMonitorFactory));
- assertThat(factory.create(new Object())).isSameAs(ProductionComponentMonitor.noOp());
+ assertThat(factory.create(new Object())).isSameInstanceAs(ProductionComponentMonitor.noOp());
}
@Test
@@ -80,7 +80,7 @@
ProductionComponentMonitor.Factory factory =
Monitors.delegatingProductionComponentMonitorFactory(
ImmutableList.of(mockProductionComponentMonitorFactory));
- assertThat(factory.create(new Object())).isSameAs(ProductionComponentMonitor.noOp());
+ assertThat(factory.create(new Object())).isSameInstanceAs(ProductionComponentMonitor.noOp());
}
@Test
@@ -94,7 +94,7 @@
ImmutableList.of(mockProductionComponentMonitorFactory));
ProductionComponentMonitor monitor = factory.create(new Object());
assertThat(monitor.producerMonitorFor(ProducerToken.create(Object.class)))
- .isSameAs(ProducerMonitor.noOp());
+ .isSameInstanceAs(ProducerMonitor.noOp());
}
@Test
@@ -109,7 +109,7 @@
ImmutableList.of(mockProductionComponentMonitorFactory));
ProductionComponentMonitor monitor = factory.create(new Object());
assertThat(monitor.producerMonitorFor(ProducerToken.create(Object.class)))
- .isSameAs(ProducerMonitor.noOp());
+ .isSameInstanceAs(ProducerMonitor.noOp());
}
@Test
@@ -223,7 +223,7 @@
mockProductionComponentMonitorFactoryA,
mockProductionComponentMonitorFactoryB,
mockProductionComponentMonitorFactoryC));
- assertThat(factory.create(new Object())).isSameAs(ProductionComponentMonitor.noOp());
+ assertThat(factory.create(new Object())).isSameInstanceAs(ProductionComponentMonitor.noOp());
}
@Test
@@ -243,7 +243,7 @@
mockProductionComponentMonitorFactoryA,
mockProductionComponentMonitorFactoryB,
mockProductionComponentMonitorFactoryC));
- assertThat(factory.create(new Object())).isSameAs(ProductionComponentMonitor.noOp());
+ assertThat(factory.create(new Object())).isSameInstanceAs(ProductionComponentMonitor.noOp());
}
@Test
diff --git a/javatests/dagger/spi/SpiPluginTest.java b/javatests/dagger/spi/SpiPluginTest.java
index e0a78b2..613a915 100644
--- a/javatests/dagger/spi/SpiPluginTest.java
+++ b/javatests/dagger/spi/SpiPluginTest.java
@@ -53,8 +53,7 @@
javac()
.withProcessors(new ComponentProcessor())
.withOptions(
- "-Aerror_on_binding=java.lang.Integer",
- "-Adagger.moduleBindingValidation=ERROR")
+ "-Aerror_on_binding=java.lang.Integer", "-Adagger.fullBindingGraphValidation=ERROR")
.compile(module);
assertThat(compilation).failed();
assertThat(compilation)
diff --git a/test_defs.bzl b/test_defs.bzl
index f72927a..15ab299 100644
--- a/test_defs.bzl
+++ b/test_defs.bzl
@@ -22,6 +22,10 @@
"-Adagger.fastInit=enabled",
"-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
],
+ "AheadOfTimeSubcomponents_ForceUseSerializedComponentImplementations": [
+ "-Adagger.experimentalAheadOfTimeSubcomponents=enabled",
+ "-Adagger.forceUseSerializedComponentImplementations=enabled",
+ ],
}
# TODO(ronshapiro): convert this to use bazel_common
diff --git a/tools/BUILD b/tools/BUILD
index b0b3524..7b3cc6c 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -20,14 +20,3 @@
exports_files([
"pom-template.xml",
])
-
-sh_library(
- name = "simple_jar",
- srcs = ["simple_jar.sh"],
-)
-
-sh_test(
- name = "simple_jar_test",
- srcs = ["simple_jar_test.sh"],
- deps = [":simple_jar"],
-)
diff --git a/tools/maven.bzl b/tools/maven.bzl
index 725c48f..2ac0359 100644
--- a/tools/maven.bzl
+++ b/tools/maven.bzl
@@ -35,4 +35,4 @@
**kwargs
)
-POM_VERSION = "2.22.1"
+POM_VERSION = "2.23.1"
diff --git a/tools/simple_jar.bzl b/tools/simple_jar.bzl
deleted file mode 100644
index 967640b..0000000
--- a/tools/simple_jar.bzl
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2018 The Dagger Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Macro for creating a jar from a set of flat files"""
-
-def simple_jar(name, srcs):
- """Creates a jar out of a set of flat files"""
-
- # TODO(dpb): consider creating a Fileset() under the hood to support srcs from different
- # directories, or continually update the same zip file for each source file
- native.genrule(
- name = name,
- srcs = srcs,
- outs = ["%s.jar" % name],
- cmd = """
- $(location //tools:simple_jar.sh) \
- "{package_name}" "$@" $(SRCS)
- """.format(package_name = native.package_name()),
- tools = ["//tools:simple_jar.sh"],
- )
diff --git a/tools/simple_jar.sh b/tools/simple_jar.sh
deleted file mode 100755
index 043c825..0000000
--- a/tools/simple_jar.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2018 The Dagger Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-
-find_dirname() {
- local package_name="$1"
- shift
-
- local src src_dirname dirname=""
- for src in "$@"; do
- if [[ ! "${src}" =~ ^((.*/)?"${package_name}")/ ]]; then
- echo "Sources must be in ${package_name}: $0" >&2
- return 1
- fi
- src_dirname="${BASH_REMATCH[1]}"
- if [[ "${dirname:=${src_dirname}}" != "${src_dirname}" ]]; then
- echo "Sources must all be in the same directory: $@" >&2
- return 1
- fi
- done
-
- if [[ -z "${dirname}" ]]; then
- echo "No sources provided" >&2
- return 1
- fi
-
- echo "${dirname}"
-}
-
-main() {
- local package_name="$1"
- local out="${PWD}/$2"
- shift 2
-
- local dirname
- dirname="$(find_dirname "${package_name}" "$@")"
- cd "${dirname}"
- zip "${out}" -r * &> /dev/null
-}
-
-if [[ -z "$TEST_SRCDIR" ]]; then
- main "$@"
-fi
diff --git a/tools/simple_jar_test.sh b/tools/simple_jar_test.sh
deleted file mode 100755
index d03d3d0..0000000
--- a/tools/simple_jar_test.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 The Dagger Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-
-fail() {
- local message="${1:-failed}"
- echo "${message} at $(caller)" >&2
- return 1
-}
-
-. "tools/simple_jar.sh"
-
-[[ "$(find_dirname some/package some/package/a/b/c some/package/d/e/f)" \
- == "some/package" ]] \
- || fail "no prefix"
-
-[[ "$(find_dirname some/package prefix/some/package/a prefix/some/package/b)" \
- == "prefix/some/package" ]] \
- || fail "with prefix"
-
-! find_dirname some/package some/package/a other/package/b >/dev/null \
- || fail "expected failure if one file is in the wrong package"
-
-! find_dirname some/package other/package/a other/package/b >/dev/null \
- || fail "expected failure if all files are in the wrong package"
-
-! find_dirname some/package some/package/a prefix/some/package/b >/dev/null \
- || fail "expected failure if files have different prefixes"
-
-! find_dirname some/package >/dev/null \
- || fail "expected failure with no sources"
-
-true