Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Cannot traverse supertypes when extending "_" class  #278

Description

@vahidg

In an Android project, when an activity extends an AA-generated "_" class, AA cannot correctly traverse the complete supertypes line, causing problems in certain cases.

Example:

@EActivity(R.layout.hello_world)
public class HelloWorldActivity extends BaseActivity_ 

Where BaseActivity_ has been generated by AA from BaseActivity.

The Javadoc of AnnotationHelper.isSubtype mentions this issue. Basically the problem is that the generated "_" sources don't exist yet at the time we want to traverse the supertypes, cutting off the traversal.

This limitation is an issue for SherlockHelper.usesSherlock where determining the correct supertype of a given activity is vital in generating the correct source. The attempt of AnnotationHelper.isSubtype is unfortunately not good enough for the specific case of SherlockHelper.usesSherlock, where a definite supertype must be determined.

The solutions to this problem are either generating the sources in rounds to make sure that needed generated classes are existent (from aforementioned Javadoc), or somehow skipping BaseActivity_ in the example above to continue the traversal from BaseActivity.

Activity

  1. naixx commented on Aug 2, 2012

    @naixx
    Contributor

    Great investigations, this is closely associated with #258

  2. vahidg commented on Aug 2, 2012

    @vahidg
    Author

    @naixx Thanks for the reference, somehow I had missed it. The root cause is indeed the same.

  3. pyricau commented on Aug 3, 2012

    @pyricau
    Contributor

    Nice research :) .

    somehow skipping BaseActivity_ in the example above to continue the traversal from BaseActivity.

    I'd love to do that, and tried already. The problem is that in one of the compiler (eclipse ? javac ? can't remember), superclassTypeMirror is an ErrorType that knows the simple name of the missing element, but not it's qualified name. That's stupid, and probably a compiler bug (because, the package should obviously be know, its given in the source), but this screws things quite a lot. Because then, we know we're looking for BaseActivity but we don't know in which package it is located.

    It's been a while since I've investigated these, and it's good to see new eyes looking at this. Any other suggestion / idea / contribution welcome :) .

    The solutions to this problem are either generating the sources in rounds to make sure that needed generated classes are existent (from aforementioned Javadoc)

    Yep. I didn't mention there that I finally tried the "round" stuff, but in fact rounds are intended to process / compile files created by another round. There seems to be no way to "handle later" a file that's been compiled in a specific round, even if it has errors.

    It still happens though, because as you know, building with Ant usually starts by issuing errors about missing types, and then everything gets compiled right.

    A more complex implementation would be to "not" generate a subclass on the abstract class, and just do the validation part. Then, when processing a class, we'd do some check on all its mother classes, to see if we can find more annotations, and we'd add them as if they were standard annotations processed in this round.

    I'm not sure if it would work though, because some informations might be lost after compilation. First thing we'd need to do is to change the annotation source level (some of them already are runtime).

  4. vahidg commented on Aug 7, 2012

    @vahidg
    Author

    Hi @pyricau,

    I'd love to do that, and tried already. The problem is that in one of the compiler (eclipse ? javac ? can't remember), superclassTypeMirror is an ErrorType that knows the simple name of the missing element, but not it's qualified name. That's stupid, and probably a compiler bug (because, the package should obviously be know, its given in the source), but this screws things quite a lot. Because then, we know we're looking for BaseActivity but we don't know in which package it is located.

    It's been a while since I've investigated these, and it's good to see new eyes looking at this. Any other suggestion / idea / contribution welcome :) .

    These are indeed the same set of challenges that I came across when trying to find a solution. Since we don't have the qualified name, what if we search for the class by iterating through the available packages? I've tried this out here, and it seems to work, but I really haven't tested it well yet, just that our project compiles. I admit that it is not the cleanest way to do it since it passes the JCodeModel down to the isSubtype method. Furthermore, it is error-prone if there are two classes of the same name (in the above example this would mean two BaseActivity classes in different packages). So I haven't thought of making it a pull request yet.

    Yep. I didn't mention there that I finally tried the "round" stuff, but in fact rounds are intended to process / compile files created by another round. There seems to be no way to "handle later" a file that's been compiled in a specific round, even if it has errors.

    It still happens though, because as you know, building with Ant usually starts by issuing errors about missing types, and then everything gets compiled right.

    Again, I also had misunderstood the 'round' concept :-) The "handle later" idea you mention sounds like it should be an ideal fix for this problem. I'll try to have a look as well.

    A more complex implementation would be to "not" generate a subclass on the abstract class, and just do the validation part. Then, when processing a class, we'd do some check on all its mother classes, to see if we can find more annotations, and we'd add them as if they were standard annotations processed in this round.

    I'm not sure if it would work though, because some informations might be lost after compilation. First thing we'd need to do is to change the annotation source level (some of them already are runtime).

    Sounds more complex indeed...

  5. pyricau commented on Aug 10, 2012

    @pyricau
    Contributor

    Sounds more complex indeed...

    Yeah, but definitely more compelling. Actually, I've been spending a few hours on this, doing some checks with the Eclipse Debugger, and the result is quite promising.

    Let's try and see if it works. This requires refactoring big chunks of code, but it could really be a game changer.

  6. pyricau commented on Aug 10, 2012

    @pyricau
    Contributor

    Yeeah it's definitely starting to look good. Had to change / debug a lot of things, but we are now taking into accounts annotations from the full class hierarchy. No need to extend a generated class such as MyAbstractActivity_ any more. And this works for all types of classes, @EService, @EFragment, @EBean...

  7. pyricau commented on Aug 10, 2012

    @pyricau
    Contributor

    So basically, we are going to inherit all annotations from the parents. The only thing that won't work (at least for now) is inheriting the layout attribute from @EActivity , @EFragment , @EView and @EViewGroup. Everything else should work.

  8. vahidg commented on Aug 10, 2012

    @vahidg
    Author

    That sounds really good! We'll be the first to test :-)

    he only thing that won't work (at least for now) is inheriting the layout attribute from @EActivity , @efragment , @eview and @eviewgroup.

    I don't completely understand.. Can you give an example?

  9. pyricau commented on Aug 10, 2012

    @pyricau
    Contributor

    If you write :

    @EActivity(R.layout.main)
    public abstract class A extends Activity {
    
      @ViewById 
      View myView;
    
    }
    
    @EActivity
    public class B extends A {
    
    }

    Then a class B_ will be generated. myView will be injected using findViewById(), however, the R.layout.main defined in @EActivity on A won't be taken into account by B_.

  10. vahidg commented on Aug 13, 2012

    @vahidg
    Author

    OK.

    This is a great improvement, thanks for the effort. We're going to insert back the annotations (mostly menu related) into our abstract base activity. Will have a look at the commit when I have more time and try to understand what you've done :-)

  11. pyricau commented on Aug 13, 2012

    @pyricau
    Contributor

    Thank you. Please do not hesitate to give any feedback. The tests are passing, but real life testing cannot do any harm :)

  12. naixx commented on Aug 20, 2012

    @naixx
    Contributor

    At last succeeded to try this change - awesome! Testing further

  13. vahidg commented on Sep 27, 2012

    @vahidg
    Author

    @pyricau The only problem I see is that for abstract base activities, the generated underscore activity is final now (as it was in earlier releases), meaning if you have abstract methods in the base activity, the generated underscore class will a compile error because it is not implementing that abstract method.

  14. naixx commented on Sep 27, 2012

    @naixx
    Contributor

    As it is abstract, it shouldn't be generated and instantiated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions