Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 99137

Summary: No hover on inner type constructor
Product: [Eclipse Project] JDT Reporter: Tobias Widmer <tobias_widmer>
Component: UIAssignee: JDT-UI-Inbox <jdt-ui-inbox>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: P3 CC: frederic_fusier, gturski, jerome_lanneluc, markus.kell.r, martinae, philippe_mulet, pwebster, thomas.a.cook
Version: 3.1   
Target Milestone: 3.3 M4   
Hardware: PC   
OS: All   
Whiteboard:
Attachments:
Description Flags
Proposed patch for JDT/UI none

Description Tobias Widmer CLA 2005-06-09 08:47:58 EDT
N20050609-0010

Steps to reproduce:
- Open class ConvertForLoopProposal from HEAD
- Hover over the first constructor reference of class LocalOccurrencesFinder

-> No hover shows up. Same with all three constructors of that particular class
Comment 1 Dani Megert CLA 2005-06-09 09:43:36 EDT
simpler test case:

public class C {
	private class Inner {
		public Inner(int i) {}
		void innerFoo(){}
	}
	
	void foo() {
		Inner i= new Inner(1);
		i.innerFoo();
	}
}
Comment 2 Martin Aeschlimann CLA 2005-06-09 10:37:06 EDT
Our label provider fails as the number of parameters receieed from the binding
key is not the same as the number of parameter names received from the IMethod.

bining key: 'Lpack/C$Inner;.(Lpack/C;I)V'

Should be only 1 parameter.

Thread [Text Viewer Hover Presenter] (Suspended (exception
ArrayIndexOutOfBoundsException))
 JavaElementLabels.getMethodLabel(IMethod, long, StringBuffer) line: 518
 JavaElementLabels.getElementLabel(IJavaElement, long, StringBuffer) line: 386
 JavaElementLabels.getElementLabel(IJavaElement, long) line: 363
 JavadocHover.getInfoText(IJavaElement) line: 142
 JavadocHover.getHoverInfo(IJavaElement[]) line: 118
 JavadocHover(AbstractJavaEditorTextHover).getHoverInfo(ITextViewer, IRegion)
line: 120
 BestMatchHover.getHoverInfo(ITextViewer, IRegion) line: 102
 JavaEditorTextHoverProxy.getHoverInfo(ITextViewer, IRegion) line: 69
 TextViewerHoverManager$4.run() line: 160

Modified our code to no crash but have an extra check and write to the log >
20050609
Comment 3 Olivier Thomann CLA 2005-06-09 12:24:30 EDT
This is not a regression compare to RC1.
Comment 4 Olivier Thomann CLA 2005-06-09 12:26:07 EDT
M7 was also broken.
Comment 5 Dirk Baeumer CLA 2005-06-13 09:53:43 EDT
*** Bug 99639 has been marked as a duplicate of this bug. ***
Comment 6 Philipe Mulet CLA 2005-06-14 15:48:33 EDT
The binding key reflects resolved info as it would appear in classfile.
Therefore, it doesn't (and shouldn't) hide synthetics which are mandated.
Also this guarantees independance in between source/binary form.

Comment 7 Dirk Baeumer CLA 2005-06-20 09:33:31 EDT
*** Bug 100773 has been marked as a duplicate of this bug. ***
Comment 8 Dirk Baeumer CLA 2005-06-20 09:41:19 EDT
This problem apprears in all cases where we have a constructor invocation for
non static inner classes. The problem is that the binding key is one for the
synthetic  construcutor taking TestClass and the signature is one for the method
as it appears in source. 

What are we going to do here: the fact that we get elements from different
models here (source versus binray) makes it complicated. 

At least the binding key should tell us that it is "synthetic" and JDT/Core
should provide methods to convert it into a "non" synthetic key. Otherwise we
can never use the key to render "source" information in this cases.

What are the options for 3.1:

- we don't log the error
- we don't log the error in cases of a constructor

Opinions ?
Comment 9 Jerome Lanneluc CLA 2005-06-20 11:01:02 EDT
I would vote for not logging the error since we correctly behave in most cases
(at least in the case in comment #1, the hover works with RC3, same with case in
100173)
Comment 10 Olivier Thomann CLA 2006-01-27 14:04:41 EST
*** Bug 123529 has been marked as a duplicate of this bug. ***
Comment 11 Frederic Fusier CLA 2006-08-11 06:37:38 EDT
I've tried with 3.1.2 and was not able to reproduce the problem (comment 0, comment 1 and duplicates) => close as worksforme as WORKSFORME as I cannot put any entry in buildnotes for this bug
Comment 12 Markus Keller CLA 2006-08-14 09:27:17 EDT
JDT/UI does not log the error any more (bug 101029 removed the logging in JavaElementLabels (line 543 in rev. 1.39)).

The key from IMethod#getKey() still contains the synthetic parameter type when decoded via Signature.getParameterTypes(new BindingKey(key).toSignature()).

The effect can be seen in 3.1.2 and in HEAD with the example from comment 1 when hovering over "Inner" in "new Inner(1)":
- Expected: "xy.C.Inner.Inner(int i)"
- Is: "xy.C.Inner.Inner(C, int)"

