Bug 152123 - [1.5][assist] Code assist for references that require static imports
Summary: [1.5][assist] Code assist for references that require static imports
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 enhancement with 1 vote (vote)
Target Milestone: 3.3 M5   Edit
Assignee: David Audel CLA
QA Contact:
URL:
Whiteboard:
Keywords: api
Depends on:
Blocks: 140290 167387
  Show dependency tree
 
Reported: 2006-07-28 06:57 EDT by Martin Aeschlimann CLA
Modified: 2007-03-29 05:07 EDT (History)
5 users (show)

See Also:


Attachments
Proposed fix for jdtcore (67.55 KB, patch)
2006-12-08 09:47 EST, David Audel CLA
no flags Details | Diff
Complementary fix (102.32 KB, patch)
2007-01-11 10:13 EST, David Audel CLA
no flags Details | Diff
Better complementary fix (119.06 KB, patch)
2007-01-12 12:40 EST, 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 Martin Aeschlimann CLA 2006-07-28 06:57:13 EDT
3.2

In JUnit 4 it is common to access 'assertEquals', 'assertTrue'... with static imports.
It is currently very annoying to enter such method invocations, as we don't offer code assist until the static import has been added.

Searching the project for all static members is likely too costly and will result in a large number of proposals.
The suggestion is to have a (project) preference where the user specifies which members are his favorites for static imports. Code assist only needs to consider this list.

As the list of members would be very long and hard to maintain, it is probably better to (also) be able to specify declaring types, for example: 'java.lang.Math.*;org.junit.Assert.*'

I believe that it's better for jdt.core to offer this functionality:
- Context is required to know when it's feasible to complete a static reference. At the moment we don't have such context in JDT UI nor a special callback for method or field invocations
- The performance to evaluate the static members and their fully resolved signatures is important. It is most likely more efficient for jdt.core to parse some extra bindings in the already created type environment.
- Clients of the headless jdt.core infrastructure are surely also interested in completion of references with static imports
Comment 1 David Audel CLA 2006-12-01 06:59:23 EST
Here is a first proposal to solve this bug as suggested. I already discussed of this proposal with Daniel.

We must define an API to give the list of imports to the completion engine. We should add this API in the CompletionRequestor.

public class CompletionRequestor {
   ...
   /**
    * Set the favorites imports. Each favorite import is a qualified
    * reference as it can be seen in an import statement.<br>
    * e.g. {"java.util.Arrays"}
    * A reference can be an on demand reference.
    * e.g. {"java.util.Arrays.*"}
    * 
    * @param favoriteImports
    * 
    * @since 3.3
    */
   public void setFavoriteImports(String[] favoriteImports) {...}
   ...
}

Then the client can specify the list of imports by calling 'setFavoriteImports' and the completion engine get this list by calling
'getFavoriteImports'.

Another API is required to return results that use this list of favorite imports.

A possibility is to use existing proposal kinds and return a fully qualified reference as proposal.
Then the client could directly insert the completion string or decide to add an import instead.
The client could identify this kind of proposal because the completion would be qualified and would be static (getFlags())
This is similar to what is currently done for type reference completion in JDT/Text.

e.g.

package p;
public class X {
  public static field;
}

package q;
public class y {
  void foo() {
    fie| // complete at |
  }
}

If "p.X.*" is a favorite import the proposal would be 

   CompletionProposal {
     kind=FIELD_REF
     completion=p.X.field
     declarationSignature=Lp.X;
     signature=I
     name=field
     flags=static
   }

The client can choose to insert
'p.X.field'
or
'X.field' and an import of 'p.X'
or
'field' and a static import of 'p.X.*'


Currently i try to implements these API.


If we found that these API aren't the good way to solve the problem we could use the CompletionProposal#getRequiredProposals() API instead. The main proposal would be a field reference with an import proposal as a required proposal (import proposal would be a new completion kind).


