Bug 321276

Summary: JDT Core APIs don't recognize InnerClass constructor inside .class files
Product: [Eclipse Project] JDT Reporter: Prashant Deva <prashant.deva>
Component: CoreAssignee: Olivier Thomann <Olivier_Thomann>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: daniel_megert, Olivier_Thomann, stephan.herrmann
Version: 3.6   
Target Milestone: 3.7 M2   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
Proposed fix
none
Proposed fix + regression test none

Description Prashant Deva CLA 2010-07-29 19:26:42 EDT
This is a fully reproducible bug.

1. Reference some jar in your project. 
2. Attach its source.
3. Browse to an Inner class. 
4. Place your cursor inside the innner class constructor.

Now if the following code snippet is run, it returns null if the file is a .class file, however it returns an IMethod if the same is inside a .java file.


 
	private IMember getMethodAtCursor()
	{
		IJavaElement element = getSelectedJavaElement();
		if (element != null)
		{
			try
			{
				if (element instanceof ICompilationUnit)
				{
					element = ((ICompilationUnit) element).getElementAt(currentSelection.getOffset());
				} else if (element instanceof IClassFile)
				{
                                        //NOTE: this line will set element to null

					element = ((IClassFile) element).getElementAt(currentSelection.getOffset());
				}

				if (element instanceof IMethod || element instanceof IInitializer)
					return (IMember) element;
			} catch (JavaModelException e)
			{
				return null;
			}
		}

		return null;
	}
Comment 1 Prashant Deva CLA 2010-07-30 18:40:54 EDT
An even easier way to reproduce this bug is to open a .class file (with source of course), and open the outline view.
When you place your cursor inside the constructor of the inner class, the outline view doesnt sync and highlight the method inside the view, however it does so for every other method in the inner class.

My personal gut feeling says that its cause the inner class constructors take a hidden parameter to the 'this' pointer of the outerclass and that is messing with the signature that the text editor is passing which does not include the hidden parameter.
Comment 2 Stephan Herrmann CLA 2010-07-30 19:39:10 EDT
At a quick check I couldn't reproduce. Using Eclipse 3.6.0 I opened class
HashMap from the JRE and navigated to some of its inner classes like Entry.
In this scenario everything works as expected.

So you probably have either a different Eclipse version or a different inner
class.
Comment 3 Prashant Deva CLA 2010-07-30 19:42:36 EDT
could be some compiler specific thing in the class file.
try using a 1.5 compiled class file.
Comment 4 Stephan Herrmann CLA 2010-07-30 20:09:27 EDT
If it's fully reproducible on your machine we need to know what
exact Eclipse version you have and which example classes from
which jar you used.
Could you please provide these details? Thanks.
Comment 5 Prashant Deva CLA 2010-07-30 20:35:13 EDT
i am using eclipse 3.6.0.

did you try reproducing on 1.5 compiled class?
Comment 6 Olivier Thomann CLA 2010-07-30 23:06:55 EDT
(In reply to comment #5)
> i am using eclipse 3.6.0.
> did you try reproducing on 1.5 compiled class?
Prashant, please attach a test case that is showing the problem.
Thanks.
Comment 7 Prashant Deva CLA 2010-07-30 23:33:10 EDT
here ya go -

1. download berkeley db je 4.103
2. reference it and attach the src in eclipse.
3. navigate to the constructor of Store.InternalPrimaryIndex

you can see the problem manifest itself there.
Comment 8 Stephan Herrmann CLA 2010-07-31 18:40:49 EDT
(In reply to comment #7)
> here ya go -
> 
> 1. download berkeley db je 4.103
> 2. reference it and attach the src in eclipse.
> 3. navigate to the constructor of Store.InternalPrimaryIndex
> 
> you can see the problem manifest itself there.

OK, that get's us going. Here's a minimal test class:

public class Container {
    private class Inner<S> {
        Inner(String st/*, Class<S> s*/) {
            super();
        }
    }
}

- export as jar in the file system, 
- import into other project as external jar and attach source. 
Using the class as above everything works fine, however, when uncommenting 
the second ctor arg (and repeating the jar-steps) the outline indeed no longer
synchronizes with the editor, likely indicating a missing java element.
Comment 9 Olivier Thomann CLA 2010-08-01 10:27:58 EDT
Thanks for the test case. I'll investigate.
Comment 10 Olivier Thomann CLA 2010-09-02 12:32:41 EDT
*** Bug 322880 has been marked as a duplicate of this bug. ***
Comment 11 Olivier Thomann CLA 2010-09-02 12:33:20 EDT
The problem occurs only when the constructor has a generic signature. I believe the problem comes from the fact that the generic signature doesn't contain the enclosing instance.
Comment 12 Olivier Thomann CLA 2010-09-02 12:34:52 EDT
Created attachment 178060 [details]
Proposed fix

Stephan, could you please test it with your test case ?
Thanks.
I still need to add a regression test for it.
Comment 13 Olivier Thomann CLA 2010-09-03 10:00:11 EDT
Created attachment 178149 [details]
Proposed fix + regression test

Same patch with a regression test.
Comment 14 Olivier Thomann CLA 2010-09-03 11:24:07 EDT
Released for 3.7M2.
Regression test added in:
org.eclipse.jdt.core.tests.model.AttachSourceTests#testConstructorAccess
Comment 15 Stephan Herrmann CLA 2010-09-04 08:09:24 EDT
(In reply to comment #12)
> Created an attachment (id=178060) [details]
> Proposed fix
> 
> Stephan, could you please test it with your test case ?
> Thanks.
> I still need to add a regression test for it.

Sorry for the delay (I was away from the internet for some days).

I just picked up build N20100903-2000 and tried the scenarios from comment 8
and everything works as desired. Good job :)

Obviously the missing JavaElement was indeed the issue and your test
and fix are sufficient.
Comment 16 Dani Megert CLA 2010-09-14 06:19:59 EDT
Verified in I20100914-0100.