Skip to content

Commit

Permalink
organize imports with the asterisk (*) wildcard character
Browse files Browse the repository at this point in the history
Signed-off-by: Snjezana Peco <[email protected]>
  • Loading branch information
snjeza authored and fbricon committed Apr 15, 2020
1 parent 71805de commit a60afc0
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.internal.corext.template.java.SignatureUtil;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;

/**
* Method implementations extracted from JDT UI. Mostly from
Expand All @@ -41,7 +42,6 @@
public class TypeProposalUtils {

private static final String PACKAGE_INFO_JAVA = "package-info.java"; //$NON-NLS-1$
private static final int IMPORTS_THRESHOLD = 99;

static void createName(ITypeBinding type, boolean includePackage,
List<String> list) {
Expand Down Expand Up @@ -163,10 +163,10 @@ static boolean isPackageInfo(ICompilationUnit cu) {
static ImportRewrite createImportRewrite(ICompilationUnit compilationUnit) {
try {
ImportRewrite rewrite = ImportRewrite.create(compilationUnit, true);
String[] importOrder = JavaLanguageServerPlugin.getPreferencesManager() == null ? new String[0] : JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getImportOrder();
rewrite.setImportOrder(importOrder);
rewrite.setOnDemandImportThreshold(IMPORTS_THRESHOLD);
rewrite.setStaticOnDemandImportThreshold(IMPORTS_THRESHOLD);
Preferences preferences = JavaLanguageServerPlugin.getPreferencesManager() == null ? new Preferences() : JavaLanguageServerPlugin.getPreferencesManager().getPreferences();
rewrite.setImportOrder(preferences.getImportOrder());
rewrite.setOnDemandImportThreshold(preferences.getImportOnDemandThreshold());
rewrite.setStaticOnDemandImportThreshold(preferences.getStaticImportOnDemandThreshold());
return rewrite;
} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,9 @@
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
Expand Down Expand Up @@ -93,8 +89,6 @@ public static void initialize() {
IEclipsePreferences defEclipsePrefs = DefaultScope.INSTANCE.getNode(IConstants.PLUGIN_ID);
defEclipsePrefs.put("org.eclipse.jdt.ui.typefilter.enabled", "");
defEclipsePrefs.put(CodeStyleConfiguration.ORGIMPORTS_IMPORTORDER, String.join(";", Preferences.JAVA_IMPORT_ORDER_DEFAULT));
defEclipsePrefs.put(CodeStyleConfiguration.ORGIMPORTS_ONDEMANDTHRESHOLD, "99");
defEclipsePrefs.put(CodeStyleConfiguration.ORGIMPORTS_STATIC_ONDEMANDTHRESHOLD, "99");
defEclipsePrefs.put(MembersOrderPreferenceCacheCommon.APPEARANCE_MEMBER_SORT_ORDER, "T,SF,SI,SM,F,I,C,M"); //$NON-NLS-1$

defEclipsePrefs.put(StubUtility.CODEGEN_KEYWORD_THIS, Boolean.FALSE.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import org.eclipse.core.internal.resources.PreferenceInitializer;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.manipulation.CodeStyleConfiguration;
Expand Down Expand Up @@ -263,6 +264,30 @@ public class Preferences {
*/
public static final String MEMBER_SORT_ORDER = "java.memberSortOrder"; //$NON-NLS-1$

/**
* A named preference that specifies the number of imports added before a
* star-import declaration is used.
* <p>
* Value is of type <code>Integer</code>: positive value specifying the number
* of non star-import is used
* </p>
*/
public static final String IMPORTS_ONDEMANDTHRESHOLD = "java.sources.organizeImports.starThreshold"; //$NON-NLS-1$

/**
* A named preference that specifies the number of static imports added before a
* star-import declaration is used.
* <p>
* Value is of type <code>Integer</code>: positive value specifying the number
* of non star-import is used
* </p>
*/
public static final String IMPORTS_STATIC_ONDEMANDTHRESHOLD = "java.sources.organizeImports.staticStarThreshold"; //$NON-NLS-1$