Comment 2 David Audel CLA 2006-12-08 09:47:40 EST
Created attachment 55310 [details]
Proposed fix for jdtcore
Comment 3 David Audel CLA 2006-12-08 09:57:14 EST
The API proposed in the fix are:

/**
 * Returns the favorites references which are used to compute some completion proposals.
 * <p>
 * A favorite reference is a qualified reference as it can be seen in an import statement.<br>
 * e.g. <code>{"java.util.Arrays"}</code><br>
 * It can be an on demand reference.<br>
 * e.g. <code>{"java.util.Arrays.*"}</code>
 * It can be a reference to a static method or field (as in a static import)<br>
 * e.g. <code>{"java.util.Arrays.equals"}</code>
 * </p>
 *
 * @return favorites imports
 * 
 * @since 3.3
 */
public String[] getFavoriteReferences() {...}

/**
 * Set the favorites references which will be used to compute some completion proposals.
 * A favorite reference is a qualified reference as it can be seen in an import statement.<br>
 * 
 * @param favoriteImports
 * 
 * @see #getFavoriteReferences()
 * 
 * @since 3.3
 */
public void setFavoriteReferences(String[] favoriteImports) {...}



I named the API getFavoriteReferences() instead of getFavoriteImports() because jdtcore don't use it as import but as favorite qualified references. With this fix the client can compute import but jdtcore only propose qualified references.

The completion proposals are as described in comment 1, so no new API are used to return result.
Comment 4 David Audel CLA 2006-12-08 10:08:45 EST
I released the fix.

Some tests are added
  CompletionTests#testFavoriteImports001() -> testFavoritesImports022()
  CompletionTests_1_5#testFavoriteImports001() -> testFavoritesImports022()

I don't close this bug as fixed. We need to check this fix with jdttext before.
Currently the code has no effect because nobody call setFavoriteReferences().
Comment 5 Dani Megert CLA 2006-12-11 02:47:46 EST
I filed bug 167387 to track the JDT Text side.
Comment 6 David Audel CLA 2006-12-13 09:00:09 EST
Daniel - I would like to close this bug and you would open new bug reports if you find issues.
Are you agree to close this bug as fixed ?
Comment 7 Dani Megert CLA 2006-12-13 09:22:51 EST
Fine by me.
Comment 8 David Audel CLA 2007-01-11 10:11:58 EST
After a discussion with Daniel, we conclude that the released API isn't easy to use by client. So we will use the CompletionProposal#getRequiredProposals() API instead and will add new kinds of completion proposal to propose imports.

The added would be

public class CompletionProposal {
   ...
   /**
    * Completion is an import of reference to a field.
    * <p>
    * The following additional context information is available
    * for this kind of completion proposal at little extra cost:
    * <ul>
    * <li>{@link #getDeclarationSignature()} -
    * the type signature of the type that declares the field that is imported
    * </li>
    * <li>{@link #getFlags()} -
    * the modifiers flags (including ACC_ENUM) of the field that is imported
    * </li>
    * <li>{@link #getName()} -
    * the simple name of the field that is imported
    * </li>
    * <li>{@link #getSignature()} -
    * the type signature of the field's type (as opposed to the
    * signature of the type in which the referenced field
    * is declared)
    * </li>
    * <li>{@link #getAdditionalFlags()} -
    * the completion flags (including ComletionFlags.StaticImport)
    * of the prosposed import
    * </li>
    * </ul>
    * </p>
    * 
    * @see #getKind()
    * 
    * @since 3.3
    */
   public static final int FIELD_IMPORT;
	
