Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 317216 - NullPointerException in ParameterizedTypeBinding.readableName
Summary: NullPointerException in ParameterizedTypeBinding.readableName
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: APT (show other bugs)
Version: 3.7   Edit
Hardware: PC Linux
: P3 normal with 1 vote (vote)
Target Milestone: 4.7 M1   Edit
Assignee: Stefan Xenos CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 497522 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-06-17 12:38 EDT by Stephen Haberman CLA
Modified: 2016-07-14 14:26 EDT (History)
5 users (show)

See Also:
jarthana: review+


Attachments
reproduction of NPE (23.56 KB, application/zip)
2010-06-20 11:24 EDT, Stephen Haberman CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stephen Haberman CLA 2010-06-17 12:38:36 EDT
Build Identifier: I20100603-1500

Running an annotation processor, I'm getting the following stack trace while calling TypeMirror.toString():

java.lang.NullPointerException
	at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.readableName(ParameterizedTypeBinding.java:828)
	at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.readableName(ParameterizedTypeBinding.java:836)
	at org.eclipse.jdt.internal.compiler.apt.model.DeclaredTypeImpl.toString(DeclaredTypeImpl.java:123)
	at org.bindgen.processor.util.BoundProperty.<init>(BoundProperty.java:51)
	at org.bindgen.processor.generators.MethodPropertyGenerator.<init>(MethodPropertyGenerator.java:41)
	at org.bindgen.processor.generators.MethodPropertyGenerator$Factory.newGenerator(MethodPropertyGenerator.java:260)
	at org.bindgen.processor.generators.MethodPropertyGenerator$Factory.newGenerator(MethodPropertyGenerator.java:229)
	at org.bindgen.processor.generators.BindingClassGenerator.getPropertyGenerators(BindingClassGenerator.java:184)
	at org.bindgen.processor.generators.BindingClassGenerator.addProperties(BindingClassGenerator.java:119)
	at org.bindgen.processor.generators.BindingClassGenerator.generate(BindingClassGenerator.java:62)
	at org.bindgen.processor.GenerationQueue.processQueue(GenerationQueue.java:65)
	at org.bindgen.processor.Processor.process(Processor.java:67)
	at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:139)
	at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.round(RoundDispatcher.java:121)
	at org.eclipse.jdt.internal.compiler.apt.dispatch.BaseAnnotationProcessorManager.processAnnotations(BaseAnnotationProcessorManager.java:159)
	at org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeAnnotationProcessorManager.processAnnotations(IdeAnnotationProcessorManager.java:134)
	at org.eclipse.jdt.internal.compiler.Compiler.processAnnotations(Compiler.java:809)
	at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:428)
	at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:364)
	at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.compile(BatchImageBuilder.java:178)
	at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:301)
	at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.build(BatchImageBuilder.java:60)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildAll(JavaBuilder.java:254)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:173)
	at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:629)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:172)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:203)
	at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:255)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:258)
	at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:311)
	at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:343)
	at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:144)
	at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:242)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

