From 7d7213f243bb70ccb17910a086f0c6d9ae46df56 Mon Sep 17 00:00:00 2001 From: WonderCsabo Date: Wed, 10 Sep 2014 19:13:06 +0200 Subject: [PATCH] Re-add Otto annotation handlers We copy all non-AA annotations when we override a method. This can help Otto, because it does not read annotations from parent classes. But if a method is only annotated with Otto annotation, so we do not override it, the annotation will not be read Otto and the methods will not be called. To help that case, we re-add Otto handlers, which override (and annotate) Otto annotated methods in the generated subclass. --- .../handler/AnnotationHandlers.java | 37 +++++++--- .../handler/ProduceHandler.java | 70 +++++++++++++++++++ .../handler/SubscribeHandler.java | 70 +++++++++++++++++++ .../helper/AnnotationHelper.java | 18 +++-- .../test15/otto/OttoActivityTest.java | 35 ++++++++++ .../androidannotations/test15/otto/Event.java | 20 ++++++ .../test15/otto/OttoActivity.java | 49 +++++++++++++ 7 files changed, 284 insertions(+), 15 deletions(-) create mode 100644 AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ProduceHandler.java create mode 100644 AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/SubscribeHandler.java create mode 100644 AndroidAnnotations/functional-test-1-5-tests/src/test/java/org/androidannotations/test15/otto/OttoActivityTest.java create mode 100644 AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/Event.java create mode 100644 AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/OttoActivity.java diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java index 4dbee01159..949f6e4e96 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java @@ -15,7 +15,22 @@ */ package org.androidannotations.handler; -import org.androidannotations.handler.rest.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.processing.ProcessingEnvironment; + +import org.androidannotations.handler.rest.DeleteHandler; +import org.androidannotations.handler.rest.GetHandler; +import org.androidannotations.handler.rest.HeadHandler; +import org.androidannotations.handler.rest.OptionsHandler; +import org.androidannotations.handler.rest.PostHandler; +import org.androidannotations.handler.rest.PutHandler; +import org.androidannotations.handler.rest.RestHandler; +import org.androidannotations.handler.rest.RestServiceHandler; import org.androidannotations.helper.AndroidManifest; import org.androidannotations.helper.OptionsHelper; import org.androidannotations.holder.GeneratedClassHolder; @@ -25,9 +40,6 @@ import org.androidannotations.process.ProcessHolder; import org.androidannotations.rclass.IRClass; -import javax.annotation.processing.ProcessingEnvironment; -import java.util.*; - public class AnnotationHandlers { private List> annotationHandlers = new ArrayList>(); @@ -99,6 +111,8 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) { add(new SeekBarTouchStartHandler(processingEnvironment)); add(new SeekBarTouchStopHandler(processingEnvironment)); add(new ServiceActionHandler(processingEnvironment)); + add(new ProduceHandler(processingEnvironment)); + add(new SubscribeHandler(processingEnvironment)); add(new InstanceStateHandler(processingEnvironment)); add(new HttpsClientHandler(processingEnvironment)); add(new OnActivityResultHandler(processingEnvironment)); @@ -115,14 +129,19 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) { if (optionsHelper.shouldLogTrace()) { add(new TraceHandler(processingEnvironment)); } - /* UIThreadHandler and BackgroundHandler must be after TraceHandler and IgnoredWhenDetached */ + /* + * UIThreadHandler and BackgroundHandler must be after TraceHandler and + * IgnoredWhenDetached + */ add(new UiThreadHandler(processingEnvironment)); add(new BackgroundHandler(processingEnvironment)); - /* SupposeUiThreadHandler and SupposeBackgroundHandler must be - after all handlers that modifies generated method body */ - add(new SupposeUiThreadHandler(processingEnvironment)); - add(new SupposeBackgroundHandler(processingEnvironment)); + /* + * SupposeUiThreadHandler and SupposeBackgroundHandler must be after all + * handlers that modifies generated method body + */ + add(new SupposeUiThreadHandler(processingEnvironment)); + add(new SupposeBackgroundHandler(processingEnvironment)); } private void add(AnnotationHandler annotationHandler) { diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ProduceHandler.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ProduceHandler.java new file mode 100644 index 0000000000..9330b04a66 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/ProduceHandler.java @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2010-2014 eBusiness Information, Excilys Group + * + * 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 org.androidannotations.handler; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; + +import org.androidannotations.helper.APTCodeModelHelper; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.helper.TargetAnnotationHelper; +import org.androidannotations.holder.EComponentHolder; +import org.androidannotations.model.AnnotationElements; +import org.androidannotations.process.IsValid; + +public class ProduceHandler extends BaseAnnotationHandler { + + private final TargetAnnotationHelper annotationHelper; + private final APTCodeModelHelper codeModelHelper = new APTCodeModelHelper(); + + public ProduceHandler(ProcessingEnvironment processingEnvironment) { + super(CanonicalNameConstants.PRODUCE, processingEnvironment); + annotationHelper = new TargetAnnotationHelper(processingEnv, getTarget()); + } + + @Override + public void validate(Element element, AnnotationElements validatedElements, IsValid valid) { + if (!annotationHelper.enclosingElementHasEnhancedComponentAnnotation(element)) { + valid.invalidate(); + return; + } + + ExecutableElement executableElement = (ExecutableElement) element; + + /* + * We check that twice to skip invalid annotated elements + */ + validatorHelper.enclosingElementHasEnhancedComponentAnnotation(executableElement, validatedElements, valid); + + validatorHelper.returnTypeIsNotVoid(executableElement, valid); + + validatorHelper.isPublic(element, valid); + + validatorHelper.doesntThrowException(executableElement, valid); + + validatorHelper.isNotFinal(element, valid); + + validatorHelper.param.zeroParameter(executableElement, valid); + } + + @Override + public void process(Element element, EComponentHolder holder) throws Exception { + ExecutableElement executableElement = (ExecutableElement) element; + + codeModelHelper.overrideAnnotatedMethod(executableElement, holder); + } +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/SubscribeHandler.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/SubscribeHandler.java new file mode 100644 index 0000000000..08657f4c22 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/SubscribeHandler.java @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2010-2014 eBusiness Information, Excilys Group + * + * 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 org.androidannotations.handler; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; + +import org.androidannotations.helper.APTCodeModelHelper; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.helper.TargetAnnotationHelper; +import org.androidannotations.holder.EComponentHolder; +import org.androidannotations.model.AnnotationElements; +import org.androidannotations.process.IsValid; + +public class SubscribeHandler extends BaseAnnotationHandler { + + private final TargetAnnotationHelper annotationHelper; + private final APTCodeModelHelper codeModelHelper = new APTCodeModelHelper(); + + public SubscribeHandler(ProcessingEnvironment processingEnvironment) { + super(CanonicalNameConstants.SUBSCRIBE, processingEnvironment); + annotationHelper = new TargetAnnotationHelper(processingEnv, getTarget()); + } + + @Override + public void validate(Element element, AnnotationElements validatedElements, IsValid valid) { + if (!annotationHelper.enclosingElementHasEnhancedComponentAnnotation(element)) { + valid.invalidate(); + return; + } + + ExecutableElement executableElement = (ExecutableElement) element; + + /* + * We check that twice to skip invalid annotated elements + */ + validatorHelper.enclosingElementHasEnhancedComponentAnnotation(executableElement, validatedElements, valid); + + validatorHelper.returnTypeIsVoid(executableElement, valid); + + validatorHelper.isPublic(element, valid); + + validatorHelper.doesntThrowException(executableElement, valid); + + validatorHelper.isNotFinal(element, valid); + + validatorHelper.param.hasExactlyOneParameter(executableElement, valid); + } + + @Override + public void process(Element element, EComponentHolder holder) throws Exception { + ExecutableElement executableElement = (ExecutableElement) element; + + codeModelHelper.overrideAnnotatedMethod(executableElement, holder); + } +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java index 694d108270..84beb8ca2b 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java @@ -15,6 +15,9 @@ */ package org.androidannotations.helper; +import static org.androidannotations.helper.ModelConstants.GENERATION_SUFFIX; +import static org.androidannotations.helper.ModelConstants.VALID_ENHANCED_COMPONENT_ANNOTATIONS; + import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -48,8 +51,6 @@ import com.sun.codemodel.JFieldRef; -import static org.androidannotations.helper.ModelConstants.GENERATION_SUFFIX; - public class AnnotationHelper { public static final String DEFAULT_FIELD_NAME_VALUE = "value"; @@ -91,9 +92,9 @@ public String generatedClassQualifiedNameFromQualifiedName(String qualifiedName) TypeElement type = typeElementFromQualifiedName(qualifiedName); if (type.getNestingKind() == NestingKind.MEMBER) { String parentGeneratedClass = generatedClassQualifiedNameFromQualifiedName(type.getEnclosingElement().asType().toString()); - return parentGeneratedClass+"."+type.getSimpleName().toString()+GENERATION_SUFFIX; + return parentGeneratedClass + "." + type.getSimpleName().toString() + GENERATION_SUFFIX; } else { - return qualifiedName+GENERATION_SUFFIX; + return qualifiedName + GENERATION_SUFFIX; } } @@ -173,7 +174,7 @@ public Types getTypeUtils() { /** * Returns a list of {@link JFieldRef} linking to the R class, based on the * given annotation - * + * * @see #extractAnnotationResources(Element, String, IRInnerClass, boolean) */ public List extractAnnotationFieldRefs(ProcessHolder holder, Element element, String annotationName, IRInnerClass rInnerClass, boolean useElementName) { @@ -195,7 +196,7 @@ public List extractAnnotationFieldRefs(ProcessHolder holder, Element * set using the value() parameter of the annotation (as int or int[]), the * resName() parameter of the annotation (as String or String[]), the * element name. - * + * * @param element * the annotated element * @param annotationName @@ -427,6 +428,11 @@ public boolean hasOneOfClassAnnotations(Element element, Class> validAnnotations) { for (Class validAnnotation : validAnnotations) { if (element.getAnnotation(validAnnotation) != null) { diff --git a/AndroidAnnotations/functional-test-1-5-tests/src/test/java/org/androidannotations/test15/otto/OttoActivityTest.java b/AndroidAnnotations/functional-test-1-5-tests/src/test/java/org/androidannotations/test15/otto/OttoActivityTest.java new file mode 100644 index 0000000000..ebf6b73a7d --- /dev/null +++ b/AndroidAnnotations/functional-test-1-5-tests/src/test/java/org/androidannotations/test15/otto/OttoActivityTest.java @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2010-2014 eBusiness Information, Excilys Group + * + * 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 org.androidannotations.test15.otto; + +import static org.fest.assertions.Assertions.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class OttoActivityTest { + + @Test + public void testOttoMethodsCalled() { + OttoActivity activity = Robolectric.setupActivity(OttoActivity_.class); + + assertThat(activity.lastEvent).isNotNull(); + } + +} diff --git a/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/Event.java b/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/Event.java new file mode 100644 index 0000000000..34a76f6431 --- /dev/null +++ b/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/Event.java @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2010-2014 eBusiness Information, Excilys Group + * + * 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 org.androidannotations.test15.otto; + +public class Event { + +} diff --git a/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/OttoActivity.java b/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/OttoActivity.java new file mode 100644 index 0000000000..2b5634248c --- /dev/null +++ b/AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/otto/OttoActivity.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2010-2014 eBusiness Information, Excilys Group + * + * 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 org.androidannotations.test15.otto; + +import org.androidannotations.annotations.EActivity; + +import android.app.Activity; +import android.os.Bundle; + +import com.squareup.otto.Bus; +import com.squareup.otto.Produce; +import com.squareup.otto.Subscribe; + +@EActivity +public class OttoActivity extends Activity { + + Event lastEvent; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bus bus = new Bus(); + bus.register(this); + } + + @Subscribe + public void onEvent(Event event) { + lastEvent = event; + } + + @Produce + public Event produceEvent() { + return new Event(); + } +}