Bug 161244 - Need to know whether a proposal is unique
Summary: Need to know whether a proposal is unique
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: David Audel CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
: 207925 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-10-17 10:32 EDT by Dani Megert CLA
Modified: 2009-01-16 10:37 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dani Megert CLA 2006-10-17 10:32:45 EDT
HEAD or N20061018-0800.

In order to fix bug 161242 we need support from JDT Core: when JDT Core creates complex method or field proposal for a missing type (i.e. with required TYPE_REF proposal) it already knows whether there is one or more missing type.

Doing this on the UI side by iterating and comparing all the proposals with each other and recompute information that is already present is bad for the performance and hence we need to have an API on CompletionProposal which tells us whether it is unique.
Comment 1 Dani Megert CLA 2007-03-17 08:30:53 EDT
ping.
Comment 2 Jerome Lanneluc CLA 2007-04-02 11:14:37 EDT
To be investigated for 3.3M7
Comment 3 David Audel CLA 2007-04-17 05:22:55 EDT
There is some different cases when we can consider that a proposal is 'unique' or not.

package p0;
public class Test {
  {
    X var = null;
    var.f| // complete at |
  }
}

1) If there is no type corresponding to X then there is no proposal
2) If there is only one type (p1.X) with a method (foo) then there is only one proposal.
   -> We can consider this proposal as 'unique'
3) If there is two types (p1.X and p2.X) with the same method (p1.X#foo and p2.X#foo) then there is two proposals.
   -> These two proposals can't be considered as 'unique'. 
4) If there is two types (p1.X and p2.X) with different methods starting with 'f' (p1.X#foo1 and p2.X#foo2) then there is two proposals.
   -> These proposals shouldn't be considered as 'unique' otherwise the user would think that the two methods come from the same type.
5) If there is two types (p1.X and p2.X) and only one type contains a method starting with 'f' (p1.X#foo) then there is one proposal.
   -> We could consired this proposal as 'unique' because there is no other proposal or we could consider this proposal as not 'unique' because it exists another type with the same simple name.
      I think that this proposal shouldn't be considered as 'unique' because it should be better to inform the user that he choose a type instead of another.



To return the information we need to add a new API.
We could add an API like:
class CompletionProposal {
   ...
   /**
    * This method is available only for required proposal of the following kinds 
    * of completion proposals:
    * <ul>
    *   <li><code>TYPE_REF</code> - return false if the simple name of the proposed type is the same as the simple name of another type</li>
    * </ul>
    */
   public boolean simpleNameIsUnique() {...}
   ...
}

for the case 2) the proposals would be
METHOD_REF - p1.X#foo()
 +-required: TYPE_REF - p1.X [simpleNameIsUnique=true]
METHOD_REF - p2.X#foo()
 +-required: TYPE_REF - p2.X [simpleNameIsUnique=true]

This API have at least these defects:
*1* - A client would need to check all required TYPE_REF proposals of a proposal to know if the qualification of the declaring type is necessary.
*2* - A required proposal can be only a part of the declaring type when it's a generic type so the link between required TYPE_REF and the declaring type isn't direct.
package p0;
public class X<T> {}

package p1;
public class Y {
  public void foo1();
}

package p2;
public class Y {
  public void foo2();
}

package t;
class Test {
  {
    p0.X<Y> var = null;
    var.foo| // complete at |
  }
}

proposals are:
METHOD_REF - p0.X<p1.Y>#foo1()
 +-required: TYPE_REF - p1.Y
METHOD_REF - p0.X<p2.Y>#foo2()
 +-required: TYPE_REF - p2.Y

Another problem is that even if Y is qualified then type arguments aren't displayed in proposal list.

package t;
class Test {
  {
    p0.X<p1.Y> var = null;
    var.foo| // complete at |
  }
}

*3* - The existing getRequiredProposals() API don't specify that a required TYPE_REF is related to the declaring type of the proposal.
And i don't think that it would be a good idea to limit the scope of this API to the declaring type because we would add a hard limitation for future usage of this API.
*4* - This API would be specific to required proposals and there is a similar problem for simple proposal without any missing types
package p1;
public class X {
  public void foo1();
}

package p2;
public class X extends p1.X {
  public void foo2();
}
 
class Test extends p2.X {
  {
    this.foo| // complete at |
  }
}

proposals are:
METHOD_REF - p1.X#foo1()
METHOD_REF - p2.X#foo2()


To avoid some defects we could add the same API for every TYPE_REF proposals (required or not)
 but it would be more work to not miss a case concerned by this API.


Another possibility could be to add an API for 'top level' proposals instead of for required proposal.

class CompletionProposal {
   ...
   /**
    * This method is available only for proposals which have a declaring type and which have a TYPE_REF as required proposal.
    * return false if simple name of the declaring type is the same as another different declaring type of another proposal.
    */
   public boolean declaringTypeSimpleNameIsUnique() {...}
   ...
}

