Bug 44984 - [typing] Automatically optimize class imports
Summary: [typing] Automatically optimize class imports
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.3 M3   Edit
Assignee: David Audel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 48242 147504 (view as bug list)
Depends on:
Blocks: 107496
  Show dependency tree
 
Reported: 2003-10-15 20:24 EDT by Brett Kotch CLA
Modified: 2007-03-29 05:07 EDT (History)
16 users (show)

See Also:


Attachments
dealing with ambigous imports during auto import (5.55 KB, image/jpeg)
2004-12-03 08:38 EST, Andrew Freeman CLA
no flags Details
Proposed fix (186.03 KB, patch)
2006-10-12 05:18 EDT, David Audel CLA
no flags Details | Diff
Better fix (19.68 KB, patch)
2006-10-16 13:15 EDT, David Audel CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brett Kotch CLA 2003-10-15 20:24:18 EDT
Forget about quick fixes for importing classes, followed by a command to 
optimize the imports ... automaticlly optimize them all the time! 

If eclipse sees a class it hasn't seen before, and that class is a valid class 
name, import it. 

When saving, if there are classes that are no longer referenced ... delete 
them. 

But don't forget not to cause the text to jump (see bug 44959)

I put this at critical, because considering the critical flaw that exists in 
quick fixes (bug 44983) and that text jumps when an import is added, I am 
always tripping over myself with the way eclipse handles imports. 

The functionality serously slows me done. Something needs to be done.
Comment 1 Brett Kotch CLA 2003-10-15 20:37:35 EDT
Moved to major, doesn't fit defination of critical. 
Comment 2 Dani Megert CLA 2003-10-16 04:45:41 EDT
The reason why I use add import (or organize import) is just because most of the
time I cannot use code assist to enter method or a filed if the type is not yet
resolved. For me it would already be a great help if the type would be
automatically imported when I use code assist to get methods and fields, e.g.:

Iterator iter; // <-- not yet imported
iter.<Ctr+Space>
==> imports Iterator and suggest methods of interface Iterator
Comment 3 Dani Megert CLA 2004-09-23 03:30:54 EDT
*** Bug 74719 has been marked as a duplicate of this bug. ***
Comment 4 Dani Megert CLA 2004-09-23 03:31:35 EDT
*** Bug 74599 has been marked as a duplicate of this bug. ***
Comment 5 Andrew Freeman CLA 2004-12-03 08:38:12 EST
Created attachment 16327 [details]
dealing with ambigous imports during auto import

IntelliJ IDEA's automatic import feature displays a hint above the class when
it does not recognize the class and it the import is ambiguous.  See the
attachment for an example.
Comment 6 Dani Megert CLA 2005-08-22 05:33:03 EDT
*** Bug 107496 has been marked as a duplicate of this bug. ***
Comment 7 Dani Megert CLA 2005-10-03 08:51:59 EDT
*** Bug 111261 has been marked as a duplicate of this bug. ***
Comment 8 Dani Megert CLA 2006-05-24 10:20:40 EDT
I still often run into this and think it would be a good productivity feature to put this (see comment 2) into 3.3.

Here's Tom and I have in mind:
1. JDT Core code assist resolves the possible types of a field or local variable
2. for those types JDT Core creates the proposals and flags those proposal (this
   new CompletionProposal flag needs to be introduced)
3. JDT Text fully qualifies the type name of such proposals instead of simple
   name
4. if the user selects a proposal that has the new flag JDT Text adds the import 
   in addition to the proposal

Moving to JDT Core for comments.
Comment 9 Randy Hudson CLA 2006-05-24 11:05:26 EDT
> Iterator iter; // <-- not yet imported
> iter.<Ctr+Space>

CTRL+SHIFT+O works above, but not in this case:

TreeItem item;
item.joi(<CTRL+SHIFT+O>

So either the compiler needs to be even robust, or you need to be very smart about when you auto-invoke organize imports.
Comment 10 Dani Megert CLA 2006-05-24 11:09:27 EDT
I don't want to use Ctrl+Shift+O but directly Ctrl+Space (code assist)
Comment 11 Dani Megert CLA 2006-06-18 10:49:44 EDT
*** Bug 44627 has been marked as a duplicate of this bug. ***
Comment 12 Philipe Mulet CLA 2006-09-13 07:02:08 EDT
Plan is for David and Dani to agree on an API early M3 (too late for M2); and have the Core+Text features implemented by end of M3.
Comment 13 Philipe Mulet CLA 2006-09-13 07:03:47 EDT
btw - API should deal with param types as well (where multiple suggestions could arise for all involved types, e.g. Missing1<Missing2,Missing3>).

Also construction case should be handled: e.g. new Missing1(|<--codeassist
Comment 14 David Audel CLA 2006-09-14 09:08:12 EDT
To add the behavior described in comment 8 in JDT Core the following API should be added in CompletionProposal and CompletionRequestor.

public class CompletionProposal {

  ...

  /**
   * Returns the missing types signatures.
   * The proposal is valid only if these types are added to the imports of the compilation unit.
   * 
   * @return the missing types signatures, or <code>null</code> if none.
   * 
   * @since 3.3
   */
  public char[][] getMissingTypesSignatures()

  ...
}

public class CompletionRequestor {

  ...

  /**
   * Returns whether the proposals which required the addition of some missing types in imports are ignored.
   * 
   * @return <code>true</code> if the proposals which required the addition of some missing types
   * in imports are ignored by this requestor, and <code>false</code> if it is of interest
   * @see #setAreProposalsWithMissingTypesIgnored(boolean)
   * @see CompletionProposal#getMissingTypesSignatures()
   * 
   * @since 3.3
   */
  public boolean areProposalsWithMissingTypesIgnored()
  
  /**
   * Sets whether the proposals which required the addition of some missing types in imports are ignored.
   * 
   * @param ignore <code>true</code> if the proposals which required the addition of some missing types
   * in imports are ignored by this requestor, and <code>false</code> if it is of interest
   * @see #areProposalsWithMissingTypesIgnored()
   * @see CompletionProposal#getMissingTypesSignatures()
   */
  public void setAreProposalsWithMissingTypesIgnored(boolean ignore)

  ...

}

CompletionProposal#getMissingTypesSignatures() must return an array of types signature because several types can be missing in a parameterized types (as described in comment 13). Clients of the API must insert the returned types in the imports otherwise the proposal will add some compilation errors.

As these new proposals require a new action from clients (add import statements) to be correctly inserted then these proposals must be identifiable. I think the getMissingTypesSignatures() is enough to do that and there is no need to add a special flag to these proposals. If getMissingTypesSignatures() return null this is a normal proposal.

We also need to avoid to break old clients of the completion API. A 3.2 client won't be able to correclty insert these new proposals. I propose to filter these proposals unless the client explicitly ask to compute them with CompletionRequestor#setAreProposalsWithMissingTypesIgnored().
Another way would be to add new completion kinds like CompletionProposal#FIELD_REF_WITH_MISSING_TYPES and CompletionProposal#METHOD_REF_WITH_MISSING_TYPES.

dani, tom - what do you think about these API ?
Comment 15 Tom Hofmann CLA 2006-09-14 09:28:44 EDT
I like the proposal in comment 14.

Perhaps the enablement query and setter name could be improved?

boolean ignoreProposalsWithMissingTypes() instead of areProposalsWithMissingTypesIgnored()

void setIgnoreProposalsWithMissingTypes(boolean ignore) instead of setAreProposalsWithMissingTypesIgnored(boolean ignore)?
Comment 16 Dani Megert CLA 2006-09-14 11:12:30 EDT
+1 but different method names ;-)

setIgnoreProposalsWithMissingTypes(boolean)
isIgnoringProposalsWithMissingTypes()

Comment 17 Philipe Mulet CLA 2006-09-14 12:10:45 EDT
What about:

guessMissingTypes(boolean)
isGuessingMissingTypes()

?

(along the lines of: the shorter, the better)
Comment 18 Dani Megert CLA 2006-09-15 04:48:39 EDT
I'm not sure whether the last suggestion reflects what it's doing. David?
Comment 19 David Audel CLA 2006-10-02 07:14:06 EDT
We could also use a more general API.

public class CompletionRequestor {
  ...
  public boolean isIgnoringComplexProposals()
  public void setIgnoreComplexProposals(boolean ignore)
  ...
}
public class CompletionProposal {
  ...
  public CompletionProposal[] getRequiredCompletions()
  ...
}

CompletionRequestor#getRequiredCompletions() would return the list of other completions that must be applied to be able to apply the proposal.

e.g.
package p;
class X {
  void foo() {
    Vector v;
    v.add| // do code assist at | location
  }
}
A completion proposal would be the add() method at 'add' location with a required proposal of java.util.Vector at 'Vector' location.

Unlike my first proposal this API can solve the case of missing imports and can be reused in the future for other kinds of complex completion proposals.
And as required proposals are standard CompletionProposal, they can be apply in the source as a standard completion proposal.

What do you think about this more general approach ?



Reply to comment 18:
Indeed guessMissingTypes() doesn't reflects what it's doing. The requestor doesn't guess something, it only accept completion results. But isIgnoringProposalsWithMissingTypes() is more correct but it would be better to find a smaller name.
Comment 20 Dani Megert CLA 2006-10-11 05:57:23 EDT
Such a 'complex' proposal could have any kind of required proposals. Supporting this for a client means a lot of work (e.g. computing the correct insert locations) and I'm not even sure at this point whether this can be correctly done since a completion participant could construct any wild proposal with any kinds of required proposals.

JDT Text does not have enough resources to support the 'complex' API. Please stick to the previously proposed solution.
Comment 21 David Audel CLA 2006-10-11 12:13:06 EDT
We can keep the general API and specify that only a limited set of results can be returned.
We also can add a filter by completion instead of the general filter CompletionProposal#isIgnoringComplexProposals().

public class CompletionProposal {

  ...

  /**
   * Returns the required completion proposals.
   * The proposal can be apply only if these required completion proposals are also applied.
   * If the required proposal aren't applied the completion could create complations problems.
   * 
   * <p>
   * This field is available for the following kinds of
   * completion proposals:
   * <ul>
   * 	<li><code>FIELD_REF</code></li>
   * 	<li><code>METHOD_REF</code>/li>
   * </ul>
   * </p>
   * <p>
   * A required completion proposal can is a completion proposal of one of the following kinds:
   * <ul>
   *  <li><code>TYPE_REF</code></li>
   * </ul>
   * Other kinds of required proposals will be returned in the future, therefore clients of this
   * API must allow with {@link CompletionRequestor#setAllowsRequiredProposals(int, boolean)} 
   * only kinds which are in this list to avoid unexpected results in the future.
   * </p>
   * <p>
   * A required completion proposal cannot have required completion proposals.
   * </p>
   * 
   * @return the required completion proposals, or <code>null</code> if none.
   * 
   * @see CompletionRequestor#setAllowsRequiredProposals(int, boolean)
   * 
   * @since 3.3
   */
  public CompletionProposal[] getRequiredProposals()

  ...

}

public class CompletionRequestor {

  ...

  /**
   * Returns whether a proposal with a required proposal
   * of the given kind is allowed.
   * 
   * @param completionProposalKind one of the kind constants declared
   * on <code>CompletionProposal</code>
   * @return <code>true</code> if a proposal with a required proposal
   * of the given kind is allowed by this requestor, and <code>false</code> 
   * if it isn't of interest.
   * <p>
   * By default, all kinds of required proposals aren't allowed.
   * </p>
   * @see #setAllowsRequiredProposals(int, boolean)
   * @see CompletionProposal#getKind()
   * @see CompletionProposal#getRequiredProposals()
   * 
   * @since 3.3
   */
  public boolean isAllowingRequiredProposals(int completionProposalKind) 
	
  /**
   * Sets whether a proposal with a required proposal
   * of the given kind is allowed.
   * 
   * @param completionProposalKind one of the kind constants declared
   * on <code>CompletionProposal</code>
   * @param allow <code>true</code> if a proposal with a required proposal
   * of the given kind is allowed by this requestor, and <code>false</code> 
   * if it isn't of interest
   * @see #isAllowingRequiredProposals(int)
   * @see CompletionProposal#getKind()
   * @see CompletionProposal#getRequiredProposals()
   * 
   * @since 3.3
   */
  public void setAllowsRequiredProposals(int completionProposalKind, boolean allow)

  ...

}

With this API, JDT/Text only have to support FIELD_REF and METHOD_REF proposals with TYPE_REF required proposals. The support for other kinds of required proposal can be added later in JDT/Core and JDT/Text.

Comment 22 Dani Megert CLA 2006-10-11 12:33:52 EDT
Comment 21 reflects the result of a longer chat between David and myself. I therefore agree on this API and will hopefully be able to fix bug 107496 with it.
Comment 23 David Audel CLA 2006-10-12 05:18:11 EDT
Created attachment 51837 [details]
Proposed fix
Comment 24 David Audel CLA 2006-10-12 05:19:01 EDT
Fix released for 3.3 M3

Test added
  CompletionWithMissingTypesTests#test0001() -> test0033()
  CompletionWithMissingTypesTests2#test0001() -> test0002()
  CompletionWithMissingTypesTests_1_5#test0001() -> test0011()

Comment 25 Dani Megert CLA 2006-10-16 10:22:46 EDT
setAllowsRequiredProposals(...) should also mention which kinds are currently supported.
Comment 26 David Audel CLA 2006-10-16 13:14:46 EDT
After a discussion with Daniel, we concluded that the API must be able to filter proposals by the kind of the required proposal AND the kind of the proposal.

The CompletionRequestor API must be:

public class CompletionRequestor {

	...

	/**
	 * Returns whether a proposal of a given kind with a required proposal
	 * of the given kind is allowed.
	 * 
	 * @param proposalKind one of the kind constants declared
	 * @param requiredProposalKind)one of the kind constants declared
	 * on <code>CompletionProposal</code>
	 * @return <code>true</code> if a proposal of a given kind with a required proposal
	 * of the given kind is allowed by this requestor, and <code>false</code> 
	 * if it isn't of interest.
	 * <p>
	 * By default, all kinds of required proposals aren't allowed.
	 * </p>
	 * @see #setAllowsRequiredProposals(int, int, boolean)
	 * @see CompletionProposal#getKind()
	 * @see CompletionProposal#getRequiredProposals()
	 * 
	 * @since 3.3
	 */
	public boolean isAllowingRequiredProposals(int proposalKind, int requiredProposalKind)

	/**
	 * Sets whether a proposal of a given kind with a required proposal
	 * of the given kind is allowed.
	 * 
	 * Currenlty only a subset of kinds support required proposals. To see what combinations
	 * are supported you must look at {@link CompletionProposal#getRequiredProposals()}
	 * documentation.
	 * 
	 * @param proposalKind one of the kind constants declared
	 * @param requiredProposalKind)one of the kind constants declared
	 * on <code>CompletionProposal</code>
	 * @param allow <code>true</code> if a proposal of a given kind with a required proposal
	 * of the given kind is allowed by this requestor, and <code>false</code> 
	 * if it isn't of interest
	 * @see #isAllowingRequiredProposals(int, int)
	 * @see CompletionProposal#getKind()
	 * @see CompletionProposal#getRequiredProposals()
	 * 
	 * @since 3.3
	 */
	public void setAllowsRequiredProposals(int proposalKind, int requiredProposalKind)boolean allow)

	...

}
Comment 27 David Audel CLA 2006-10-16 13:15:27 EDT
Created attachment 52045 [details]
Better fix
Comment 28 David Audel CLA 2006-10-16 13:18:56 EDT
Released better fix.

The fix contains also the modification suggested by comment 25.
Comment 29 Frederic Fusier CLA 2006-10-30 11:10:17 EST
(In reply to comment #4)
> *** Bug 74599 has been marked as a duplicate of this bug. ***
> 
Bug 74599 has been reopened as this is not a duplicate.
Comment 30 Frederic Fusier CLA 2006-10-30 11:13:58 EST
(In reply to comment #6)
> *** Bug 107496 has been marked as a duplicate of this bug. ***
> 
Not a duplicate and has been treated separately by JDT/UI (see bug 107496 comment 2)
Comment 31 Frederic Fusier CLA 2006-10-30 11:36:18 EST
*** Bug 48242 has been marked as a duplicate of this bug. ***
Comment 32 Frederic Fusier CLA 2006-10-30 11:40:11 EST
*** Bug 147504 has been marked as a duplicate of this bug. ***
Comment 33 Frederic Fusier CLA 2006-10-30 11:42:59 EST
Verified for 3.3 M3 using build I20061030-0010.