Our current fallback in JavaElementLabels is to just render the parameter types, but not the parameter names.
Comment 13 Frederic Fusier CLA 2006-11-27 08:03:26 EST
(In reply to comment #12)
> JDT/UI does not log the error any more (bug 101029 removed the logging in
> JavaElementLabels (line 543 in rev. 1.39)).
> 
> The key from IMethod#getKey() still contains the synthetic parameter type when
> decoded via Signature.getParameterTypes(new BindingKey(key).toSignature()).
> 
> The effect can be seen in 3.1.2 and in HEAD with the example from comment 1
> when hovering over "Inner" in "new Inner(1)":
> - Expected: "xy.C.Inner.Inner(int i)"
> - Is: "xy.C.Inner.Inner(C, int)"
> 
> Our current fallback in JavaElementLabels is to just render the parameter
> types, but not the parameter names.
> 
Not really sure to understand your fall back here... Why, when parameter types and parameter names have different lengthes, don't you use the method.getParameterTypes() instead of Signature.getParameterTypes() result?

Then you would have:
if (getFlag(flags, M_PARAMETER_NAMES) && method.exists()) {
	names= method.getParameterNames();
	if (types == null) {
		nParams= names.length;
	} else if (nParams != names.length) {
		if (resolvedSig == null) {
			// nothing can really be done in this case...
			names = null;
		} else {
			// get types from model instead of signature
			types = method.getParameterTypes();
			if (types == null) {
				nParams = names.length;
			else if (types.length == names.length) {
				nParams = types.length;
			} else {
				// nothing can really be done in this case...
				names = null;
			}
		}
	}
}

As the model is already populated with method.exists() call, there's no real performance side effect with this implementation.

This snippet shows that clients can distinguish constructors with synthetic parameters. Then, I think that trying to add information in unique key for this piece of information would pollute it unnecessarily.

Markus, what's your mind on this?
Comment 14 Markus Keller CLA 2006-11-28 11:53:49 EST
The problem is that clients can only do the distinction if they have both a binding key and the corresponding IMethod. If they use BindingKey#toSignature() in a different context, they still get the wrong signature.

Re our current fallback: We didn't try to find a "smart" workaround -- we just didn't want to be completely screwed up in case this happens.
Comment 15 Frederic Fusier CLA 2006-11-28 13:39:07 EST
Consider this as a limitation of the unique key: we can't remove the synthetic parameters from the it has they come from the method signature. By the way, the unique key is not supposed to provide all the information of the IMethod.

So, unfortunately, if there are cases where clients only have this binding key, then they will not be able to distinguish these synthetic parameters. However, I can't see in any duplicate bugs such a test case...

Note that, talking with Jerome, he said that getParameterTypes on IMethod gives less information than those got from binding key, so the comment 13 snippet can be improved => I'll attach a patch...
Comment 16 Frederic Fusier CLA 2006-11-28 13:40:35 EST
Created attachment 54656 [details]
Proposed patch for JDT/UI

This patch was done on version v20061128-0800 of org.eclipse.jdt.ui project.
Comment 17 Frederic Fusier CLA 2006-11-28 13:43:21 EST
Markus,
As the attached patch fixes issue described in this bug and considering that unique key has this limitation on synthetic parameters, I move this bug to JDT/UI
Comment 18 Martin Aeschlimann CLA 2006-11-29 05:59:54 EST
Thanks Frederic for the patch. I changed our code to do what you suggested.

Its clear to me that from a signature it isn't possible to find out anymore what parameters are synthetic. But I think it would make sense to add that to the Javadoc to 'Signature.getParameterTypes' to say that the returned types can also contain synthetic parameter that are not returned from API in the Java model or AST.

I guess you could solve the problem in the binding key where the format is under your control and you could offer
(new API) BindingKey.getParameterTypes that does not return these types.

But I must say that I'm fine if we ignore this issue for now until we detect other problems. The workaround will do fine.
Comment 19 Martin Aeschlimann CLA 2006-11-29 06:43:34 EST
moving to jdt.core to decide if they want to offer new API in BindingKey to solve this, or if the current solution is good enough
Comment 20 Frederic Fusier CLA 2006-11-29 07:06:59 EST
As I said in comment 17, we currently consider this as a limitation of BindingKey and do not plan to add any new API to solve this peculiar issue until there's a strong need on it...

I'd rather prefer to assign this bug to JDT/UI as we didn't change any code in JDT/Core to solve this problem. You can then close it as FIXED and add a specific test for it.

If you want to keep trace of the BindingKey limitation on this subject, then open a separate bug and I'll close it as WONTFIX. We could then reopen it if someone else complains about this...
Comment 21 Martin Aeschlimann CLA 2006-11-29 08:43:02 EST
I was more thinking about the bug title. But you're right, the scenario is fixed now. I updated the title to match the scenario
Comment 22 Dani Megert CLA 2006-12-12 04:08:47 EST
Starting verification...
Comment 23 Dani Megert CLA 2006-12-12 04:12:05 EST
Verified using I20061212-0010.