From 003fa4a4170f26128f608932145cdd451d19b2d1 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Thu, 12 Oct 2023 16:05:57 +0800 Subject: [PATCH 1/4] Automatically add the existing static imports in user code as the favorite static members Signed-off-by: Jinbo Wang --- .../CompletionProposalUtils.java | 31 +++++++++++++++++++ .../BaseDocumentLifeCycleHandler.java | 17 +++------- .../internal/handlers/CompletionHandler.java | 2 ++ .../internal/preferences/Preferences.java | 8 ++++- .../handlers/CompletionHandlerTest.java | 28 +++++++++++++++++ 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java index ff62a0bee6..7c21683653 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java @@ -14,8 +14,13 @@ package org.eclipse.jdt.ls.core.internal.contentassist; import java.util.Arrays; +import java.util.List; import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.ls.core.internal.preferences.Preferences; public class CompletionProposalUtils { @@ -62,4 +67,30 @@ public static CompletionProposal getRequiredTypeProposal(CompletionProposal prop return requiredProposal; } + + public static void addStaticImportsAsFavoriteImports(ICompilationUnit unit) { + try { + List staticImports = Arrays.stream(unit.getImports()) + .filter(t -> { + try { + return Flags.isStatic(t.getFlags()); + } catch (JavaModelException e) { + // ignore + } + return false;}) + .map(t -> t.getElementName()) + .map(t -> { + int lastDot = t.lastIndexOf("."); + if (lastDot > -1) { + return t.substring(0, lastDot) + ".*"; + } + return t; + }).toList(); + if (!staticImports.isEmpty()) { + Preferences.DISCOVERED_STATIC_IMPORTS.addAll(staticImports); + } + } catch (JavaModelException e) { + // ignore + } + } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java index 77c880ac18..b76663961e 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java @@ -63,6 +63,7 @@ import org.eclipse.jdt.ls.core.internal.JobHelpers; import org.eclipse.jdt.ls.core.internal.MovingAverage; import org.eclipse.jdt.ls.core.internal.ProjectUtils; +import org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalUtils; import org.eclipse.jdt.ls.core.internal.corrections.DiagnosticsHelper; import org.eclipse.jdt.ls.core.internal.managers.InvisibleProjectImporter; import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager; @@ -334,12 +335,7 @@ public void didOpen(DidOpenTextDocumentParams params) { handleOpen(params); } else { // Open an unmanaged file, use a workspace runnable to mount it to default project or invisible project. try { - ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { - @Override - public void run(IProgressMonitor monitor) throws CoreException { - handleOpen(params); - } - }, null, IWorkspace.AVOID_UPDATE, new NullProgressMonitor()); + ResourcesPlugin.getWorkspace().run((IWorkspaceRunnable) monitor -> handleOpen(params), null, IWorkspace.AVOID_UPDATE, new NullProgressMonitor()); } catch (CoreException e) { JavaLanguageServerPlugin.logException("Handle document open ", e); } @@ -360,12 +356,7 @@ public void didSave(DidSaveTextDocumentParams params) { // some refactorings may be applied by the way, wrap those in a WorkspaceRunnable try { JobHelpers.waitForJobs(DocumentLifeCycleHandler.DOCUMENT_LIFE_CYCLE_JOBS, new NullProgressMonitor()); - ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { - @Override - public void run(IProgressMonitor monitor) throws CoreException { - handleSaved(params); - } - }, null, IWorkspace.AVOID_UPDATE, new NullProgressMonitor()); + ResourcesPlugin.getWorkspace().run((IWorkspaceRunnable) monitor -> handleSaved(params), null, IWorkspace.AVOID_UPDATE, new NullProgressMonitor()); } catch (CoreException e) { JavaLanguageServerPlugin.logException("Handle document save ", e); } @@ -398,6 +389,8 @@ public ICompilationUnit handleOpen(DidOpenTextDocumentParams params) { } } + // Update the static imports of current file as the favorite static members. + CompletionProposalUtils.addStaticImportsAsFavoriteImports(unit); // DiagnosticsHandler problemRequestor = new DiagnosticsHandler(connection, unit.getResource(), reportOnlySyntaxErrors); unit.becomeWorkingCopy(new NullProgressMonitor()); IBuffer buffer = unit.getBuffer(); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java index 8da12c6c52..48693876dd 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java @@ -45,6 +45,7 @@ import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; import org.eclipse.jdt.ls.core.internal.contentassist.ChainCompletionProposalComputer; import org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalRequestor; +import org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalUtils; import org.eclipse.jdt.ls.core.internal.contentassist.JavadocCompletionProposal; import org.eclipse.jdt.ls.core.internal.contentassist.SnippetCompletionProposal; import org.eclipse.jdt.ls.core.internal.contentassist.SortTextHelper; @@ -230,6 +231,7 @@ private CompletionList computeContentAssist(ICompilationUnit unit, CompletionPar } } + CompletionProposalUtils.addStaticImportsAsFavoriteImports(unit); List proposals = new ArrayList<>(); final int offset = JsonRpcHelpers.toOffset(unit.getBuffer(), params.getPosition().getLine(), params.getPosition().getCharacter()); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java index 6d8def8634..9f43947e57 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -559,6 +560,9 @@ public class Preferences { public static final String IMPLEMENTATION_ID = UUID.randomUUID().toString(); public static final String SELECTION_RANGE_ID = UUID.randomUUID().toString(); public static final String INLAY_HINT_ID = UUID.randomUUID().toString(); + + public static final Set DISCOVERED_STATIC_IMPORTS = new LinkedHashSet<>(); + private static final String GRADLE_OFFLINE_MODE = "gradle.offline.mode"; private static final int DEFAULT_TAB_SIZE = 4; @@ -1610,7 +1614,9 @@ public List getJavaImportExclusions() { } public String[] getJavaCompletionFavoriteMembers() { - return javaCompletionFavoriteMembers.toArray(new String[0]); + Set favorites = new LinkedHashSet<>(javaCompletionFavoriteMembers); + favorites.addAll(DISCOVERED_STATIC_IMPORTS); + return favorites.toArray(new String[0]); } public String getJavaHome() { diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java index ade05f45f2..74bee7d2a4 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -3211,6 +3212,33 @@ public class Test { } } + @Test + public void testCompletion_autoAddStaticImportAsFavoriteImport() throws JavaModelException { + ICompilationUnit unit = getWorkingCopy("src/org/sample/Test.java", """ + package org.sample; + import static java.util.Arrays.sort; + public class Test { + public static void main(String[] args) { + asList + } + }"""); + String[] oldFavorites = JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getJavaCompletionFavoriteMembers(); + Set oldStaticImports = new LinkedHashSet<>(Preferences.DISCOVERED_STATIC_IMPORTS); + try { + JavaLanguageServerPlugin.getPreferencesManager().getPreferences().setJavaCompletionFavoriteMembers(Arrays.asList("org.junit.Assert.*")); + Preferences.DISCOVERED_STATIC_IMPORTS.clear(); + CompletionList list = requestCompletions(unit, "asList"); + assertNotNull(list); + assertFalse(list.getItems().isEmpty()); + CompletionItem item = list.getItems().stream().filter(i -> i.getDetail() != null && i.getDetail().startsWith("java.util.Arrays.asList(")).collect(Collectors.toList()).get(0); + assertNotNull(item); + } finally { + JavaLanguageServerPlugin.getPreferencesManager().getPreferences().setJavaCompletionFavoriteMembers(Arrays.asList(oldFavorites)); + Preferences.DISCOVERED_STATIC_IMPORTS.addAll(oldStaticImports); + PreferenceManager.getPrefs(null).setFilteredTypes(Collections.emptyList()); + } + } + @Test public void testCompletion_InvalidJavadoc() throws Exception { importProjects("maven/aspose"); From 8eff343d70726afcfbb317995c515124664e473b Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Fri, 13 Oct 2023 11:04:10 +0800 Subject: [PATCH 2/4] fix test case --- .../jdt/ls/core/internal/handlers/CompletionHandlerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java index 74bee7d2a4..f59c5d99fe 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerTest.java @@ -129,6 +129,7 @@ public void setUp() { lifeCycleHandler = new DocumentLifeCycleHandler(javaClient, preferenceManager, projectsManager, true); preferences.setPostfixCompletionEnabled(false); preferences.setCompletionLazyResolveTextEditEnabled(false); + Preferences.DISCOVERED_STATIC_IMPORTS.clear(); } @After From 09d99ef8ecbc307f09d61bcf389b4a9b95225a5e Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Fri, 13 Oct 2023 12:44:08 +0800 Subject: [PATCH 3/4] fix test case --- .../ls/core/internal/handlers/CompletionHandlerChainTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerChainTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerChainTest.java index 3fc88ecfe6..af07552fc3 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerChainTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandlerChainTest.java @@ -13,6 +13,7 @@ import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.JsonMessageHelper; +import org.eclipse.jdt.ls.core.internal.preferences.Preferences; import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.CompletionList; import org.junit.After; @@ -54,6 +55,7 @@ public void setUp() { lifeCycleHandler = new DocumentLifeCycleHandler(javaClient, preferenceManager, projectsManager, true); preferences.setPostfixCompletionEnabled(false); preferences.setChainCompletionEnabled(true); + Preferences.DISCOVERED_STATIC_IMPORTS.clear(); } @After From 0356c1bb7ef2d1202994a46d6f428e2d55e767b9 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Mon, 16 Oct 2023 10:31:56 +0800 Subject: [PATCH 4/4] Simplify the logic to resolve the static imports of current file --- .../CompletionProposalUtils.java | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java index 7c21683653..481e968078 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalUtils.java @@ -71,24 +71,16 @@ public static CompletionProposal getRequiredTypeProposal(CompletionProposal prop public static void addStaticImportsAsFavoriteImports(ICompilationUnit unit) { try { List staticImports = Arrays.stream(unit.getImports()) - .filter(t -> { - try { - return Flags.isStatic(t.getFlags()); - } catch (JavaModelException e) { - // ignore - } - return false;}) - .map(t -> t.getElementName()) - .map(t -> { - int lastDot = t.lastIndexOf("."); - if (lastDot > -1) { - return t.substring(0, lastDot) + ".*"; - } - return t; - }).toList(); - if (!staticImports.isEmpty()) { - Preferences.DISCOVERED_STATIC_IMPORTS.addAll(staticImports); - } + .filter(t -> { + try { + return Flags.isStatic(t.getFlags()); + } catch (JavaModelException e) { + return false; + } + }) + .map(t -> t.getElementName().replaceFirst("\\.[^\\.]+$", ".*")) + .toList(); + Preferences.DISCOVERED_STATIC_IMPORTS.addAll(staticImports); } catch (JavaModelException e) { // ignore }