Bug 156352 - NPE when accessing annotations from ITypeBinding
Summary: NPE when accessing annotations from ITypeBinding
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 M4   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 151364 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-09-06 09:01 EDT by Martin Aeschlimann CLA
Modified: 2006-12-12 13:15 EST (History)
3 users (show)

See Also:


Attachments
test case (3.50 KB, text/plain)
2006-09-06 09:39 EDT, Martin Aeschlimann CLA
no flags Details
New test case (6.42 KB, text/plain)
2006-09-06 11:39 EDT, Olivier Thomann CLA
no flags Details
simplified test case (3.11 KB, text/plain)
2006-09-06 11:42 EDT, Martin Aeschlimann CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Aeschlimann CLA 2006-09-06 09:01:50 EDT
The attached snippet fails with a NPE when it tries to access the annotations of a super class.

java.lang.NullPointerException
	at org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding.getAnnotationTagBits(SourceTypeBinding.java:677)
	at org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding.retrieveAnnotationHolder(SourceTypeBinding.java:1417)
	at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.retrieveAnnotations(ReferenceBinding.java:1082)
	at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.getAnnotations(ReferenceBinding.java:595)
	at org.eclipse.jdt.core.dom.TypeBinding.getAnnotations(TypeBinding.java:92)
	at org.eclipse.jdt.junit.tests.JUnit4TestFinderTest.testNPE(JUnit4TestFinderTest.java:323)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Comment 1 Martin Aeschlimann CLA 2006-09-06 09:39:58 EDT
Created attachment 49480 [details]
test case
Comment 2 Olivier Thomann CLA 2006-09-06 11:37:07 EDT
The annotations from the superclass are not resolved before the scopes are nullified.
The call getAnnotations() is trying to resolve them, but there is no more scopes to do it. The call createBindings(...) doesn't resolve the superclass of the given bindings.
createAST(...) on the compilation unit that contaisn Test3 correctly initializes the annotations of the superclass and I could print:
p.Test3 has 0 annotation(s).
p.Test2 has 2 annotation(s).
java.lang.Object has 0 annotation(s).

So the problem comes from the createBindings(...) call.
Comment 3 Olivier Thomann CLA 2006-09-06 11:39:53 EDT
Created attachment 49503 [details]
New test case

This test case is using one call to createBindings(...) and one call to createAST(...).
Comment 4 Martin Aeschlimann CLA 2006-09-06 11:42:53 EDT
Created attachment 49504 [details]
simplified test case

Simplified: no JUnit container references needed and compliance correctly set to 1.5
Comment 5 Martin Aeschlimann CLA 2006-09-08 09:07:30 EDT
Is it possible up the priority of this bug? The workaround only works for types in compilation units, but not in a classfile with no source.
Comment 6 Olivier Thomann CLA 2006-11-13 15:34:00 EST
This is a direct consequence of fix for bug 114935.
If commenting out line 677 to 686 in org.eclipse.jdt.core.dom.CompilationUnitResolver, the test case doesn't fail anymore.
In this case the superclass source unit is requested in order to connect the superclass, but since it is not part of the requestedSource, the superclass source unit added in the unitToProcess list is not resolved and therefore it is not possible to get the annotation bindings once the units have been cleaned up.

We should investigate two fixes:
1) prevent the call from failing if annotations are not resolved => add a null check
2) resolve units required to connect the superclass.

I added regression tests in org.eclipse.jdt.core.tests.dom.ASTConverter15Test#test0230/0231. 0230 is disabled since it fails.
Comment 7 Olivier Thomann CLA 2006-11-13 15:57:52 EST
When we use createAST(...), the scopes of the requested types are not cleaned up and then the call to get the annotations work fine.
When we use createBindings(...), all scopes are cleaned up and therefore it is not possible to do any further resolution. This has been done to fix bug 114935.

Jérôme, since you fixed bug 114935, you might have an idea how to fix this one as well. We might want to be able to resolve bindings inside the hierarchy. Otherwise we end up with incomplete bindings.
Comment 8 Jerome Lanneluc CLA 2006-11-14 07:50:22 EST
It looks like we want to force the resolution of annotations of types and methods that are in the queue before the cleanup. 

That sounds like a lot of work. Martin, since you didn't request the resolution of the super type, would returning an empty list in this case  be good enough ?
Comment 9 Martin Aeschlimann CLA 2006-11-14 08:44:42 EST
In our use case we indeed need the super types and all their member's annotations.
But even if we didn't, it would seem like a bug to get incomplete bindings. It shouldn't make a difference how a binding was requested (createAST or createBinding), it should always look the same.
Comment 10 Olivier Thomann CLA 2006-11-14 11:26:31 EST
(In reply to comment #8)
> It looks like we want to force the resolution of annotations of types and
> methods that are in the queue before the cleanup. 
We don't need to resolve if not requested.
 
> That sounds like a lot of work. Martin, since you didn't request the resolution
> of the super type, would returning an empty list in this case  be good enough ?
I don't think an empty list would help.

We need a consistent story between createBindings(...) and createAST(...). createAST(...) doesn't clean up units in the queue. We could do the same thing for createBindings(...).
However this breaks the regression test added for bug 114935. So we might want to revisit it.

I don't see why in org.eclipse.jdt.core.tests.dom.BatchASTCreationTests#test070, Y should not be resolved. If the user explicitly requests bindings for Y, I expect them to be available. If not, this would need to be described in the createBindings(...) API as well as createAST(...) that is doing too much work right now.

Jérôme, any comment?
Comment 11 Jerome Lanneluc CLA 2006-11-14 11:59:07 EST
(In reply to comment #10)
> (In reply to comment #8)
> > That sounds like a lot of work. Martin, since you didn't request the resolution
> > of the super type, would returning an empty list in this case  be good enough ?
> I don't think an empty list would help.
We already return an empty list for fields and members if their declaring type has not been resolved.
 
> We need a consistent story between createBindings(...) and createAST(...).
> createAST(...) doesn't clean up units in the queue. We could do the same thing
> for createBindings(...).
If we eagerly created all bindings, this would be a performance regression (see bug bug 114935).

> However this breaks the regression test added for bug 114935. So we might want
> to revisit it.
This test ensures that we don't have a performance regression.

> I don't see why in
> org.eclipse.jdt.core.tests.dom.BatchASTCreationTests#test070, Y should not be
> resolved. If the user explicitly requests bindings for Y, I expect them to be
> available. If not, this would need to be described in the createBindings(...)
> API as well as createAST(...) that is doing too much work right now.
Right. In the case of BatchASTCreationTests#test070, the user doesn't ask Y to be resolved.
 

Comment 12 Olivier Thomann CLA 2006-11-14 12:10:35 EST
We definitely need consistency between the two APIs. So if we continue to clean up the queued units as we do in createBindings(...) we should also clean up queued units in createAST(...).
Martin, any comment? Would this break existing code on your side?
Comment 13 Martin Aeschlimann CLA 2006-11-14 12:25:57 EST
We expect all bindings to be complete. Changing this will definitly break us.

Or we have to introduce new flags on createBinding to give you hints how much should be resolved.

It's not obvious to me how bug 114935 and ASTParser.createBindings are related. For the ASTRequestor it makes perfectly sense to stop reporting ASTs anymore when all user requested ASTs and bindings have been processed, but ASTParser.createBindings is a simple function, no ASTRequestor involved. 
Comment 14 Jerome Lanneluc CLA 2006-11-14 12:44:00 EST
(In reply to comment #13)
> We expect all bindings to be complete. Changing this will definitly break us.
As said before, you are already broken for fields and methods.

> Or we have to introduce new flags on createBinding to give you hints how much
> should be resolved.
This problem should be resolved when we reify the AST queue. In this case, the lookup environment will be kept in memory and things will be lazily resolved.

> It's not obvious to me how bug 114935 and ASTParser.createBindings are related.
> For the ASTRequestor it makes perfectly sense to stop reporting ASTs anymore
> when all user requested ASTs and bindings have been processed, but
> ASTParser.createBindings is a simple function, no ASTRequestor involved. 
The problem in bug 114935 was not to stop reporting ASTs, but to stop resolving ASTs that were not requested (same as stop resolving binding keys that were not requested).


Comment 15 Martin Aeschlimann CLA 2006-11-14 12:54:09 EST
Can you elaborate which fields and methods we're not getting? We need a clear understanding of this, so we know why refactorings or other stuff fails.
Comment 16 Jerome Lanneluc CLA 2006-11-15 05:21:21 EST
(In reply to comment #15)
> Can you elaborate which fields and methods we're not getting? We need a clear
> understanding of this, so we know why refactorings or other stuff fails.
Let's say you have class A with field 'foo' and class B that extends A. If you call createBindings on B only, then you navigate to A binding (using getSuperClass() on B binding), then ask A binding for its fields using getDeclaredFields(), this will return an empty list since A was not resolved.
Comment 17 Martin Aeschlimann CLA 2006-11-15 06:39:20 EST
I verified that in the AST view and you're right. But I'm afraid this is a bug, we're really expecting bindings to be complete and to look the same, regardless if achieved from createAST or createBinding. 

Performance is of course an issue, but correctness is more important. If thing are left away, it needs to be decided/controled by the user of the API.

What do you mean by 'not requested'. Assuming I want to know all fields from a type's superclasses, do you think I should pass in the fields as IFields to createBinding? How would we get all these IFields? Building a supertype hierarchy? That really wouldn't make sense.
Comment 18 Markus Keller CLA 2006-11-15 08:20:56 EST
I think the performance improvement of bug 114935 should be made explicit by allowing the API client to tell whether bindings should be completely resolved after the last accept*(..) callback. This could either be an additional parameter for ASTParser#createASTs(..), or another callback method in ASTRequestor, e.g.
    public boolean stopResolvingBindings() { return false; }

ASTParser#createBindings(..) has to return complete bindings.
Comment 19 Jerome Lanneluc CLA 2006-11-15 09:14:00 EST
(In reply to comment #17)
> What do you mean by 'not requested'. 
I meant that it is not part of the set of ICompilationUnits and IClassFiles that are the parents of the IJavaElements passed to createBindings(...).

> Assuming I want to know all fields from a
> type's superclasses, do you think I should pass in the fields as IFields to
> createBinding? 
You would need to only pass in the type's superclasses.

> How would we get all these IFields? Building a supertype
> hierarchy? That really wouldn't make sense.
Agreed that would be very inefficient.

Comment 20 Jerome Lanneluc CLA 2006-11-15 09:17:28 EST
(In reply to comment #18)
> I think the performance improvement of bug 114935 should be made explicit by
> allowing the API client to tell whether bindings should be completely resolved
> after the last accept*(..) callback. This could either be an additional
> parameter for ASTParser#createASTs(..), or another callback method in
> ASTRequestor, e.g.
>     public boolean stopResolvingBindings() { return false; }
> 
> ASTParser#createBindings(..) has to return complete bindings.
> 
This proposal makes sense to me.
So we have 2 issues here:
- fixing the NPE (this bug)
- adding a new API to control whether we should stop resolving after the last accept(...) has been done (please open a separate bug for that)
Comment 21 Olivier Thomann CLA 2006-11-15 09:59:36 EST
Ok, in this case we might need two new APIs depending how we do it. One for createBindings(...) and one for createAST(...).
Do we agree that right now createAST(...) is doing too much work? It should also clean up all units in the queue. In order to get all the bindings complete, the new API should be used. This might break existing users.
Comment 22 Jerome Lanneluc CLA 2006-11-15 10:09:06 EST
(In reply to comment #21)
> Ok, in this case we might need two new APIs depending how we do it. One for
> createBindings(...) and one for createAST(...).
I think you meant one for createASTs(...) and one for createAST(). Markus said that createBindings(...) should always return complete bindings, so we should fix that when we get a separate bug for it.

> Do we agree that right now createAST(...) is doing too much work? It should
> also clean up all units in the queue. In order to get all the bindings
> complete, the new API should be used. This might break existing users.
I agree that it is doing too much. However nobody complained about it yet. So when we get a complaint that createAST(...) is too slow, then we can add a new API that would cleanup the remaining CUs in the queue. Thus we would not break existing clients. So I would not change anything for createAST(...) for now.

Comment 23 Martin Aeschlimann CLA 2006-11-15 10:20:51 EST
createAST() is doing the right thing, createBindings() should do the same (complete bindings). I agree with Jerome, we don;t need to add API at this time.

The new API would be for clients of 'createASTs' (like in bug 114935) so they can tell the queue that after the last callback to their ASTRequestor they are done and won't access bindings outside the queue (or is this already part of the contract of the ASTRequestor?)
Comment 24 Olivier Thomann CLA 2006-11-15 11:29:10 EST
(In reply to comment #23)
> createAST() is doing the right thing, createBindings() should do the same
> (complete bindings). I agree with Jerome, we don;t need to add API at this
> time.
createAST() doesn't resolve the bindings before they are requested. It simply keeps all the scopes around for the units in the queue. This allows lazy resolution to work. So in order to fix this, we would simply remove the cleaning of the units in the queue for createBindings() and we should get a consistent behavior. But this should be in a different bug report. This one is about the NPE.

I open bug 164660 for the new API creation. Feel free to add your proposal there.
Comment 25 Olivier Thomann CLA 2006-11-15 23:23:34 EST
*** Bug 151364 has been marked as a duplicate of this bug. ***
Comment 26 Olivier Thomann CLA 2006-11-16 11:19:53 EST
NPE is fixed in HEAD.
Released for 3.3M4.
Please use bug 164660 in order to fix the problem with incomplete bindings (annotations are not resolved for the super class).
Regression tests are now reenabled.
Comment 27 Frederic Fusier CLA 2006-12-12 13:15:17 EST
Verified for 3.3 M4 using build I20061212-0010.