Bug 74294 - [1.5] Improved code assist proposals for generic types
Summary: [1.5] Improved code assist proposals for generic types
Status: CLOSED DUPLICATE of bug 6930
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-09-20 10:39 EDT by Erich Gamma CLA
Modified: 2014-01-23 11:08 EST (History)
2 users (show)

See Also:


Attachments
prototype (25.05 KB, text/plain)
2005-01-25 07:14 EST, David Audel CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Erich Gamma CLA 2004-09-20 10:39:37 EDT
When doing a code assist in the following set-up:
List<String> l= new Array|
I get the completion ArrayList. However, in this case code assist can help me
further and suggest "new ArrayList<String>"
Comment 1 David Audel CLA 2004-09-28 06:59:11 EDT
These completions could produce a large number of proposals.

Currently only a type name is proposed.
   new ArrayList

If we add this new kind of proposal the new proposal list will be:
   new ArrayList
   new ArrayList<String>

Another enhancement request was to add a construtor in this case (I don't find 
the number of this bug). With this kind of completion the list will become:
   new ArrayList
   new ArrayList<String>
   new ArrayList()
   new ArrayLst<String>()

The result could be an overcrowded and unusable list of proposals if there is 
several types to suggest.

Erich - Do you think that this kind of proposals are really necessary ? (the 
size of the list would be multiplied by 2)
Comment 2 Erich Gamma CLA 2004-09-28 07:32:01 EDT
>Do you think that this kind of proposals are really necessary ?
I really think so, entering the type parameter information is really annoying 
and one of the frustrations I have when entering 1.5 code.

I don't fully understand why the proposal list is doubled. When I enter
List<String> l= new Array|
Then I would only expect a single proposal
    ArrayList<String> 
and not the raw type
    ArrayList
I must be missing something here?
Comment 3 David Audel CLA 2004-09-28 07:54:03 EDT
ArrayList must be proposed for the potential static member class.
 new ArrayList.StaticMemberType();

We could only propose "new ArrayList" if it contains a static member class, 
but it is currently costly to compute (bug 44958).
Comment 4 Erich Gamma CLA 2004-09-28 08:57:34 EDT
Since you are already considering the left hand side of the assignment could 
you check whether the type on the left has a type parameter and in this case 
you make the proposals in the following order:
   new ArrayList<String>
   new ArrayList
This would still allow me to quickly complete the type name and I'm not 
penalized for the limitation described in bug 44958.

I have a scenaro for you, try to enter
Map<String, String>= new HashMap<String, String>();
Notice, even when you complete to HashMap and code assist:
   HashMap<String, String>= new HashMap<|>
You don't get helpful proposals for the type parameters. This means that I 
basically have to type "String, String".
Comment 5 Erich Gamma CLA 2004-09-28 08:59:23 EDT
typo, the scenario to try would be:
Map<String, String> map= new HashMap<String, String>();
Comment 6 Erich Gamma CLA 2004-09-28 09:14:41 EDT
Not sure whether the completion issue in the scenario 
   HashMap<String, String>m = new HashMap<|>
is a core or ui issue. I assume there is a new requestor that can return type 
parameters? Is there such a requestor that the UI should use.
Comment 7 David Audel CLA 2004-09-28 10:47:31 EDT
I am agree with you, the problem can be solve by a higher relevance for 
parameterized type (And it is probably the best solution). The only problem is 
when several types are proposed (more than 20), the completions like "new 
ArrayList" would be always at the end of the list and are not directly visible 
by user (usable?).

Now compute the proposals that you suggest is not easy. Look at the following 
example.

public interface X <T> {
}
public class Y <U> extends X<List<U>> {
}
public class A {
  void foo() {
    X<List<String>> x = new Y|
  }
}

In this case the best completion is "new Y<String>" and not "new 
Y<List<String>>".
To compute this kind of completion, there is the same probleme as bug 44948 : 
types needs to be resolved. Perhaps it would be costly, so i need to perform 
more investigation on this front.

The probleme is similar for "Map<String, String>m = new HashM|" 
and "Map<String, String>m = new HashMap<|>".
Comment 8 David Audel CLA 2004-09-28 10:52:57 EDT
Currently i work on a new requestor to be able to propose parameterized type, 
type parmater, ... . This requestor is the class CompletionRequestor but it is 
currently not functionnal and perhaps this API needs some modifications.
Comment 9 David Audel CLA 2005-01-17 09:49:36 EST
With the following test case

XX<A> x;
x = new Y//<-- do codeassist here

if YY is a generic type and YY is a sub type of XX

'class YY<T> extends XX<T> {}'

it would be interesting to complete the code with

'new YY<A>();'

A completion result is composed of two informations, the description (type
signature) and the code to insert: {signature, completion}.
The completion proposal for this case could be {LY<LA;>;, YY<A>}.
It's also possible to propose only the signature of the declaring type
{LY<LT;>;, YY<A>}.