   /**
    * Completion is an import of reference to a static method.
    * <p>
    * The following additional context information is available
    * for this kind of completion proposal at little extra cost:
    * <ul>
    * <li>{@link #getDeclarationSignature()} -
    * the type signature of the type that declares the method that is imported
    * </li>
    * <li>{@link #getFlags()} -
    * the modifiers flags of the method that is imported
    * </li>
    * <li>{@link #getName()} -
    * the simple name of the method that is imported
    * </li>
    * <li>{@link #getSignature()} -
    * the method signature of the method that is imported
    * </li>
    * <li>{@link #getAdditionalFlags()} -
    * the completion flags (including ComletionFlags.StaticImport)
    * of the prosposed import
    * </li>
    * </ul>
    * </p>
    * 
    * @see #getKind()
    * 
    * @since 3.3
    */
   public static final int METHOD_IMPORT;
	
   /**
    * Completion is an import of reference to a type.
    * Only reference to reference types are allowed.
    * <p>
    * The following additional context information is available
    * for this kind of completion proposal at little extra cost:
    * <ul>
    * <li>{@link #getDeclarationSignature()} -
    * the dot-based package name of the package that contains
    * the type that is imported
    * </li>
    * <li>{@link #getSignature()} -
    * the type signature of the type that is imported
    * </li>
    * <li>{@link #getFlags()} -
    * the modifiers flags (including Flags.AccInterface, AccEnum,
    * and AccAnnotation) of the type that is imported
    * </li>
    * <li>{@link #getAdditionalFlags()} -
    * the completion flags (including ComletionFlags.StaticImport)
    * of the prosposed import
    * </li>
    * </ul>
    * </p>
    * 
    * @see #getKind()
    * 
    * @since 3.3
    */
   public static final int TYPE_IMPORT;


   /**
    * Returns the completion flags relevant in the context, or
    * <code>CompletionFlags.Default</code> if none.
    * <p>
    * This field is available for the following kinds of
    * completion proposals:
    * <ul>
    * <li><code>FIELD_IMPORT</code> - completion flags
    * of the attribute that is referenced. Completion flags for
    * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
    * <li><code>METHOD_IMPORT</code> - completion flags
    * of the attribute that is referenced. Completion flags for
    * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
    * <li><code>TYPE_IMPORT</code> - completion flags
    * of the attribute that is referenced. Completion flags for
    * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
    * </ul>
    * For other kinds of completion proposals, this method returns
    * <code>CompletionFlags.Default</code>.
    * </p>
    * 
    * @return the completion flags, or
    * <code>CompletionFlags.Default</code> if none
    * @see CompletionFlags
    * 
    * @since 3.3
    */
   public int getAdditionalFlags() {...}
   ...
}

and

public final class CompletionFlags {
   /**
    * Constant representing the absence of any flag
    */
   public static final int Default = 0x0000;
	
   /**
    * Constant representing a static import
    */
   public static final int StaticImport = 0x0001;

   /**
    * Returns whether the given integer includes the {@link #StaticImport} flag.
    *
    * @param flags the flags
    * @return <code>true</code> if the {@link #StaticImport} flag is included
    */
   public static boolean isStaticImport(int flags) {...}
}


With this test case

class Test {
  void foo(){
    sort| // do completion at |
  }
}

if a favorite is "java.util.Arrays.*" then a proposal would be 'sort()' with a required proposal 'import static java.util.Arrays.sort;'.
If the compliance level is 1.4 the proposal would be 'Arrays.sort()' with a required proposal 'import java.util.Arrays;'.
Comment 9 David Audel CLA 2007-01-11 10:13:40 EST
Created attachment 56767 [details]
Complementary fix
Comment 10 David Audel CLA 2007-01-12 12:40:48 EST
Created attachment 56841 [details]
Better complementary fix

This patch also add an option to not propose static imports even if compliance is 5.0.
This option is JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS and his default value is ENABLED.
Comment 11 David Audel CLA 2007-01-12 13:07:54 EST
The complementary fix is released.
I considered that this bug is fixed, if you find bugs in this area please open new bug report.

Released for 3.3M5.
Comment 12 Frederic Fusier CLA 2007-02-05 09:30:21 EST
Verified for 3.3 M5 using warm-up build I20070205-0009.