Repository navigation
Cannot traverse supertypes when extending "_" class #278
Description
Activity
Great investigations, this is closely associated with #258
@naixx Thanks for the reference, somehow I had missed it. The root cause is indeed the same.
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
BaseActivitybut 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).
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
JCodeModeldown to theisSubtypemethod. Furthermore, it is error-prone if there are two classes of the same name (in the above example this would mean twoBaseActivityclasses 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...
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.
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...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,@EViewand@EViewGroup. Everything else should work.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?
- added a commit that references this issue
on Aug 10, 2012 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.myViewwill be injected usingfindViewById(), however, theR.layout.maindefined in@EActivityonAwon't be taken into account byB_.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 :-)
Thank you. Please do not hesitate to give any feedback. The tests are passing, but real life testing cannot do any harm :)
At last succeeded to try this change - awesome! Testing further
@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.
As it is abstract, it shouldn't be generated and instantiated.
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:
Where
BaseActivity_has been generated by AA fromBaseActivity.The Javadoc of
AnnotationHelper.isSubtypementions 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.usesSherlockwhere determining the correct supertype of a given activity is vital in generating the correct source. The attempt ofAnnotationHelper.isSubtypeis unfortunately not good enough for the specific case ofSherlockHelper.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 fromBaseActivity.