This API have some of the defects of the first proposal:
*1* - This API would be specific to proposal with required proposals and there is a similar problem for simple proposal without any missing types
*2* - The existing getRequiredProposals() API don't specify that a required TYPE_REF is related to the declaring type of the proposal


I think we should avoid to add one of these proposal of API because
- we are beyond the 3.3 API freeze.
- we shouldn't add an API specific to the 'missing types' case that could be cause problem in the future to manage cases with no missing types
- the test case of the problem is not a common case: A variable's type must be unresolved and the name of this type must correspond to several types and a completion on a member reference must requested
- i need to do more investigation to solve the general case before M7 which is close.

Daniel - What do you think about these proposals ? And do you think it's necessary to add this API for 3.3 ?
Comment 4 Dani Megert CLA 2007-04-25 04:46:32 EDT
>- we are beyond the 3.3 API freeze.
This is not a blocker. Many new APIs have already been approved.

>And do you think it's necessary to add this API for 3.3 ?
Yes, I think so. Look at this example:
List l; l.toS<code assist>
==> you get several proposals where the type is shown unqualified. If you choose toString from Object it will insert java.util.List but in all other cases it will insert java.awt.List.

The second proposal i.e. flag on the top-level proposal is what we need as this is the proposal we show to the user.
Comment 5 Dani Megert CLA 2007-04-25 04:47:36 EDT
We don't need to know whether it is unique but whether I need to fully qualify the type and this is the case when the proposal type is yet unresolved.
Comment 6 David Audel CLA 2007-04-26 13:15:16 EDT
My proposals in comment 3 aren't sufficient to solve the problem.

With a test case like

java.util.Collection<List> var;
var.toS<code assist>

there is two proposals in the list (one for java.awt.List, one for java.util.List)

toString() String - Object
toString() String - Object

Even if all types are displayed fully qualified then proposals will be still ambiguous.
The missing information is the type of the receiver (eg. java.util.Collection<java.util.List>).
Currently this information isn't given by jdt/core CompletionProposal.

If an API was added to give this information (eg. CompletionProposal#getReceiverSignature()), clients (jdt/text) won't know what part of the receiver type is 'ambiguous'.
Or clients display all the type fully qualified (java.util.Collection<java.util.List>) or else clients can compute a shorter type (Collection<java.util.List>) but this could be bad for performance.

Another issue is that there is some other 'ambiguous' cases:

a) (from comment 3)
package p1;
public class X {
  public void foo1();
}

package p2;
public class X extends p1.X {
  public void foo2();
}

class Test extends p2.X {
  {
    this.foo| // complete at |
  }
}

proposals are
foo1() void - X
foo2() void - X

b)
public class AClass {
  public void foo(java.awt.List l) {}
  public void foo(java.util.List l) {}
}
class Test {
  {
    AClass  var;
    var.foo| // complete at |
  }
}

proposals are
foo1(List l) void - AClass
foo2(List l) void - AClass

c)
public class AClass {
  public void foo(java.awt.List l) {}
  public void foo(java.util.List l) {}
}
class Test extends AClass {
  foo| // complete at |
}

proposals are
foo1(List l) void - Override method in AClass
foo2(List l) void - Override method in AClass


API previously proposed doesn't solve a) b) or c) and it would be a bad idea to add an API that solve only the 'missing type' case and that become obsolete later if we decide later to add more general API.


Perhaps it would be better that jdt/core give the receiver type and declaring type and 'signature' with the minimal qualification (eg. Collection<java.util.List>).
It's just an idea and i don't know if it is easy to do that.


We are close to 3.3M7 then it seems difficult to find the right API for 3.3. 
Comment 7 Philipe Mulet CLA 2007-05-03 10:56:54 EDT
removing target for now
Comment 8 Dani Megert CLA 2007-10-30 06:22:55 EDT
*** Bug 207925 has been marked as a duplicate of this bug. ***
Comment 9 Dani Megert CLA 2007-10-30 06:24:40 EDT
Another solution would be to not suggest all three but only suggest one proposal without an import i.e. let the user choose later.
Comment 10 Dani Megert CLA 2007-10-31 11:55:57 EDT
>Another solution would be to not suggest all three but only suggest one
>proposal without an import i.e. let the user choose later.
This wasn't clear. I meant, in case of similar duplicates JDT Core could only suggest one but without the required proposal that adds the import.

See bug 207926 for another use case.
Comment 11 Jerome Lanneluc CLA 2008-05-12 05:20:14 EDT
Deferring again.
Comment 12 Dani Megert CLA 2009-01-14 12:00:07 EST
I think I no longer need this. Please close if you agree with my latest comment in bug 161242.
Comment 13 Dani Megert CLA 2009-01-16 10:37:23 EST
I no longer need this.