From b1a51b108c9fbe86720cc3e6eea2c9a301e7d602 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Thu, 12 Mar 2026 17:53:59 +0100 Subject: [PATCH 1/3] Optimize completion performance by caching preference manager calls Cache getPreferencesManager().getClientPreferences() results in local variables to avoid redundant method calls during completion requests. This eliminates duplicate lookups in hot code paths. Co-Authored-By: Claude Sonnet 4.5 --- .../eclipse/jdt/ls/core/internal/CompletionUtils.java | 10 ++++++---- .../CompletionProposalDescriptionProvider.java | 3 ++- .../CompletionProposalReplacementProvider.java | 4 ++-- .../contentassist/JavadocCompletionProposal.java | 5 +++-- .../contentassist/SnippetCompletionProposal.java | 3 ++- .../ls/core/internal/contentassist/SnippetUtils.java | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/CompletionUtils.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/CompletionUtils.java index 60f139ef32..39247d4592 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/CompletionUtils.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/CompletionUtils.java @@ -43,10 +43,11 @@ public static String sanitizeCompletion(String replace) { * the completion itemDefaults of the completion list */ public static void setInsertTextMode(final CompletionItem item, CompletionItemDefaults completionItemDefaults) { - if ((!JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionListItemDefaultsPropertySupport("insertTextMode") || + var clientPreferences = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences(); + if ((!clientPreferences.isCompletionListItemDefaultsPropertySupport("insertTextMode") || completionItemDefaults.getInsertTextMode() == null || completionItemDefaults.getInsertTextMode() != InsertTextMode.AdjustIndentation) && - JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().getCompletionItemInsertTextModeDefault() != InsertTextMode.AdjustIndentation + clientPreferences.getCompletionItemInsertTextModeDefault() != InsertTextMode.AdjustIndentation ) { item.setInsertTextMode(InsertTextMode.AdjustIndentation); } @@ -61,8 +62,9 @@ public static void setInsertTextMode(final CompletionItem item, CompletionItemDe * the completion itemDefaults of the completion list */ public static void setInsertTextFormat(final CompletionItem item, CompletionItemDefaults completionItemDefaults) { - InsertTextFormat insertTextFormat = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionSnippetsSupported() ? InsertTextFormat.Snippet : InsertTextFormat.PlainText; - if (!JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionListItemDefaultsPropertySupport("insertTextFormat") || + var clientPreferences = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences(); + InsertTextFormat insertTextFormat = clientPreferences.isCompletionSnippetsSupported() ? InsertTextFormat.Snippet : InsertTextFormat.PlainText; + if (!clientPreferences.isCompletionListItemDefaultsPropertySupport("insertTextFormat") || completionItemDefaults.getInsertTextFormat() == null || completionItemDefaults.getInsertTextFormat() != insertTextFormat ) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalDescriptionProvider.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalDescriptionProvider.java index 83c70c890a..5315d61611 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalDescriptionProvider.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalDescriptionProvider.java @@ -839,6 +839,7 @@ private void setLabelDetails(CompletionItem item, String label, String detail, S } private boolean isCompletionItemLabelDetailsSupport() { - return JavaLanguageServerPlugin.getPreferencesManager() != null && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionItemLabelDetailsSupport(); + var preferenceManager = JavaLanguageServerPlugin.getPreferencesManager(); + return preferenceManager != null && preferenceManager.getClientPreferences().isCompletionItemLabelDetailsSupport(); } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalReplacementProvider.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalReplacementProvider.java index fa3913e051..0f434f42e8 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalReplacementProvider.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalReplacementProvider.java @@ -176,8 +176,8 @@ public void updateReplacement(CompletionProposal proposal, CompletionItem item, } else { item.setInsertTextFormat(InsertTextFormat.PlainText); } - if (isResolvingRequest || (!JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionListItemDefaultsPropertySupport("insertTextMode") - && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().getCompletionItemInsertTextModeDefault() != InsertTextMode.AdjustIndentation)) { + if (isResolvingRequest || (!client.isCompletionListItemDefaultsPropertySupport("insertTextMode") + && client.getCompletionItemInsertTextModeDefault() != InsertTextMode.AdjustIndentation)) { item.setInsertTextMode(InsertTextMode.AdjustIndentation); } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/JavadocCompletionProposal.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/JavadocCompletionProposal.java index 0dc2d19b6d..6564b5b1cd 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/JavadocCompletionProposal.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/JavadocCompletionProposal.java @@ -107,10 +107,11 @@ public List getProposals(ICompilationUnit cu, int offset, Comple } final CompletionItem ci = new CompletionItem(); CompletionItemDefaults completionItemDefaults = collector.getCompletionItemDefaults(); + var clientPreferences = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences(); Range range = JDTUtils.toRange(unit, offset, 0); - boolean isSnippetSupported = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionSnippetsSupported(); + boolean isSnippetSupported = clientPreferences.isCompletionSnippetsSupported(); String replacement = prepareTemplate(buf.toString(), lineDelimiter, isSnippetSupported); - if (JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionListItemDefaultsPropertySupport("editRange") && + if (clientPreferences.isCompletionListItemDefaultsPropertySupport("editRange") && completionItemDefaults != null && completionItemDefaults.getEditRange() != null && completionItemDefaults.getEditRange().getLeft() == range) { ci.setTextEditText(replacement); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetCompletionProposal.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetCompletionProposal.java index 88546a6470..c04e58dc39 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetCompletionProposal.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetCompletionProposal.java @@ -431,7 +431,8 @@ public static void setTextEdit(CompletionContext completionContext, ICompilation } private static boolean isCompletionItemLabelDetailsSupport() { - return JavaLanguageServerPlugin.getPreferencesManager() != null && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isCompletionItemLabelDetailsSupport(); + var preferenceManager = JavaLanguageServerPlugin.getPreferencesManager(); + return preferenceManager != null && preferenceManager.getClientPreferences().isCompletionItemLabelDetailsSupport(); } public static String evaluateGenericTemplate(ICompilationUnit cu, CompletionContext completionContext, Template template) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetUtils.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetUtils.java index c6b0a47e5e..f5e363dd60 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetUtils.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SnippetUtils.java @@ -83,8 +83,9 @@ public static Either beautifyDocument(String raw) { escapedString = escapedString.replaceAll(TM_SELECTED_TEXT, ""); escapedString = escapedString.replaceAll(TM_FILENAME_BASE, ""); - if (JavaLanguageServerPlugin.getPreferencesManager() != null && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences() != null - && JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isSupportsCompletionDocumentationMarkdown()) { + var preferenceManager = JavaLanguageServerPlugin.getPreferencesManager(); + if (preferenceManager != null && preferenceManager.getClientPreferences() != null + && preferenceManager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) { MarkupContent markupContent = new MarkupContent(); markupContent.setKind(MarkupKind.MARKDOWN); markupContent.setValue(String.format("```%s\n%s\n```", MARKDOWN_LANGUAGE, escapedString)); From 4a3bc21f6a319d98771d0e1b7420dd655704dc4b Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Thu, 12 Mar 2026 17:57:09 +0100 Subject: [PATCH 2/3] Combine double loop in completion proposal ranking Merge two separate loops that iterate through proposals into a single loop, reducing iterations from 2N to N. Also pre-size the HashMap to avoid resizing during population. Co-Authored-By: Claude Sonnet 4.5 --- .../contentassist/CompletionProposalRequestor.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java index eaa2157bf9..5c8e5da86f 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/CompletionProposalRequestor.java @@ -260,17 +260,16 @@ public List getCompletionItems() { public List getCompletionItems(IProgressMonitor monitor) { CompletionRankingAggregation[] aggregatedRanks = getAggregatedRankingResult(monitor); + Map proposalToRankingResult = new HashMap<>(proposals.size()); for (int i = 0; i < proposals.size(); i++) { CompletionProposal proposal = proposals.get(i); - if (aggregatedRanks[i] != null) { + CompletionRankingAggregation ranking = aggregatedRanks[i]; + if (ranking != null) { // we assume there won't be overflow for now since the the score from // each provider can only be 100 at most. - proposal.setRelevance(proposal.getRelevance() + aggregatedRanks[i].getScore()); + proposal.setRelevance(proposal.getRelevance() + ranking.getScore()); } - } - Map proposalToRankingResult = new HashMap<>(); - for (int i = 0; i < proposals.size(); i++) { - proposalToRankingResult.put(proposals.get(i), aggregatedRanks[i]); + proposalToRankingResult.put(proposal, ranking); } proposals.sort(new ProposalComparator(proposals.size())); From b691016f8fe191c8bd585f7f4d2b06ef4f6303ad Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Thu, 12 Mar 2026 18:05:59 +0100 Subject: [PATCH 3/3] Optimize completion command assignment loop Improve performance of the command assignment loop by: - Early exit when data map is null (fast path) - Use Map.get() instead of getOrDefault() for better performance - Reduce unnecessary string initializations - Better null checking reduces wasted iterations Co-Authored-By: Claude Sonnet 4.5 --- .../core/internal/handlers/CompletionHandler.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 4a6172ebdb..a4bd89efdf 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 @@ -140,17 +140,18 @@ public Either, CompletionList> completion(CompletionParams long executionTime = System.currentTimeMillis() - startTime; String lastRequestId = null; for (CompletionItem item : $.getItems()) { - String requestId = ""; - String proposalId = ""; @SuppressWarnings("unchecked") Map data = (Map) item.getData(); - if (data != null) { - requestId = data.getOrDefault(CompletionResolveHandler.DATA_FIELD_REQUEST_ID, ""); - proposalId = data.getOrDefault(CompletionResolveHandler.DATA_FIELD_PROPOSAL_ID, ""); + if (data == null) { + continue; } - if (requestId.isEmpty() || proposalId.isEmpty()) { + + String requestId = data.get(CompletionResolveHandler.DATA_FIELD_REQUEST_ID); + String proposalId = data.get(CompletionResolveHandler.DATA_FIELD_PROPOSAL_ID); + if (requestId == null || requestId.isEmpty() || proposalId == null || proposalId.isEmpty()) { continue; } + item.setCommand(new Command("", "java.completion.onDidSelect", Arrays.asList( requestId, proposalId