diff --git a/java/dagger/internal/codegen/FactoryGenerator.java b/java/dagger/internal/codegen/FactoryGenerator.java index 95024f4d5af..da6784fdabd 100644 --- a/java/dagger/internal/codegen/FactoryGenerator.java +++ b/java/dagger/internal/codegen/FactoryGenerator.java @@ -27,6 +27,7 @@ import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION; import static dagger.internal.codegen.ContributionBinding.Kind.PROVISION; import static dagger.internal.codegen.ErrorMessages.CANNOT_RETURN_NULL_FROM_NON_NULLABLE_PROVIDES_METHOD; +import static dagger.internal.codegen.GwtCompatibility.gwtIncompatibleAnnotation; import static dagger.internal.codegen.Proxies.createProxy; import static dagger.internal.codegen.Proxies.shouldGenerateProxy; import static dagger.internal.codegen.SourceFiles.bindingTypeElementTypeVariableNames; @@ -276,6 +277,8 @@ Optional write(ClassName generatedTypeName, ProvisionBinding b proxyMethodFor(binding).ifPresent(factoryBuilder::addMethod); + gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation); + return Optional.of(factoryBuilder); } diff --git a/java/dagger/internal/codegen/GwtCompatibility.java b/java/dagger/internal/codegen/GwtCompatibility.java new file mode 100644 index 00000000000..34d8f6d69fc --- /dev/null +++ b/java/dagger/internal/codegen/GwtCompatibility.java @@ -0,0 +1,56 @@ +/* + * 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.common.base.Preconditions.checkArgument; + +import com.squareup.javapoet.AnnotationSpec; +import java.util.Optional; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.Name; + +final class GwtCompatibility { + + /** + * Returns a {@code @GwtIncompatible} annotation that is applied to {@code binding}'s {@link + * Binding#bindingElement()} or any enclosing type. + */ + static Optional gwtIncompatibleAnnotation(Binding binding) { + checkArgument(binding.bindingElement().isPresent()); + Element element = binding.bindingElement().get(); + while (element != null) { + Optional gwtIncompatible = + element + .getAnnotationMirrors() + .stream() + .filter(annotation -> isGwtIncompatible(annotation)) + .map(AnnotationSpec::get) + .findFirst(); + if (gwtIncompatible.isPresent()) { + return gwtIncompatible; + } + element = element.getEnclosingElement(); + } + return Optional.empty(); + } + + private static boolean isGwtIncompatible(AnnotationMirror annotation) { + Name simpleName = annotation.getAnnotationType().asElement().getSimpleName(); + return simpleName.contentEquals("GwtIncompatible"); + } +} diff --git a/java/dagger/internal/codegen/MembersInjectorGenerator.java b/java/dagger/internal/codegen/MembersInjectorGenerator.java index 3cf63676421..eeca10431e4 100644 --- a/java/dagger/internal/codegen/MembersInjectorGenerator.java +++ b/java/dagger/internal/codegen/MembersInjectorGenerator.java @@ -29,6 +29,7 @@ import static dagger.internal.codegen.AnnotationSpecs.suppressWarnings; import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock; 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.frameworkTypeUsageStatement; import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies; @@ -219,6 +220,8 @@ Optional write(ClassName generatedTypeName, MembersInjectionBi injectorTypeBuilder.addMethod(injectMembersBuilder.build()); injectMethodsForSubclasses.forEach(injectorTypeBuilder::addMethod); + gwtIncompatibleAnnotation(binding).ifPresent(injectorTypeBuilder::addAnnotation); + return Optional.of(injectorTypeBuilder); } diff --git a/java/dagger/internal/codegen/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/ProducerFactoryGenerator.java index 7a2c2c58675..44d656b2cd7 100644 --- a/java/dagger/internal/codegen/ProducerFactoryGenerator.java +++ b/java/dagger/internal/codegen/ProducerFactoryGenerator.java @@ -23,6 +23,7 @@ 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.GwtCompatibility.gwtIncompatibleAnnotation; import static dagger.internal.codegen.SourceFiles.frameworkTypeUsageStatement; import static dagger.internal.codegen.SourceFiles.generateBindingFieldsForDependencies; import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding; @@ -214,6 +215,8 @@ Optional write(ClassName generatedTypeName, ProductionBinding factoryBuilder.addMethod(applyMethodBuilder.build()); factoryBuilder.addMethod(executeMethodBuilder.build()); + gwtIncompatibleAnnotation(binding).ifPresent(factoryBuilder::addAnnotation); + // TODO(gak): write a sensible toString return Optional.of(factoryBuilder); } diff --git a/javatests/dagger/functional/gwt/GwtIncompatibles.java b/javatests/dagger/functional/gwt/GwtIncompatibles.java new file mode 100644 index 00000000000..d65f1169b9a --- /dev/null +++ b/javatests/dagger/functional/gwt/GwtIncompatibles.java @@ -0,0 +1,72 @@ +/* + * 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.functional.gwt; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import dagger.Module; +import dagger.Provides; +import java.lang.annotation.Retention; +import javax.inject.Inject; + +interface GwtIncompatibles { + @Retention(RUNTIME) + @interface GwtIncompatible {} + + @GwtIncompatible + class OnClass { + @Inject + OnClass() {} + } + + class OnConstructor { + @Inject + @GwtIncompatible + OnConstructor() {} + } + + @GwtIncompatible + class OuterClass { + static class OnOuterClass { + @Inject + OnOuterClass() {} + } + } + + @GwtIncompatible + class MembersInjectedType { + @Inject String string; + } + + @GwtIncompatible + @Module + class OnModule { + @Provides + static String onModule() { + return "on module"; + } + } + + @Module + class OnMethod { + @GwtIncompatible + @Provides + static String onMethod() { + return "on method"; + } + } +} diff --git a/javatests/dagger/functional/gwt/GwtIncompatiblesTest.java b/javatests/dagger/functional/gwt/GwtIncompatiblesTest.java new file mode 100644 index 00000000000..c038e1dc1f5 --- /dev/null +++ b/javatests/dagger/functional/gwt/GwtIncompatiblesTest.java @@ -0,0 +1,45 @@ +/* + * 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.functional.gwt; + +import dagger.functional.gwt.GwtIncompatibles.GwtIncompatible; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@code @GwtIncompatible} bindings. */ +@RunWith(JUnit4.class) +public class GwtIncompatiblesTest { + @Test + public void testIncompatible() { + assertGwtIncompatible(GwtIncompatibles_OnClass_Factory.class); + assertGwtIncompatible(GwtIncompatibles_OnConstructor_Factory.class); + assertGwtIncompatible(GwtIncompatibles_OuterClass_OnOuterClass_Factory.class); + + assertGwtIncompatible(GwtIncompatibles_MembersInjectedType_MembersInjector.class); + + assertGwtIncompatible(GwtIncompatibles_OnModule_OnModuleFactory.class); + assertGwtIncompatible(GwtIncompatibles_OnMethod_OnMethodFactory.class); + } + + private void assertGwtIncompatible(Class clazz) { + boolean gwtIncompatible = clazz.getAnnotation(GwtIncompatible.class) != null; + if (!gwtIncompatible) { + throw new AssertionError(clazz.getCanonicalName() + " is not @GwtIncompatible"); + } + } +} diff --git a/javatests/dagger/functional/producers/gwt/GwtIncompatibles.java b/javatests/dagger/functional/producers/gwt/GwtIncompatibles.java new file mode 100644 index 00000000000..75efd966068 --- /dev/null +++ b/javatests/dagger/functional/producers/gwt/GwtIncompatibles.java @@ -0,0 +1,46 @@ +/* + * 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.functional.producers.gwt; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import dagger.producers.ProducerModule; +import dagger.producers.Produces; +import java.lang.annotation.Retention; + +interface GwtIncompatibles { + @Retention(RUNTIME) + @interface GwtIncompatible {} + + @GwtIncompatible + @ProducerModule + class OnModule { + @Produces + static String onModule() { + return "on module"; + } + } + + @ProducerModule + class OnMethod { + @GwtIncompatible + @Produces + static String onMethod() { + return "on method"; + } + } +} diff --git a/javatests/dagger/functional/producers/gwt/GwtIncompatiblesTest.java b/javatests/dagger/functional/producers/gwt/GwtIncompatiblesTest.java new file mode 100644 index 00000000000..0ca3dc41758 --- /dev/null +++ b/javatests/dagger/functional/producers/gwt/GwtIncompatiblesTest.java @@ -0,0 +1,39 @@ +/* + * 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.functional.producers.gwt; + +import dagger.functional.producers.gwt.GwtIncompatibles.GwtIncompatible; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@code @GwtIncompatible} bindings. */ +@RunWith(JUnit4.class) +public class GwtIncompatiblesTest { + @Test + public void testIncompatible() { + assertGwtIncompatible(GwtIncompatibles_OnModule_OnModuleFactory.class); + assertGwtIncompatible(GwtIncompatibles_OnMethod_OnMethodFactory.class); + } + + private void assertGwtIncompatible(Class clazz) { + boolean gwtIncompatible = clazz.getAnnotation(GwtIncompatible.class) != null; + if (!gwtIncompatible) { + throw new AssertionError(clazz.getCanonicalName() + " is not @GwtIncompatible"); + } + } +}