What is the best proposal representation for you ? {LY<LA;>;, YY<A>} or
{LY<LT;>;, YY<A>} ?

Other cases are when YY is not a subtype of XX or YY is a subtype of XX but some
parameters of YY do not parameterized XX.

1) 'class Y <T> {}'
2) 'class Y <T> extends X<A> {}'
3) 'class Y <T1, T2> extends X<T1> {}'

XX<A> x;
x = new Y//<-- do codeassist here

For 1) there is no way to know the type to insert as parameter.
We could propose the type with an empty parameter ('YY<>') or propose the type
paramterized with the bound ('YY<Object>').
I don't think that propose the bound is a good idea because it will be very
often the wrong type.

If the proposed signature is the declaring signature the proposal will be
{LYY<LT;>;, YY<>}.
If the proposed signature is the parameterized signature, i think we must use
wildcard because all types are possible {LYY<*>;, YY<>}

Case 2) and 1) are the same but 2) is more relevant because YY i a subtype of XX<A>.

For 3) the proposal would be {LYY<LT1;LT2;>;, YY<A,>} or {LYY<LA;*>;, YY<A,>}

What do you think about these proposals representation ? Which is the best for you ?

Currently i'm not sure that is possible to propose this kind of completion
because it could be too coslty to compute (between 40% and 2000% slower but i
try to improve performance).
Comment 10 Tom Hofmann CLA 2005-01-18 03:35:35 EST
Another option would be to offer a generic constructor proposal

 'new ArrayList<T>()' 

the type parameter 'T' of which would only be resolved upon applying the proposal.

Advantages:
- similar to today's parameter completion for methods.
- much cheaper, since only the applied proposal's type must be resolved
- if more than one concrete type parameter is possible, they can be proposed in
a follow-up proposal (as the guessed method parameters).
- if the guess is not 100% unambiguous, the types can be made linked fields
Comment 11 Tom Hofmann CLA 2005-01-18 03:48:28 EST
Oh, hadn't read comment 9 closely when posting...

I guess the generic signature '{LYY<LT;>;, YY<A>}' or even '{LYY<LT;>;, YY<T>}'
would be enough at first to propose the completion.

I favor a two-step approach where the user selects a generic constructor<T>
first, and the type parameter is only computed when the proposal is chosen. If
the type parameter can not be unambiguously determined, we can still either
offer the possible choices, or at least mark the type parameter as linked
region, so the user can change it quickly.

BTW: would the generic signature not rather be 

'{LYY<TT;>;, YY<A>}'
      ^

, since Signature.C_TYPE_VARIABLE == 'T'?
Comment 12 David Audel CLA 2005-01-25 07:00:37 EST
* To compute parameterized type i need to know type binding.
Compute type binding for all proposed types is too costly when there is a lot of
types.

* To reduce the number of types to resolve, i could resolve only subtypes of the
expected type.
Compute hierachy of the expected type is too coslty with large hierarchies
(List, Map, Exception, ...).
 
Comment 13 David Audel CLA 2005-01-25 07:14:57 EST
Created attachment 17421 [details]
prototype

This patch contains partial code to compute hierachy and resolve types. The
algorithme to compute parameterized proposals is not correct.

The performance of is code is to bad to be usable inside code assist.
Comment 14 Tom Hofmann CLA 2005-01-25 11:08:45 EST
> The performance of is code is to bad to be usable inside code assist.

But would it be fast enough to use on a single proposal?

I think when completing types (and constructors), we should

- offer a list of generic type proposals ({LY<LT;>;, YY<T>}, which is cheap
- only resolve the possible member types upon applying a selected proposal. Very
often the concrete type cannot be known (as you pointed out in comment 9), so we
can simply run with an educated guess (use the bound, or use a type derived from
the LHS of the assignment, which is more expensive) and let the user change it.

I see the rationale behind having to complete the raw type name in case there
are static inner classes (comment 3), but frankly I think it is the 5% case -
most of the time I just want the type/constructor. So, ranking the raw types
less than the generic types is certainly a good idea.
Comment 15 Tom Hofmann CLA 2006-02-24 09:53:11 EST
I believe this is fixed (if you enable Java > Editor > Content Assist > Fill arguments).
Comment 16 David Audel CLA 2006-03-29 08:54:58 EST
Need more investigation to improve this behavior.

Deferred post 3.2
Comment 17 Eclipse Webmaster CLA 2009-08-30 02:34:26 EDT
As of now 'LATER' and 'REMIND' resolutions are no longer supported.
Please reopen this bug if it is still valid for you.
Comment 18 Dani Megert CLA 2014-01-23 11:08:28 EST
Got fixed along with 6930.

*** This bug has been marked as a duplicate of bug 6930 ***