The line that is failing is enclosingType().readableName():

	public char[] readableName() {
	    StringBuffer nameBuffer = new StringBuffer(10);
		if (isMemberType()) {
			nameBuffer.append(CharOperation.concat(enclosingType().readableName(), this.sourceName, '.'));
		} else {
			nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
		}

isMemberType() is true but the enclosingType field is null.

The error is happening with:

* TypeElement te = java.util.Map
* ExecutableElement ee = te.getEnclosed() if kind==name and name==entrySet
* TypeMirror tm = ee.getReturnType
* tm.toString() --> NPE

Note that tm is the DeclaredTypeImpl that is 3 lines into the NPE stack trace.

While tm.toString() fails (it calls _binding.readableName()), if I debug and look at _binding, it toStrings() as:

    public interface Set<Entry<K,V>>
	extends NULL TYPENULL SUPERINTERFACESNULL FIELDSNULL METHODS

Inside the _binding.readableName, nameBuffer had gotten to:

    java.util.Set<

And it is calling into the 1st type parameters readableName. This binding can also toString:

public static interface Entry<K,V>
	extends NULL TYPENULL SUPERINTERFACESNULL FIELDSNULL METHODS

But it's readableName is what is blowing up.

I've made a separate project to reproduce it, but unfortunately it works just fine. I get to the same binding, and in this new project it toStrings as:

public static interface Entry<K,V>
	extends NULL TYPENULL SUPERINTERFACES
	enclosing type : Map#RAWNULL FIELDSNULL METHODS

Note that enclosign type is no longer null.

I have no idea why my more complex project would lead to the enclosing type being null.

I can keep poking around, but suggestions are welcome.

Also note that I'm seeing this behavior in both the latest 3.5 and 3.6.RC4.



Reproducible: Always

Steps to Reproduce:
I cannot reproduce it outside of my current project yet.
Comment 1 Stephen Haberman CLA 2010-06-18 22:26:19 EDT
I can't get this out into a sample project, but it's easily reproducible in my existing project.

If you checkout bindgen from github, this commit introduces the error:

http://github.com/stephenh/bindgen/commit/5f4d0feddf5789088c9c8f3618c1a7f0089018c0

Bindgen comes with two projects, the processor which you can import into Eclipse and then run the BindgenExamples launch target in debug mode and import the bindgen-examples project. If you set a debug point for NPE and then change/save the MapFailsExample class in the bindgen-examples, you should hit the error right away.

Commenting/uncommenting the Map<String,String> line from the MapFailsExample class makes it go away/come back.

I've tried to mimic the bindgen processor's call path as closely as possible in another project to recreate the error and have not had success yet.
Comment 2 Stephen Haberman CLA 2010-06-20 10:23:46 EDT
Still no luck reproducing--I'd really like to set a conditional breakpoint in ParameterizedTypeBinding to see when it's constructed such that isMemberType==true but enclosingType==null. My eclipse setup isn't letting me do that though, I can set breakpoints but conditional ones cause a "missing Java project context" error.
Comment 3 Stephen Haberman CLA 2010-06-20 11:24:44 EDT
Created attachment 172292 [details]
reproduction of NPE

Got it. Should have found it a lot sooner.

The culprit is the Types method:

    DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs);

The bindgen processor does this dance where if we're in a type Foo<T> and a method return type is List<T>, but the user has declared their field as Foo<String> someStrings, I have this crazy look up routine where I figure out that the T in List<T> is the same type as Foo<T> and so then get the declared type of Foo with String, e.g. getDeclaredType(Foo, new TypeMirror[] { String }).

It turns out when the type var is not resolved, as in the case of Map.Entry<K, V>, and I call getDeclaredType(Map.Entry, new TypeMirror{} { K, V }), the resulting DeclaredType has the faulty memberType==true but enclosing==null.

(There are probably a few inaccuracies in my description, I'm rushing it, but nonetheless the attached file reproduces the error.)

Now that I know what is going wrong, I could potentially avoid it--if I detect that no s/T/String replacement took place, I could skip the getDeclaredType(Foo, TypeMirror[]) and just use the original Foo TypeMirror.
Comment 4 Jean-Marie HENAFF CLA 2016-04-05 04:28:35 EDT
Hi,

is there any news on this?

Correct me if I'm wrong, but it still seems to be present in 4.6M6.

Thanks.
Comment 5 Stefan Xenos CLA 2016-07-07 15:57:46 EDT
*** Bug 497522 has been marked as a duplicate of this bug. ***
Comment 6 Eclipse Genie CLA 2016-07-07 16:03:21 EDT
New Gerrit change created: https://git.eclipse.org/r/76903
Comment 7 Stefan Xenos CLA 2016-07-07 16:08:39 EDT
One of my coworkers suggested the following fix (attached).
Comment 9 Stephen Haberman CLA 2016-07-14 14:26:48 EDT
Awesome!