Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointer Exception in the AnnotationBinding #2895

Conversation

subyssurendran666
Copy link
Contributor

@subyssurendran666 subyssurendran666 commented Sep 3, 2024

What it does

#2402

How to test

Author checklist

@subyssurendran666 subyssurendran666 force-pushed the NullPointerException-in-AnnotationBinding-2402-new branch 2 times, most recently from ee9c71d to b3f8bf1 Compare September 23, 2024 18:45
@@ -612,7 +615,7 @@ protected JavaElement getUnresolvedJavaElement() {
return null;
}
if (!(this.resolver instanceof DefaultBindingResolver)) return null;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this change.

@jarthana
Copy link
Member

To add some context to my last review comment, here are couple of experiments I want you to try:

  1. Add this line to the end of your testcase
    assertEquals("incorrect number of annotations", 1, annotations.length);
  2. Make this small change to your testcase:
    class anothername {} instead of class com{}
    Now if you run your test with class name as anothername, the test will pass. But with class com{}, it will fail.
    Here's what I found. When we have a valid class in the scope with the same name as the qualifier of the annotation, in this case, "com", the annotation resolution returns null. Otherwise, i.e. when the first qualifier (which is considered to be a package) is not found, we create a MissingTypeBinding and not null. But I guess this is irrelevant to this issue.

We should try and exclude the null annotation to the array if possible.

@stephan-herrmann
Copy link
Contributor

  1. Make this small change to your testcase:
    class anothername {} instead of class com{}
    Now if you run your test with class name as anothername, the test will pass. But with class com{}, it will fail.
    Here's what I found. When we have a valid class in the scope with the same name as the qualifier of the annotation, in this case, "com", the annotation resolution returns null. Otherwise, i.e. when the first qualifier (which is considered to be a package) is not found, we create a MissingTypeBinding and not null. But I guess this is irrelevant to this issue.

Well, maybe this finding will help us to prevent the null in the first place? Why does one unresolvable name produce null while a similar case produces MissingTypeBinding (which is very much to be preferred!).

@jarthana
Copy link
Member

Well, maybe this finding will help us to prevent the null in the first place? Why does one unresolvable name produce null while a similar case produces MissingTypeBinding (which is very much to be preferred!).

Well, I do know why we do that and assumed that's the expected way. In fact, almost copied you on this issue, but didn't bother you. Anyway, since we are here, let me say what's going on. When there's a type in the same CU with the same name (com) as the first qualifier of the type in question (com.Missing), the first call to findTypeOrpackage returns non empty and from there on (and since we don't have any other package/type with that name), we keep the scope as that type and return null. Do you think we should still create a missing type binding?

@stephan-herrmann
Copy link
Contributor

Well, maybe this finding will help us to prevent the null in the first place? Why does one unresolvable name produce null while a similar case produces MissingTypeBinding (which is very much to be preferred!).

Well, I do know why we do that and assumed that's the expected way. In fact, almost copied you on this issue, but didn't bother you. Anyway, since we are here, let me say what's going on. When there's a type in the same CU with the same name (com) as the first qualifier of the type in question (com.Missing), the first call to findTypeOrpackage returns non empty and from there on (and since we don't have any other package/type with that name), we keep the scope as that type and return null. Do you think we should still create a missing type binding?

Can you show me the location of that return null? Is it inside Scope.getTypeOrPackage() (which overload?) or is some caller doing that? Or are you actually looking at a different method?

@jarthana
Copy link
Member

Can you show me the location of that return null? Is it inside Scope.getTypeOrPackage() (which overload?) or is some caller doing that? Or are you actually looking at a different method?

Sorry, this fell between cracks. What happens is, we return a SourceTypeBinding from Scope.getTypeOrPackage(char[], int, boolean). This is called from getPackage, line number 3173. Since it's not null, it escapes the null check in next line and then we hit this few lines below:
if (!(binding instanceof PackageBinding)) return null;

We are looking for a qualified name "com.Missing". But getTypeOrPackage() call only gets one segment. So, it is oblivious to the fact that com.Missing is actually from a package "test", which is not part of the qualified name. So, ideally, getTypeOrPackage() should have returned null instead of STB.

@jarthana
Copy link
Member

jarthana commented Oct 21, 2024

@subyssurendran666 Read the comment on the Scope#getPackage() method:

/* Answer the package from the compoundName or null if it begins with a type.
* Intended to be used while resolving a qualified type name. */

This is what is happening now. But looks like the clients of the getPackage() are not really prepared to receive a null.

@jarthana
Copy link
Member

jarthana commented Oct 25, 2024

OK, after having spent quite a bit of time, I am more of less convinced that this is by design. The compiler is unaffected. Only the DOM is, which we can mitigate by the null-check. I will go ahead with the original patch from Suby. @subyssurendran666 can you please resolve the conflicts and update the PR?

@subyssurendran666 subyssurendran666 force-pushed the NullPointerException-in-AnnotationBinding-2402-new branch from b3f8bf1 to b15d113 Compare October 28, 2024 08:34
@subyssurendran666 subyssurendran666 force-pushed the NullPointerException-in-AnnotationBinding-2402-new branch from a6f4685 to 16f1b8c Compare October 28, 2024 09:30
@jarthana jarthana merged commit 65db85c into eclipse-jdt:master Oct 28, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants