Roll forward with fix of 'Support Kotlin val properties with @BindValue.'
When matching javax.lang elements with Kotlin metadata we rely on descriptors. When generating the descriptor of an element whose type is an error (type is not yet resolved, probably a generated type) a fully modeled type is not needed and instead the ErrorType can be treated as a DeclaredType, using its reference names to generate a descriptor containing the class name in its internal form. The fix here is to do just that instead of defaulting to throwing an error when visiting an ErrorType while generating a descriptor.
PiperOrigin-RevId: 333089177
diff --git a/java/dagger/hilt/android/processor/BUILD b/java/dagger/hilt/android/processor/BUILD
index 5be8dbd..95ccb17 100644
--- a/java/dagger/hilt/android/processor/BUILD
+++ b/java/dagger/hilt/android/processor/BUILD
@@ -51,6 +51,7 @@
"//java/dagger/hilt/processor/internal:component_descriptor",
"//java/dagger/hilt/processor/internal:component_names",
"//java/dagger/hilt/processor/internal:components",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/hilt/processor/internal/aggregateddeps:annotation",
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
index 77bac27..f538448 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
@@ -35,9 +35,10 @@
import dagger.hilt.processor.internal.BadInputException;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.Components;
-import dagger.hilt.processor.internal.KotlinMetadata;
+import dagger.hilt.processor.internal.KotlinMetadataUtils;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.Processors;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -251,11 +252,10 @@
// If this AndroidEntryPoint is a Kotlin class and its base type is also Kotlin and has
// default values declared in its constructor then error out because for the short-form
// usage of @AndroidEntryPoint the bytecode transformation will be done incorrectly.
+ KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
ProcessorErrors.checkState(
- !KotlinMetadata.of(androidEntryPointElement).isPresent()
- || !KotlinMetadata.of(baseElement)
- .map(KotlinMetadata::containsConstructorWithDefaultParam)
- .orElse(false),
+ !metadataUtil.hasMetadata(androidEntryPointElement)
+ || !metadataUtil.containsConstructorWithDefaultParam(baseElement),
baseElement,
"The base class, '%s', of the @AndroidEntryPoint, '%s', contains a constructor with "
+ "default parameters. This is currently not supported by the Gradle plugin. Either "
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD b/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
index ff96498..55e9ddc 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
@@ -85,9 +85,11 @@
"//java/dagger/hilt/android/processor/internal:android_classnames",
"//java/dagger/hilt/processor/internal:classnames",
"//java/dagger/hilt/processor/internal:components",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/codegen/kotlin",
"//java/dagger/internal/guava:base",
"//java/dagger/internal/guava:collect",
"@google_bazel_common//third_party/java/auto:value",
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BUILD b/java/dagger/hilt/android/processor/internal/bindvalue/BUILD
index 092fe0b..cbc51b3 100644
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BUILD
+++ b/java/dagger/hilt/android/processor/internal/bindvalue/BUILD
@@ -37,9 +37,11 @@
"//java/dagger/hilt/processor/internal:base_processor",
"//java/dagger/hilt/processor/internal:classnames",
"//java/dagger/hilt/processor/internal:components",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/codegen/kotlin",
"//java/dagger/internal/guava:base",
"//java/dagger/internal/guava:collect",
"@google_bazel_common//third_party/java/auto:service",
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java
index 39005b7..d18e7c4 100644
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java
+++ b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueGenerator.java
@@ -23,6 +23,7 @@
import com.google.common.collect.ImmutableSet;
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.ParameterSpec;
@@ -137,7 +138,11 @@
} else {
builder
.addParameter(testClassName, "test")
- .addStatement("return test.$L", bindValue.variableElement().getSimpleName());
+ .addStatement(
+ "return $L",
+ bindValue.getterElement().isPresent()
+ ? CodeBlock.of("test.$L()", bindValue.getterElement().get().getSimpleName())
+ : CodeBlock.of("test.$L", bindValue.variableElement().getSimpleName()));
}
ClassName annotationClassName = bindValue.annotationName();
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
index a592429..bf50288 100644
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
+++ b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
@@ -18,19 +18,23 @@
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import com.google.auto.common.MoreElements;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
import dagger.hilt.processor.internal.ClassNames;
+import dagger.hilt.processor.internal.KotlinMetadataUtils;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.Processors;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
import java.util.Collection;
import java.util.Optional;
import javax.inject.Inject;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
@@ -80,6 +84,8 @@
abstract Optional<AnnotationMirror> mapKey();
+ abstract Optional<ExecutableElement> getterElement();
+
static BindValueElement create(Element element) {
ImmutableList<ClassName> bindValues = BindValueProcessor.getBindValueAnnotations(element);
ProcessorErrors.checkState(
@@ -97,12 +103,26 @@
annotationClassName.simpleName(),
element);
- ProcessorErrors.checkState(
- !element.getModifiers().contains(Modifier.PRIVATE),
- element,
- "@%s fields cannot be private. Found: %s",
- annotationClassName.simpleName(),
- element);
+ KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
+ Optional<ExecutableElement> propertyGetter =
+ metadataUtil.hasMetadata(element)
+ ? metadataUtil.getPropertyGetter(MoreElements.asVariable(element))
+ : Optional.empty();
+ if (propertyGetter.isPresent()) {
+ ProcessorErrors.checkState(
+ !propertyGetter.get().getModifiers().contains(Modifier.PRIVATE),
+ element,
+ "@%s field getter cannot be private. Found: %s",
+ annotationClassName.simpleName(),
+ element);
+ } else {
+ ProcessorErrors.checkState(
+ !element.getModifiers().contains(Modifier.PRIVATE),
+ element,
+ "@%s fields cannot be private. Found: %s",
+ annotationClassName.simpleName(),
+ element);
+ }
ProcessorErrors.checkState(
!Processors.hasAnnotation(element, Inject.class),
@@ -151,7 +171,8 @@
qualifiers.isEmpty()
? Optional.<AnnotationMirror>empty()
: Optional.<AnnotationMirror>of(qualifiers.get(0)),
- optionalMapKeys);
+ optionalMapKeys,
+ propertyGetter);
}
}
}
diff --git a/java/dagger/hilt/processor/BUILD b/java/dagger/hilt/processor/BUILD
index c04d0bc..b772e9d 100644
--- a/java/dagger/hilt/processor/BUILD
+++ b/java/dagger/hilt/processor/BUILD
@@ -69,6 +69,7 @@
"//java/dagger/hilt/processor/internal:component_descriptor",
"//java/dagger/hilt/processor/internal:component_names",
"//java/dagger/hilt/processor/internal:components",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/hilt/processor/internal/aggregateddeps:annotation",
diff --git a/java/dagger/hilt/processor/internal/BUILD b/java/dagger/hilt/processor/internal/BUILD
index 9c9eb9f..ac57c70 100644
--- a/java/dagger/hilt/processor/internal/BUILD
+++ b/java/dagger/hilt/processor/internal/BUILD
@@ -54,16 +54,20 @@
name = "processors",
srcs = [
"AnnotationValues.java",
- "KotlinMetadata.java",
"Processors.java",
],
deps = [
":classnames",
+ ":kotlin",
":processor_errors",
"//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/codegen/kotlin",
+ "//java/dagger/internal/codegen/langmodel",
"//java/dagger/internal/guava:base",
"//java/dagger/internal/guava:collect",
"@google_bazel_common//third_party/java/javapoet",
+ "@google_bazel_common//third_party/java/jsr305_annotations",
+ "@google_bazel_common//third_party/java/jsr330_inject",
"@maven//:com_google_auto_auto_common",
"@maven//:org_jetbrains_kotlin_kotlin_stdlib",
"@maven//:org_jetbrains_kotlinx_kotlinx_metadata_jvm",
@@ -128,6 +132,15 @@
],
)
+java_library(
+ name = "kotlin",
+ srcs = ["KotlinMetadataUtils.java"],
+ deps = [
+ "//:dagger_with_compiler",
+ "//java/dagger/internal/codegen/kotlin",
+ ],
+)
+
filegroup(
name = "srcs_filegroup",
srcs = glob(["*"]),
diff --git a/java/dagger/hilt/processor/internal/KotlinMetadata.java b/java/dagger/hilt/processor/internal/KotlinMetadata.java
deleted file mode 100644
index 2fe6321..0000000
--- a/java/dagger/hilt/processor/internal/KotlinMetadata.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2020 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.hilt.processor.internal;
-
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import static dagger.hilt.processor.internal.AnnotationValues.getIntArrayValue;
-import static dagger.hilt.processor.internal.AnnotationValues.getIntValue;
-import static dagger.hilt.processor.internal.AnnotationValues.getOptionalIntValue;
-import static dagger.hilt.processor.internal.AnnotationValues.getOptionalStringValue;
-import static dagger.hilt.processor.internal.AnnotationValues.getStringArrayValue;
-import static dagger.hilt.processor.internal.AnnotationValues.getStringValue;
-
-import com.google.auto.common.MoreElements;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.TypeElement;
-import kotlin.Metadata;
-import kotlinx.metadata.Flag;
-import kotlinx.metadata.Flag.ValueParameter;
-import kotlinx.metadata.KmClassVisitor;
-import kotlinx.metadata.KmConstructorVisitor;
-import kotlinx.metadata.KmValueParameterVisitor;
-import kotlinx.metadata.jvm.KotlinClassHeader;
-import kotlinx.metadata.jvm.KotlinClassMetadata;
-
-/** Data class of a TypeElement and its Kotlin metadata. */
-public final class KotlinMetadata {
-
- private final KotlinClassMetadata.Class metadata;
- private final TypeElement typeElement;
-
- /**
- * Kotlin metadata flag for this class.
- *
- * <p>Use {@link Flag.Class} to apply the right mask and obtain a specific value.
- */
- private final int flags;
-
- private KotlinMetadata(KotlinClassMetadata.Class metadata, TypeElement typeElement, int flags) {
- this.metadata = metadata;
- this.typeElement = typeElement;
- this.flags = flags;
- }
-
- /** Returns true if the type element of this metadata is a Kotlin object. */
- public boolean isObjectClass() {
- return Flag.Class.IS_OBJECT.invoke(flags);
- }
-
- /** Returns true if the type element of this metadata is a Kotlin companion object. */
- public boolean isCompanionObjectClass() {
- return Flag.Class.IS_COMPANION_OBJECT.invoke(flags);
- }
-
- /**
- * Returns true if the type element of this metadata contains a constructor with declared default
- * values.
- */
- public boolean containsConstructorWithDefaultParam() {
- final boolean[] containsDefaultParam = { false };
- metadata.accept(
- new KmClassVisitor() {
- private final KmConstructorVisitor constructorVisitor =
- new KmConstructorVisitor() {
- @Override
- public KmValueParameterVisitor visitValueParameter(int flags, String name) {
- containsDefaultParam[0] |= ValueParameter.DECLARES_DEFAULT_VALUE.invoke(flags);
- return super.visitValueParameter(flags, name);
- }
- };
-
- @Override
- public KmConstructorVisitor visitConstructor(int flags) {
- return constructorVisitor;
- }
- });
- return containsDefaultParam[0];
- }
-
- /** Returns the Kotlin Metadata of a given type element. */
- public static Optional<KotlinMetadata> of(TypeElement typeElement) {
- if (!isAnnotationPresent(typeElement, Metadata.class)) {
- return Optional.empty();
- }
-
- KotlinClassMetadata.Class metadata = metadataOf(typeElement);
- MetadataVisitor visitor = new MetadataVisitor();
- metadata.accept(visitor);
- return Optional.of(new KotlinMetadata(metadata, typeElement, visitor.classFlags));
- }
-
- private static KotlinClassMetadata.Class metadataOf(TypeElement typeElement) {
- AnnotationMirror metadataAnnotation =
- MoreElements.getAnnotationMirror(typeElement, Metadata.class).get();
- KotlinClassHeader header =
- new KotlinClassHeader(
- getIntValue(metadataAnnotation, "k"),
- getIntArrayValue(metadataAnnotation, "mv"),
- getIntArrayValue(metadataAnnotation, "bv"),
- getStringArrayValue(metadataAnnotation, "d1"),
- getStringArrayValue(metadataAnnotation, "d2"),
- getStringValue(metadataAnnotation, "xs"),
- getOptionalStringValue(metadataAnnotation, "pn").orElse(null),
- getOptionalIntValue(metadataAnnotation, "xi").orElse(null));
- KotlinClassMetadata metadata = KotlinClassMetadata.read(header);
- if (metadata == null) {
- // Should only happen on Kotlin < 1.0 (i.e. metadata version < 1.1)
- throw new IllegalStateException(
- "Unsupported metadata version. Check that your Kotlin version is >= 1.0");
- }
- if (metadata instanceof KotlinClassMetadata.Class) {
- return (KotlinClassMetadata.Class) metadata;
- } else {
- throw new IllegalStateException("Unsupported metadata type: " + metadata);
- }
- }
-
- private static final class MetadataVisitor extends KmClassVisitor {
- int classFlags;
-
- @Override
- public void visit(int flags, String s) {
- this.classFlags = flags;
- }
- }
-}
diff --git a/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java b/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java
new file mode 100644
index 0000000..0f762ac
--- /dev/null
+++ b/java/dagger/hilt/processor/internal/KotlinMetadataUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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.hilt.processor.internal;
+
+import dagger.Component;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
+import javax.inject.Singleton;
+
+/** A single-use provider of {@link KotlinMetadataUtil}. */
+public final class KotlinMetadataUtils {
+
+ @Singleton
+ @Component
+ interface MetadataComponent {
+ KotlinMetadataUtil get();
+ }
+
+ /** Gets the metadata util. */
+ public static KotlinMetadataUtil getMetadataUtil() {
+ return DaggerKotlinMetadataUtils_MetadataComponent.create().get();
+ }
+
+ private KotlinMetadataUtils() {}
+}
diff --git a/java/dagger/hilt/processor/internal/Processors.java b/java/dagger/hilt/processor/internal/Processors.java
index b387caf..a0cafc5 100644
--- a/java/dagger/hilt/processor/internal/Processors.java
+++ b/java/dagger/hilt/processor/internal/Processors.java
@@ -17,15 +17,18 @@
package dagger.hilt.processor.internal;
import static com.google.auto.common.MoreElements.asPackage;
+import static com.google.auto.common.MoreElements.asVariable;
import static com.google.common.base.Preconditions.checkNotNull;
import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.STATIC;
+import com.google.auto.common.AnnotationMirrors;
import com.google.auto.common.GeneratedAnnotations;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.base.CaseFormat;
+import com.google.common.base.Equivalence.Wrapper;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.FluentIterable;
@@ -43,6 +46,8 @@
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.extension.DaggerStreams;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
import java.lang.annotation.Annotation;
import java.util.LinkedHashSet;
import java.util.List;
@@ -50,8 +55,10 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
+import javax.inject.Qualifier;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
@@ -726,7 +733,27 @@
/** Returns Qualifier annotated annotations found on an element. */
public static ImmutableList<AnnotationMirror> getQualifierAnnotations(Element element) {
- return getAnnotationsAnnotatedWith(element, ClassNames.QUALIFIER);
+ // TODO(bcorso): Consolidate this logic with InjectionAnnotations in Dagger
+ ImmutableSet<? extends AnnotationMirror> qualifiers =
+ AnnotationMirrors.getAnnotatedAnnotations(element, Qualifier.class);
+ KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
+ // TODO(user): Apply an additional check to verify field element has a @BindValue
+ if (element.getKind() == ElementKind.FIELD && metadataUtil.hasMetadata(element)) {
+ VariableElement fieldElement = asVariable(element);
+ return Stream.concat(
+ qualifiers.stream(),
+ metadataUtil.isMissingSyntheticPropertyForAnnotations(fieldElement)
+ ? Stream.empty()
+ : metadataUtil
+ .getSyntheticPropertyAnnotations(fieldElement, Qualifier.class)
+ .stream())
+ .map(AnnotationMirrors.equivalence()::wrap)
+ .distinct()
+ .map(Wrapper::get)
+ .collect(DaggerStreams.toImmutableList());
+ } else {
+ return ImmutableList.copyOf(qualifiers);
+ }
}
/** Returns Scope annotated annotations found on an element. */
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java b/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java
index 7d04be5..d07e773 100644
--- a/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java
+++ b/java/dagger/hilt/processor/internal/aggregateddeps/AggregatedDepsProcessor.java
@@ -37,9 +37,10 @@
import dagger.hilt.processor.internal.BaseProcessor;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.Components;
-import dagger.hilt.processor.internal.KotlinMetadata;
+import dagger.hilt.processor.internal.KotlinMetadataUtils;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.Processors;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -290,10 +291,8 @@
}
private static boolean isKotlinObject(TypeElement type) {
- Optional<KotlinMetadata> kotlinMetadata = KotlinMetadata.of(type);
- return kotlinMetadata
- .map(metadata -> metadata.isObjectClass() || metadata.isCompanionObjectClass())
- .orElse(false);
+ KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
+ return metadataUtil.isObjectClass(type) || metadataUtil.isCompanionObjectClass(type);
}
private static boolean hasOnlyStaticProvides(TypeElement module) {
diff --git a/java/dagger/hilt/processor/internal/aggregateddeps/BUILD b/java/dagger/hilt/processor/internal/aggregateddeps/BUILD
index f18f7d3..1eb8d36 100644
--- a/java/dagger/hilt/processor/internal/aggregateddeps/BUILD
+++ b/java/dagger/hilt/processor/internal/aggregateddeps/BUILD
@@ -48,9 +48,11 @@
"//java/dagger/hilt/processor/internal:base_processor",
"//java/dagger/hilt/processor/internal:classnames",
"//java/dagger/hilt/processor/internal:components",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/codegen/kotlin",
"//java/dagger/internal/guava:collect",
"@google_bazel_common//third_party/java/auto:service",
"@google_bazel_common//third_party/java/auto:value",
diff --git a/java/dagger/hilt/processor/internal/root/BUILD b/java/dagger/hilt/processor/internal/root/BUILD
index 3a0d0ac..923a79e 100644
--- a/java/dagger/hilt/processor/internal/root/BUILD
+++ b/java/dagger/hilt/processor/internal/root/BUILD
@@ -69,11 +69,13 @@
":root_type",
"//java/dagger/hilt/processor/internal:classnames",
"//java/dagger/hilt/processor/internal:component_descriptor",
+ "//java/dagger/hilt/processor/internal:kotlin",
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
"//java/dagger/hilt/processor/internal/aliasof:alias_ofs",
"//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/codegen/kotlin",
"//java/dagger/internal/guava:base",
"//java/dagger/internal/guava:collect",
"@google_bazel_common//third_party/java/auto:value",
diff --git a/java/dagger/hilt/processor/internal/root/RootMetadata.java b/java/dagger/hilt/processor/internal/root/RootMetadata.java
index 59a3348..d712341 100644
--- a/java/dagger/hilt/processor/internal/root/RootMetadata.java
+++ b/java/dagger/hilt/processor/internal/root/RootMetadata.java
@@ -30,12 +30,12 @@
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.ComponentDescriptor;
import dagger.hilt.processor.internal.ComponentTree;
-import dagger.hilt.processor.internal.KotlinMetadata;
+import dagger.hilt.processor.internal.KotlinMetadataUtils;
import dagger.hilt.processor.internal.Processors;
import dagger.hilt.processor.internal.aggregateddeps.ComponentDependencies;
import dagger.hilt.processor.internal.aliasof.AliasOfs;
+import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
import java.util.List;
-import java.util.Optional;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
@@ -194,11 +194,9 @@
}
private static boolean daggerCanConstruct(TypeElement type) {
- Optional<KotlinMetadata> kotlinMetadata = KotlinMetadata.of(type);
+ KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
boolean isKotlinObject =
- kotlinMetadata
- .map(metadata -> metadata.isObjectClass() || metadata.isCompanionObjectClass())
- .orElse(false);
+ metadataUtil.isObjectClass(type) || metadataUtil.isCompanionObjectClass(type);
if (isKotlinObject) {
// Treat Kotlin object modules as if Dagger can construct them (it technically can't, but it
// doesn't need to as it can use them since all their provision methods are static).
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index e64b99b..323e9ca 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -79,6 +79,7 @@
artifact_target_libs = [
":package_info",
"//java/dagger/internal/codegen/base",
+ "//java/dagger/internal/codegen/base:shared",
"//java/dagger/internal/codegen/binding",
"//java/dagger/internal/codegen/bindinggraphvalidation",
"//java/dagger/internal/codegen/compileroption",
diff --git a/java/dagger/internal/codegen/base/BUILD b/java/dagger/internal/codegen/base/BUILD
index 71a5f29..0bcbb12 100644
--- a/java/dagger/internal/codegen/base/BUILD
+++ b/java/dagger/internal/codegen/base/BUILD
@@ -19,12 +19,23 @@
package(default_visibility = ["//:src"])
+SHARED_SOURCES = [
+ "ClearableCache.java",
+ "MoreAnnotationMirrors.java",
+ "MoreAnnotationValues.java",
+]
+
java_library(
name = "base",
- srcs = glob(["*.java"]),
+ srcs = glob(
+ ["*.java"],
+ exclude = SHARED_SOURCES,
+ ),
plugins = ["//java/dagger/internal/codegen/bootstrap"],
tags = ["maven:merged"],
+ exports = [":shared"],
deps = [
+ ":shared",
"//java/dagger:core",
"//java/dagger/internal/codegen/extension",
"//java/dagger/internal/codegen/javapoet",
@@ -40,3 +51,16 @@
"@maven//:com_google_auto_auto_common",
],
)
+
+# TODO(bcorso): Remove this target but first remove spi and producers from :base
+java_library(
+ name = "shared",
+ srcs = SHARED_SOURCES,
+ tags = ["maven:merged"],
+ deps = [
+ "//java/dagger/internal/codegen/extension",
+ "//java/dagger/internal/guava:base",
+ "//java/dagger/internal/guava:collect",
+ "@maven//:com_google_auto_auto_common",
+ ],
+)
diff --git a/java/dagger/internal/codegen/kotlin/BUILD b/java/dagger/internal/codegen/kotlin/BUILD
index b41dfb5..f919ef9 100644
--- a/java/dagger/internal/codegen/kotlin/BUILD
+++ b/java/dagger/internal/codegen/kotlin/BUILD
@@ -25,7 +25,8 @@
plugins = ["//java/dagger/internal/codegen/bootstrap"],
tags = ["maven:merged"],
deps = [
- "//java/dagger/internal/codegen/base",
+ "//java/dagger:core",
+ "//java/dagger/internal/codegen/base:shared",
"//java/dagger/internal/codegen/extension",
"//java/dagger/internal/codegen/langmodel",
"//java/dagger/internal/guava:base",
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java b/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
index c65f5e1..b7ba174 100644
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
+++ b/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
@@ -16,7 +16,6 @@
package dagger.internal.codegen.kotlin;
-import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.common.base.Preconditions.checkArgument;
import static dagger.internal.codegen.base.MoreAnnotationValues.getIntArrayValue;
import static dagger.internal.codegen.base.MoreAnnotationValues.getIntValue;
@@ -39,18 +38,21 @@
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
-import javax.inject.Inject;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import kotlin.Metadata;
import kotlinx.metadata.Flag;
+import kotlinx.metadata.Flag.ValueParameter;
import kotlinx.metadata.KmClassVisitor;
+import kotlinx.metadata.KmConstructorVisitor;
import kotlinx.metadata.KmExtensionType;
import kotlinx.metadata.KmPropertyExtensionVisitor;
import kotlinx.metadata.KmPropertyVisitor;
+import kotlinx.metadata.KmValueParameterVisitor;
import kotlinx.metadata.jvm.JvmFieldSignature;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
@@ -62,49 +64,156 @@
private final TypeElement typeElement;
+ private final KotlinClassMetadata.Class data;
+
/**
* Kotlin metadata flag for this class.
*
* <p>Use {@link Flag.Class} to apply the right mask and obtain a specific value.
*/
- private final int flags;
+ private final Supplier<Integer> flags;
- private final Optional<String> companionObjectName;
+ private final Supplier<Optional<String>> companionObjectName;
- // Map that associates @Inject field elements with its Kotlin synthetic method for annotations.
+ private final Supplier<List<Property>> properties;
+
+ private final Supplier<Map<String, Property>> propertyDescriptors;
+
+ private final Supplier<Map<String, ExecutableElement>> methodDescriptors;
+
+ // Map that associates field elements with its Kotlin synthetic method for annotations.
private final Supplier<Map<VariableElement, Optional<MethodForAnnotations>>>
elementFieldAnnotationMethodMap;
- private KotlinMetadata(
- TypeElement typeElement,
- int flags,
- Optional<String> companionObjectName,
- List<Property> properties) {
+ // Map that associates field elements with its Kotlin getter method.
+ private final Supplier<Map<VariableElement, Optional<ExecutableElement>>>
+ elementFieldGetterMethodMap;
+
+ private final Supplier<Boolean> containsConstructorWithDefaultParam;
+
+ private KotlinMetadata(TypeElement typeElement, KotlinClassMetadata.Class data) {
this.typeElement = typeElement;
- this.flags = flags;
- this.companionObjectName = companionObjectName;
+ this.data = data;
+ this.flags = Suppliers.memoize(this::retrieveFlags);
+ this.companionObjectName = Suppliers.memoize(this::retrieveCompanionObjectName);
+ this.properties = Suppliers.memoize(this::retrieveProperties);
+ this.propertyDescriptors =
+ Suppliers.memoize(
+ () ->
+ properties.get().stream()
+ .filter(property -> property.getFieldSignature().isPresent())
+ .collect(
+ Collectors.toMap(
+ property -> property.getFieldSignature().get(), Function.identity())));
+ this.methodDescriptors =
+ Suppliers.memoize(
+ () ->
+ ElementFilter.methodsIn(typeElement.getEnclosedElements()).stream()
+ .collect(
+ Collectors.toMap(
+ DaggerElements::getMethodDescriptor, Function.identity())));
this.elementFieldAnnotationMethodMap =
Suppliers.memoize(
- () -> {
- Map<String, Property> propertyDescriptors =
- properties.stream()
- .filter(property -> property.getFieldSignature().isPresent())
- .collect(
- Collectors.toMap(
- property -> property.getFieldSignature().get(), Function.identity()));
- Map<String, ExecutableElement> methodDescriptors =
- ElementFilter.methodsIn(typeElement.getEnclosedElements()).stream()
- .collect(
- Collectors.toMap(
- DaggerElements::getMethodDescriptor, Function.identity()));
- return mapFieldToAnnotationMethod(propertyDescriptors, methodDescriptors);
- });
+ () -> mapFieldToAnnotationMethod(propertyDescriptors.get(), methodDescriptors.get()));
+ this.elementFieldGetterMethodMap =
+ Suppliers.memoize(
+ () -> mapFieldToGetterMethod(propertyDescriptors.get(), methodDescriptors.get()));
+ this.containsConstructorWithDefaultParam =
+ Suppliers.memoize(this::checkConstructorForDefaultParam);
+ }
+
+ private int retrieveFlags() {
+ FlagsVisitor visitor = new FlagsVisitor();
+ data.accept(visitor);
+ return visitor.flags;
+ }
+
+ private static final class FlagsVisitor extends KmClassVisitor {
+
+ int flags;
+
+ @Override
+ public void visit(int flags, String name) {
+ this.flags = flags;
+ }
+ }
+
+ private Optional<String> retrieveCompanionObjectName() {
+ CompanionObjectNameVisitor visitor = new CompanionObjectNameVisitor();
+ data.accept(visitor);
+ return visitor.name;
+ }
+
+ private static final class CompanionObjectNameVisitor extends KmClassVisitor {
+
+ Optional<String> name = Optional.empty();
+
+ @Override
+ public void visitCompanionObject(String name) {
+ this.name = Optional.of(name);
+ }
+ }
+
+ private List<Property> retrieveProperties() {
+ PropertiesVisitor visitor = new PropertiesVisitor();
+ data.accept(visitor);
+ return visitor.properties;
+ }
+
+ private static final class PropertiesVisitor extends KmClassVisitor {
+
+ List<Property> properties = new ArrayList<>();
+
+ @Override
+ public KmPropertyVisitor visitProperty(
+ int flags, String name, int getterFlags, int setterFlags) {
+ return new KmPropertyVisitor() {
+ Optional<String> fieldSignature;
+ Optional<String> getterSignature = Optional.empty();
+ Optional<String> methodForAnnotationsSignature = Optional.empty();
+
+ @Override
+ public KmPropertyExtensionVisitor visitExtensions(KmExtensionType kmExtensionType) {
+ if (!kmExtensionType.equals(JvmPropertyExtensionVisitor.TYPE)) {
+ return null;
+ }
+
+ return new JvmPropertyExtensionVisitor() {
+ @Override
+ public void visit(
+ int jvmFlags,
+ @Nullable JvmFieldSignature jvmFieldSignature,
+ @Nullable JvmMethodSignature jvmGetterSignature,
+ @Nullable JvmMethodSignature jvmSetterSignature) {
+ fieldSignature =
+ Optional.ofNullable(jvmFieldSignature).map(JvmFieldSignature::asString);
+ getterSignature =
+ Optional.ofNullable(jvmGetterSignature).map(JvmMethodSignature::asString);
+ }
+
+ @Override
+ public void visitSyntheticMethodForAnnotations(
+ @Nullable JvmMethodSignature methodSignature) {
+ methodForAnnotationsSignature =
+ Optional.ofNullable(methodSignature).map(JvmMethodSignature::asString);
+ }
+ };
+ }
+
+ @Override
+ public void visitEnd() {
+ properties.add(
+ new Property(
+ name, flags, fieldSignature, getterSignature, methodForAnnotationsSignature));
+ }
+ };
+ }
}
private Map<VariableElement, Optional<MethodForAnnotations>> mapFieldToAnnotationMethod(
Map<String, Property> propertyDescriptors, Map<String, ExecutableElement> methodDescriptors) {
return ElementFilter.fieldsIn(typeElement.getEnclosedElements()).stream()
- .filter(field -> isAnnotationPresent(field, Inject.class))
+ .filter(field -> !field.getModifiers().contains(Modifier.STATIC))
.collect(
Collectors.toMap(
Function.identity(),
@@ -120,6 +229,20 @@
.orElse(MethodForAnnotations.MISSING))));
}
+ private Map<VariableElement, Optional<ExecutableElement>> mapFieldToGetterMethod(
+ Map<String, Property> propertyDescriptors, Map<String, ExecutableElement> methodDescriptors) {
+ return ElementFilter.fieldsIn(typeElement.getEnclosedElements()).stream()
+ .filter(field -> !field.getModifiers().contains(Modifier.STATIC))
+ .collect(
+ Collectors.toMap(
+ Function.identity(),
+ field ->
+ findProperty(field, propertyDescriptors)
+ .getGetterMethodSignature()
+ .flatMap(
+ signature -> Optional.ofNullable(methodDescriptors.get(signature)))));
+ }
+
private Property findProperty(VariableElement field, Map<String, Property> propertyDescriptors) {
String fieldDescriptor = getFieldDescriptor(field);
if (propertyDescriptors.containsKey(fieldDescriptor)) {
@@ -132,11 +255,34 @@
}
}
+ private boolean checkConstructorForDefaultParam() {
+ ConstructorWithDefaultParamVisitor visitor = new ConstructorWithDefaultParamVisitor();
+ data.accept(visitor);
+ return visitor.containsConstructorWithDefaultParam;
+ }
+
+ private static final class ConstructorWithDefaultParamVisitor extends KmClassVisitor {
+
+ boolean containsConstructorWithDefaultParam;
+
+ @Override
+ public KmConstructorVisitor visitConstructor(int flags) {
+ return new KmConstructorVisitor() {
+ @Override
+ public KmValueParameterVisitor visitValueParameter(int flags, String name) {
+ containsConstructorWithDefaultParam |=
+ ValueParameter.DECLARES_DEFAULT_VALUE.invoke(flags);
+ return super.visitValueParameter(flags, name);
+ }
+ };
+ }
+ }
+
TypeElement getTypeElement() {
return typeElement;
}
- /** Gets the synthetic method for annotations of a given @Inject annotated field element. */
+ /** Gets the synthetic method for annotations of a given field element. */
Optional<ExecutableElement> getSyntheticAnnotationMethod(VariableElement fieldElement) {
checkArgument(elementFieldAnnotationMethodMap.get().containsKey(fieldElement));
return elementFieldAnnotationMethodMap
@@ -169,12 +315,12 @@
}
boolean isObjectClass() {
- return Flag.Class.IS_OBJECT.invoke(flags);
+ return Flag.Class.IS_OBJECT.invoke(flags.get());
}
/** Returns true if the type element of this metadata is a Kotlin companion object. */
boolean isCompanionObjectClass() {
- return Flag.Class.IS_COMPANION_OBJECT.invoke(flags);
+ return Flag.Class.IS_COMPANION_OBJECT.invoke(flags.get());
}
/**
@@ -183,19 +329,27 @@
* returns an empty optional.
*/
Optional<String> getCompanionObjectName() {
- return companionObjectName;
+ return companionObjectName.get();
}
boolean isPrivate() {
- return Flag.IS_PRIVATE.invoke(flags);
+ return Flag.IS_PRIVATE.invoke(flags.get());
+ }
+
+ /** Gets the getter method of a given field element corresponding to a property. */
+ Optional<ExecutableElement> getPropertyGetter(VariableElement fieldElement) {
+ checkArgument(elementFieldGetterMethodMap.get().containsKey(fieldElement));
+ return elementFieldGetterMethodMap.get().get(fieldElement);
+ }
+
+ /** Returns true if any constructor of the defined a default parameter. */
+ public boolean containsConstructorWithDefaultParam() {
+ return containsConstructorWithDefaultParam.get();
}
/** Parse Kotlin class metadata from a given type element * */
static KotlinMetadata from(TypeElement typeElement) {
- MetadataVisitor visitor = new MetadataVisitor();
- metadataOf(typeElement).accept(visitor);
- return new KotlinMetadata(
- typeElement, visitor.classFlags, visitor.companionObjectName, visitor.classProperties);
+ return new KotlinMetadata(typeElement, metadataOf(typeElement));
}
private static KotlinClassMetadata.Class metadataOf(TypeElement typeElement) {
@@ -226,80 +380,25 @@
}
}
- private static final class MetadataVisitor extends KmClassVisitor {
-
- int classFlags;
- Optional<String> companionObjectName = Optional.empty();
- List<Property> classProperties = new ArrayList<>();
-
- @Override
- public void visit(int flags, String s) {
- this.classFlags = flags;
- }
-
- @Override
- public void visitCompanionObject(@Nullable String companionObjectName) {
- this.companionObjectName = Optional.ofNullable(companionObjectName);
- }
-
- @Override
- public KmPropertyVisitor visitProperty(
- int flags, String name, int getterFlags, int setterFlags) {
- return new KmPropertyVisitor() {
- Optional<String> fieldSignature;
- Optional<String> methodForAnnotationsSignature = Optional.empty();
-
- @Override
- public KmPropertyExtensionVisitor visitExtensions(KmExtensionType kmExtensionType) {
- if (!kmExtensionType.equals(JvmPropertyExtensionVisitor.TYPE)) {
- return null;
- }
-
- return new JvmPropertyExtensionVisitor() {
- @Override
- public void visit(
- int jvmFlags,
- @Nullable JvmFieldSignature jvmFieldSignature,
- @Nullable JvmMethodSignature getterSignature,
- @Nullable JvmMethodSignature setterSignature) {
- fieldSignature =
- Optional.ofNullable(jvmFieldSignature).map(JvmFieldSignature::asString);
- }
-
- @Override
- public void visitSyntheticMethodForAnnotations(
- @Nullable JvmMethodSignature methodSignature) {
- methodForAnnotationsSignature =
- Optional.ofNullable(methodSignature).map(JvmMethodSignature::asString);
- }
- };
- }
-
- @Override
- public void visitEnd() {
- classProperties.add(
- new Property(name, flags, fieldSignature, methodForAnnotationsSignature));
- }
- };
- }
- }
-
/* Data class representing Kotlin Property Metadata */
private static final class Property {
private final String name;
private final int flags;
private final Optional<String> fieldSignature;
+ private final Optional<String> getterSignature;
private final Optional<String> methodForAnnotationsSignature;
Property(
String name,
int flags,
Optional<String> fieldSignature,
+ Optional<String> getterSignature,
Optional<String> methodForAnnotationsSignature) {
this.name = name;
this.flags = flags;
this.fieldSignature = fieldSignature;
+ this.getterSignature = getterSignature;
this.methodForAnnotationsSignature = methodForAnnotationsSignature;
}
@@ -322,6 +421,10 @@
return fieldSignature;
}
+ Optional<String> getGetterMethodSignature() {
+ return getterSignature;
+ }
+
/** Returns JVM method descriptor of the synthetic method for property annotations. */
Optional<String> getMethodForAnnotationsSignature() {
return methodForAnnotationsSignature;
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java b/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
index 1d49254..13c7cf2 100644
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
+++ b/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
@@ -24,6 +24,7 @@
import com.google.common.collect.ImmutableList;
import dagger.internal.codegen.extension.DaggerCollectors;
import java.lang.annotation.Annotation;
+import java.util.Optional;
import javax.inject.Inject;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
@@ -114,6 +115,15 @@
return hasMetadata(typeElement) && metadataFactory.create(typeElement).isPrivate();
}
+ public Optional<ExecutableElement> getPropertyGetter(VariableElement fieldElement) {
+ return metadataFactory.create(fieldElement).getPropertyGetter(fieldElement);
+ }
+
+ public boolean containsConstructorWithDefaultParam(TypeElement typeElement) {
+ return hasMetadata(typeElement)
+ && metadataFactory.create(typeElement).containsConstructorWithDefaultParam();
+ }
+
/**
* Returns {@code true} if the <code>@JvmStatic</code> annotation is present in the given element.
*/
diff --git a/java/dagger/internal/codegen/langmodel/DaggerElements.java b/java/dagger/internal/codegen/langmodel/DaggerElements.java
index 63c5e1d..12cec31 100644
--- a/java/dagger/internal/codegen/langmodel/DaggerElements.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerElements.java
@@ -291,7 +291,9 @@
@Override
public String visitError(ErrorType errorType, Void v) {
- return visitUnknown(errorType, null);
+ // For descriptor generating purposes we don't need a fully modeled type since we are
+ // only interested in obtaining the class name in its "internal form".
+ return visitDeclared(errorType, v);
}
@Override
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt b/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt
index 95b1417..2356ced 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt
+++ b/javatests/artifacts/hilt-android/simpleKotlin/app/src/test/java/dagger/hilt/android/simpleKotlin/SimpleTest.kt
@@ -44,7 +44,7 @@
class SimpleTest {
@get:Rule val rule = HiltAndroidRule(this)
- @BindValue @JvmField val bindStr = "STRING_BINDING"
+ @BindValue val bindStr = "STRING_BINDING"
@Inject @JvmField var str: String? = null