public static final int IMPORTS_ONDEMANDTHRESHOLD_DEFAULT = 99;

public static final int IMPORTS_STATIC_ONDEMANDTHRESHOLD_DEFAULT = 99;

/**
* Preference key for the id(s) of the preferred content provider(s).
*/
Expand Down Expand Up @@ -399,6 +424,8 @@ public class Preferences {
private Collection<IPath> triggerFiles;
private int parallelBuildsCount;
private int maxCompletionResults;
private int importOnDemandThreshold;
private int staticImportOnDemandThreshold;
private Set<RuntimeEnvironment> runtimes = new HashSet<>();

static {
Expand Down Expand Up @@ -565,6 +592,8 @@ public Preferences() {
filteredTypes = JAVA_COMPLETION_FILTERED_TYPES_DEFAULT;
parallelBuildsCount = PreferenceInitializer.PREF_MAX_CONCURRENT_BUILDS_DEFAULT;
maxCompletionResults = JAVA_COMPLETION_MAX_RESULTS_DEFAULT;
importOnDemandThreshold = IMPORTS_ONDEMANDTHRESHOLD_DEFAULT;
staticImportOnDemandThreshold = IMPORTS_STATIC_ONDEMANDTHRESHOLD_DEFAULT;
referencedLibraries = JAVA_PROJECT_REFERENCED_LIBRARIES_DEFAULT;
}

Expand Down Expand Up @@ -736,6 +765,12 @@ public static Preferences createFrom(Map<String, Object> configuration) {
int maxCompletions = getInt(configuration, JAVA_COMPLETION_MAX_RESULTS_KEY, JAVA_COMPLETION_MAX_RESULTS_DEFAULT);
prefs.setMaxCompletionResults(maxCompletions);

int onDemandThreshold = getInt(configuration, IMPORTS_ONDEMANDTHRESHOLD, IMPORTS_ONDEMANDTHRESHOLD_DEFAULT);
prefs.setImportOnDemandThreshold(onDemandThreshold);

int staticOnDemandThreshold = getInt(configuration, IMPORTS_STATIC_ONDEMANDTHRESHOLD, IMPORTS_STATIC_ONDEMANDTHRESHOLD_DEFAULT);
prefs.setStaticImportOnDemandThreshold(staticOnDemandThreshold);

List<?> runtimeList = getList(configuration, JAVA_CONFIGURATION_RUNTIMES, JAVA_IMPORT_ORDER_DEFAULT);
Set<RuntimeEnvironment> runtimes = new HashSet<>();
boolean[] hasDefault = { false };
Expand Down Expand Up @@ -1302,4 +1337,34 @@ public Preferences setRuntimes(Set<RuntimeEnvironment> runtimes) {
this.runtimes = runtimes;
return this;
}

public int getImportOnDemandThreshold() {
return importOnDemandThreshold;
}

public Preferences setImportOnDemandThreshold(int importOnDemandThreshold) {
if (importOnDemandThreshold < 0) {
this.importOnDemandThreshold = IMPORTS_ONDEMANDTHRESHOLD_DEFAULT;
} else {
this.importOnDemandThreshold = importOnDemandThreshold;
}
IEclipsePreferences defEclipsePrefs = DefaultScope.INSTANCE.getNode(IConstants.PLUGIN_ID);
defEclipsePrefs.put(CodeStyleConfiguration.ORGIMPORTS_ONDEMANDTHRESHOLD, String.valueOf(this.importOnDemandThreshold));
return this;
}

public int getStaticImportOnDemandThreshold() {
return staticImportOnDemandThreshold;
}

public Preferences setStaticImportOnDemandThreshold(int staticImportOnDemandThreshold) {
if (staticImportOnDemandThreshold < 0) {
this.staticImportOnDemandThreshold = IMPORTS_STATIC_ONDEMANDTHRESHOLD_DEFAULT;
} else {
this.staticImportOnDemandThreshold = staticImportOnDemandThreshold;
}
IEclipsePreferences defEclipsePrefs = DefaultScope.INSTANCE.getNode(IConstants.PLUGIN_ID);
defEclipsePrefs.put(CodeStyleConfiguration.ORGIMPORTS_STATIC_ONDEMANDTHRESHOLD, String.valueOf(this.staticImportOnDemandThreshold));
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,86 @@ public void testOrganizeImportsInProject() throws CoreException, BadLocationExce
assertEquals(buf.toString(), getOrganizeImportResult(cu2, rootEdit));
}

@Test
public void testOrganizeImportsOnDemandThreshold() throws Exception {
int onDemandTreshold = preferenceManager.getPreferences().getImportOnDemandThreshold();
try {
preferenceManager.getPreferences().setImportOnDemandThreshold(2);
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import java.util.HashMap;\n");
buf.append("import java.util.ArrayList;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" ArrayList list = new ArrayList();\n");
buf.append(" HashMap<String, String> map = new HashMap<String, String>();\n");
buf.append(" }\n");
buf.append("}\n");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);
buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import java.util.*;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" ArrayList list = new ArrayList();\n");
buf.append(" HashMap<String, String> map = new HashMap<String, String>();\n");
buf.append(" }\n");
buf.append("}\n");
WorkspaceEdit rootEdit = new WorkspaceEdit();
command.organizeImportsInCompilationUnit(cu, rootEdit);
assertEquals(buf.toString(), getOrganizeImportResult(cu, rootEdit));
} finally {
preferenceManager.getPreferences().setImportOnDemandThreshold(onDemandTreshold);
}
}

@Test
public void testOrganizeImportsStaticOnDemandThreshold() throws Exception {
int staticOnDemandTreshold = preferenceManager.getPreferences().getStaticImportOnDemandThreshold();
try {
preferenceManager.getPreferences().setStaticImportOnDemandThreshold(2);
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import static java.lang.Math.pow;\n");
buf.append("import static java.lang.Math.sqrt;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" double d1 = sqrt(4);\n");
buf.append(" double d2 = pow(2, 2);\n");
buf.append(" }\n");
buf.append("}\n");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);
buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import static java.lang.Math.*;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" double d1 = sqrt(4);\n");
buf.append(" double d2 = pow(2, 2);\n");
buf.append(" }\n");
buf.append("}\n");
WorkspaceEdit rootEdit = new WorkspaceEdit();
command.organizeImportsInCompilationUnit(cu, rootEdit);
assertEquals(buf.toString(), getOrganizeImportResult(cu, rootEdit));
} finally {
preferenceManager.getPreferences().setStaticImportOnDemandThreshold(staticOnDemandTreshold);
}
}

private String getOrganizeImportResult(ICompilationUnit cu, WorkspaceEdit we) throws BadLocationException, CoreException {
List<TextEdit> change = we.getChanges().get(JDTUtils.toURI(cu));
if (change == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,84 @@ public void testOrganizeImportsSort() throws Exception {
assertCodeActions(cu, e1);
}

@Test
public void testOrganizeImportsOnDemandThreshold() throws Exception {
int onDemandTreshold = preferenceManager.getPreferences().getImportOnDemandThreshold();
try {
preferenceManager.getPreferences().setImportOnDemandThreshold(2);
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import java.util.HashMap;\n");
buf.append("import java.util.ArrayList;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" ArrayList list = new ArrayList();\n");
buf.append(" HashMap<String, String> map = new HashMap<String, String>();\n");
buf.append(" }\n");
buf.append("}\n");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);
buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import java.util.*;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" ArrayList list = new ArrayList();\n");
buf.append(" HashMap<String, String> map = new HashMap<String, String>();\n");
buf.append(" }\n");
buf.append("}\n");
Expected e1 = new Expected("Organize imports", buf.toString());
assertCodeActions(cu, e1);
} finally {
preferenceManager.getPreferences().setImportOnDemandThreshold(onDemandTreshold);
}
}

@Test
public void testOrganizeImportsStaticOnDemandThreshold() throws Exception {
int staticOnDemandTreshold = preferenceManager.getPreferences().getStaticImportOnDemandThreshold();
try {
preferenceManager.getPreferences().setStaticImportOnDemandThreshold(2);
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import static java.lang.Math.pow;\n");
buf.append("import static java.lang.Math.sqrt;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" double d1 = sqrt(4);\n");
buf.append(" double d2 = pow(2, 2);\n");
buf.append(" }\n");
buf.append("}\n");
ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);
buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("\n");
buf.append("import static java.lang.Math.*;\n");
buf.append("\n");
buf.append("public class E {\n");
buf.append("\n");
buf.append(" public E() {\n");
buf.append(" double d1 = sqrt(4);\n");
buf.append(" double d2 = pow(2, 2);\n");
buf.append(" }\n");
buf.append("}\n");
Expected e1 = new Expected("Organize imports", buf.toString());
assertCodeActions(cu, e1);
} finally {
preferenceManager.getPreferences().setStaticImportOnDemandThreshold(staticOnDemandTreshold);
}
}

@Test
public void testOrganizeImportsAutomaticallyResolve() throws Exception {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -2616,6 +2617,58 @@ public void testStaticImports2() throws Exception {
}
}

@Test
public void testStarImports() throws Exception {
List<String> favorites = new ArrayList<>();
favorites.add("java.lang.Math.*");
Preferences prefs = PreferenceManager.getPrefs(null);
List<String> oldFavorites = Arrays.asList(prefs.getJavaCompletionFavoriteMembers());
int onDemandThreshold = prefs.getImportOnDemandThreshold();
int staticOnDemandThreshold = prefs.getStaticImportOnDemandThreshold();
prefs.setJavaCompletionFavoriteMembers(favorites);
prefs.setImportOnDemandThreshold(2);
prefs.setStaticImportOnDemandThreshold(2);
try {
ICompilationUnit unit = getWorkingCopy("src/test1/B.java",
//@formatter:off
"package test1;\n" +
"import static java.lang.Math.sqrt;\n" +
"import java.util.List;\n" +
"public class B {\n" +
" List<String> list = new ArrayL\n" +
" public static void main(String[] args) {\n" +
" double d1 = sqrt(4);\n" +
" double d2 = abs\n" +
" }\n" +
"}\n");
//@formatter:on
int[] loc = findCompletionLocation(unit, "new ArrayL");
CompletionList list = server.completion(JsonMessageHelper.getParams(createCompletionRequest(unit, loc[0], loc[1]))).join().getRight();
assertNotNull(list);
assertTrue(list.getItems().size() > 0);
CompletionItem item = list.getItems().stream().filter(i -> "ArrayList()".equals(i.getLabel())).collect(Collectors.toList()).get(0);
assertNotNull(item);
List<TextEdit> textEdits = item.getAdditionalTextEdits();
assertEquals(1, textEdits.size());
TextEdit textEdit = textEdits.get(0);
assertEquals("\n\nimport java.util.*;", textEdit.getNewText());
loc = findCompletionLocation(unit, "= abs");
list = server.completion(JsonMessageHelper.getParams(createCompletionRequest(unit, loc[0], loc[1]))).join().getRight();
assertNotNull(list);
assertTrue(list.getItems().size() > 0);
item = list.getItems().stream().filter(i -> i.getLabel().startsWith("abs(double")).collect(Collectors.toList()).get(0);
assertNotNull(item);
textEdits = item.getAdditionalTextEdits();
assertEquals(1, textEdits.size());
textEdit = textEdits.get(0);
assertEquals("import static java.lang.Math.*;\n\n", textEdit.getNewText());
} finally {
prefs.setJavaCompletionFavoriteMembers(oldFavorites);
prefs.setImportOnDemandThreshold(onDemandThreshold);
prefs.setStaticImportOnDemandThreshold(staticOnDemandThreshold);
}
}

@Test
public void testCompletion_linksInMarkdown() throws JavaModelException{
ClientPreferences mockCapabilies = Mockito.mock(ClientPreferences.class);
Expand Down

0 comments on commit a60afc0

Please sign in to comment.