Skip to content

Commit 4bb6698

Browse files
committed
GH-1317: allow individual context assist processors to devide whether the list is incomplete or not + refined the way class and package proposals show up in XML config files
1 parent 7763abc commit 4bb6698

File tree

16 files changed

+123
-75
lines changed

16 files changed

+123
-75
lines changed

headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/CompositeCompletionEngine.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019 Pivotal, Inc.
2+
* Copyright (c) 2019, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -50,23 +50,32 @@ public void add(ICompletionEngine engine) {
5050
}
5151

5252
@Override
53-
public Collection<ICompletionProposal> getCompletions(TextDocument document, int offset) throws Exception {
53+
public InternalCompletionList getCompletions(TextDocument document, int offset) throws Exception {
5454
LanguageId language = document.getLanguageId();
5555
log.info("languageId = {}", language);
5656
Collection<ICompletionEngine> engines = subEngines.get(language);
57+
5758
if (engines.size()==1) {
59+
5860
//Special case to avoid some collection copying
5961
ICompletionEngine engine = engines.iterator().next();
6062
return engine.getCompletions(document, offset);
63+
6164
} else {
65+
66+
boolean isIncomplete = false;
6267
ImmutableList.Builder<ICompletionProposal> completions = ImmutableList.builder();
68+
6369
for (ICompletionEngine engine : engines) {
64-
Collection<ICompletionProposal> c = engine.getCompletions(document, offset);
65-
if (c!=null) {
66-
completions.addAll(c);
70+
InternalCompletionList c = engine.getCompletions(document, offset);
71+
if (c != null && c.completionItems() != null) {
72+
completions.addAll(c.completionItems());
73+
if (c.isIncomplete()) {
74+
isIncomplete = true;
75+
}
6776
}
6877
}
69-
return completions.build();
78+
return new InternalCompletionList(completions.build(), isIncomplete);
7079
}
7180
};
7281

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2015, 2018 Pivotal, Inc.
2+
* Copyright (c) 2015, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -10,15 +10,13 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.commons.languageserver.completion;
1212

13-
import java.util.Collection;
14-
1513
import org.springframework.ide.vscode.commons.util.text.TextDocument;
1614

1715
/**
1816
* @author Kris De Volder
1917
*/
2018
public interface ICompletionEngine {
2119

22-
Collection<ICompletionProposal> getCompletions(TextDocument document, int offset) throws Exception;
20+
InternalCompletionList getCompletions(TextDocument document, int offset) throws Exception;
2321

2422
}

headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
*/
2323
public interface ICompletionProposal {
2424

25-
2625
String getLabel();
2726
CompletionItemKind getKind();
2827
DocumentEdits getTextEdit();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Broadcom
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Broadcom - initial API and implementation
10+
*******************************************************************************/
11+
package org.springframework.ide.vscode.commons.languageserver.completion;
12+
13+
import java.util.Collection;
14+
15+
public record InternalCompletionList (Collection<ICompletionProposal> completionItems, boolean isIncomplete) {
16+
}

headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -213,25 +213,27 @@ public CompletionList getCompletions(CancelChecker cancelToken, TextDocumentPosi
213213
int offset = doc.toOffset(params.getPosition());
214214

215215
// get completions
216-
Collection<ICompletionProposal> rawCompletions = engine.getCompletions(doc, offset);
216+
InternalCompletionList rawCompletionList = engine.getCompletions(doc, offset);
217217

218218
cancelToken.checkCanceled();
219219

220-
List<ICompletionProposal> completions = filter(rawCompletions);
220+
List<ICompletionProposal> completions = filter(rawCompletionList.completionItems());
221221
Collections.sort(completions, ScoreableProposal.COMPARATOR);
222222

223223
cancelToken.checkCanceled();
224224

225-
list.setIsIncomplete(false);
225+
boolean isIncomplete = rawCompletionList.isIncomplete();
226+
226227
List<CompletionItem> items = new ArrayList<>(completions.size());
227228
SortKeys sortkeys = new SortKeys();
228229
int count = 0;
229230

230231
for (ICompletionProposal c : completions) {
231232
count++;
232233

233-
if (maxCompletions > 0 && count>maxCompletions) {
234-
list.setIsIncomplete(true);
234+
if (maxCompletions > 0 && count > maxCompletions) {
235+
// override whatever completion engines said about being incomplete
236+
isIncomplete = true;
235237
break;
236238
}
237239
try {
@@ -244,6 +246,8 @@ public CompletionList getCompletions(CancelChecker cancelToken, TextDocumentPosi
244246
cancelToken.checkCanceled();
245247

246248
list.setItems(items);
249+
list.setIsIncomplete(isIncomplete);
250+
247251
//This is a hack is no longer needed but keeping it as a reference:
248252
// See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=535823
249253
// Reason hack is not needed is because of the fix in: https://www.pivotaltracker.com/story/show/159667257

headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/YamlCompletionEngine.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2016, 2018 Pivotal, Inc.
2+
* Copyright (c) 2016, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -25,6 +25,7 @@
2525
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
2626
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
2727
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
28+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
2829
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
2930
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
3031
import org.springframework.ide.vscode.commons.util.Assert;
@@ -81,7 +82,7 @@ protected CompletionFactory proposalFactory() {
8182
}
8283

8384
@Override
84-
public Collection<ICompletionProposal> getCompletions(TextDocument _doc, int offset) throws Exception {
85+
public InternalCompletionList getCompletions(TextDocument _doc, int offset) throws Exception {
8586
YamlDocument doc = new YamlDocument(_doc, structureProvider);
8687
if (!doc.isCommented(offset)) {
8788
SRootNode root = doc.getStructure();
@@ -98,16 +99,16 @@ public Collection<ICompletionProposal> getCompletions(TextDocument _doc, int off
9899
completions.addAll(getRelaxedCompletions(offset, doc, current, contextNode, baseIndent, deempasizeBy));
99100
deempasizeBy += ScoreableProposal.DEEMP_NEXT_CONTEXT;
100101
}
101-
return completions;
102+
return new InternalCompletionList(completions, false);
102103
} else {
103104
//precise indentation only
104105
Assert.isLegal(contextNodes.size()<=1);
105106
for (SNode contextNode : contextNodes) {
106-
return getBaseCompletions(offset, doc, current, contextNode);
107+
return new InternalCompletionList(getBaseCompletions(offset, doc, current, contextNode), false);
107108
}
108109
}
109110
}
110-
return Collections.emptyList();
111+
return new InternalCompletionList(Collections.emptyList(), false);
111112
}
112113

113114
protected Collection<? extends ICompletionProposal> getRelaxedCompletions(int offset, YamlDocument doc, SNode current, SNode contextNode, int baseIndent, double deempasizeBy) {

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/ClasspathResourceCompletionProvider.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2020 Pivotal, Inc.
2+
* Copyright (c) 2020, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
2222
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
2323
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
2424
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
25+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
2526
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
2627
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
2728
import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
@@ -73,7 +74,7 @@ protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String que
7374
private PropertyCompletionFactory completionFactory = new PropertyCompletionFactory();
7475

7576
@Override
76-
public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offset) {
77+
public InternalCompletionList getCompletions(TextDocument doc, int offset) {
7778
ImmutableList.Builder<ICompletionProposal> proposals = ImmutableList.builder();
7879
IJavaProject jp = projectFinder.find(doc.getId()).orElse(null);
7980
if (jp!=null) {
@@ -98,7 +99,7 @@ public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offs
9899
}
99100
}
100101
}
101-
return proposals.build();
102+
return new InternalCompletionList(proposals.build(), false);
102103
}
103104

104105
@Override

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/DollarPropertyCompletionProvider.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2020 Pivotal, Inc.
2+
* Copyright (c) 2020, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -19,6 +19,7 @@
1919
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
2020
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
2121
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
22+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
2223
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
2324
import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
2425
import org.springframework.ide.vscode.commons.util.BadLocationException;
@@ -51,7 +52,7 @@ public DollarPropertyCompletionProvider(BootLanguageServerParams params) {
5152
}
5253

5354
@Override
54-
public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offset) {
55+
public InternalCompletionList getCompletions(TextDocument doc, int offset) {
5556
ImmutableList.Builder<ICompletionProposal> proposals = ImmutableList.builder();
5657
String prefix = PREFIX_FINDER.getPrefix(doc, offset);
5758
int prefixStart = offset-prefix.length();
@@ -74,7 +75,7 @@ public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offs
7475
} catch (BadLocationException e) {
7576
//ignore. Didn't find the '${'
7677
}
77-
return proposals.build();
78+
return new InternalCompletionList(proposals.build(), false);
7879
}
7980

8081
@Override

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCompletionEngine.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2017, 2018 Pivotal, Inc.
2+
* Copyright (c) 2017, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -25,6 +25,7 @@
2525
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
2626
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
2727
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
28+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
2829
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
2930
import org.springframework.ide.vscode.commons.util.BadLocationException;
3031
import org.springframework.ide.vscode.commons.util.text.LanguageId;
@@ -48,7 +49,7 @@ public BootJavaCompletionEngine(CompilationUnitCache cuCache, Map<String, Comple
4849
}
4950

5051
@Override
51-
public Collection<ICompletionProposal> getCompletions(TextDocument document, int offset) throws Exception {
52+
public InternalCompletionList getCompletions(TextDocument document, int offset) throws Exception {
5253
return cuCache.withCompilationUnit(document, cu -> {
5354
if (cu != null) {
5455
ASTNode node = findNode(document, offset, cu);
@@ -58,11 +59,12 @@ public Collection<ICompletionProposal> getCompletions(TextDocument document, int
5859
collectCompletionsForAnnotations(node, offset, document, completions);
5960
collectCompletions(node, offset, document, completions);
6061
snippets.getCompletions(document, offset, node, cu, completions);
61-
return completions;
62+
63+
return new InternalCompletionList(completions, false);
6264
}
6365
}
6466

65-
return Collections.emptyList();
67+
return new InternalCompletionList(Collections.emptyList(), false);
6668
});
6769
}
6870

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/SpringPropertiesCompletionEngine.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2016, 2019 Pivotal, Inc.
2+
* Copyright (c) 2016, 2024 Pivotal, Inc.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -19,6 +19,7 @@
1919
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
2020
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
2121
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
22+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
2223
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
2324
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
2425
import org.springframework.ide.vscode.commons.util.BadLocationException;
@@ -54,9 +55,11 @@ public SpringPropertiesCompletionEngine(SpringPropertyIndexProvider indexProvide
5455
* Create completions proposals in the context of a properties text editor.
5556
*/
5657
@Override
57-
public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offset) throws BadLocationException {
58-
return new PropertiesCompletionProposalsCalculator(indexProvider.getIndex(doc).getProperties(),
58+
public InternalCompletionList getCompletions(TextDocument doc, int offset) throws BadLocationException {
59+
Collection<ICompletionProposal> completionItems = new PropertiesCompletionProposalsCalculator(indexProvider.getIndex(doc).getProperties(),
5960
typeUtilProvider.getTypeUtil(sourceLinks, doc), completionFactory, doc, offset, preferLowerCaseEnums).calculate();
61+
62+
return new InternalCompletionList(completionItems, false);
6063
}
6164

6265
public boolean getPreferLowerCaseEnums() {

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/SpringXMLCompletionEngine.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
6969
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
7070
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
71+
import org.springframework.ide.vscode.commons.languageserver.completion.InternalCompletionList;
7172
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
7273
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
7374
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -135,9 +136,9 @@ public SpringXMLCompletionEngine(
135136
}
136137

137138
@Override
138-
public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offset) throws Exception {
139+
public InternalCompletionList getCompletions(TextDocument doc, int offset) throws Exception {
139140
if (!config.isSpringXMLSupportEnabled() || !config.isXmlContentAssistEnabled()) {
140-
return Collections.emptyList();
141+
return new InternalCompletionList(Collections.emptyList(), false);
141142
}
142143

143144
String content = doc.get();
@@ -175,7 +176,7 @@ public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offs
175176

176177
XMLCompletionProvider completionProvider = this.completionProviders.get(key);
177178
if (completionProvider != null) {
178-
Collection<ICompletionProposal> completions = completionProvider.getCompletions(doc, namespace, node, attributeAt, scanner, offset);
179+
InternalCompletionList completions = completionProvider.getCompletions(doc, namespace, node, attributeAt, scanner, offset);
179180
return completions;
180181
}
181182
}
@@ -185,15 +186,15 @@ public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offs
185186
if (scanner.getTokenOffset() <= offset && offset < scanner.getTokenEnd()) {
186187
if (node.getParentNode() != null && node.getParentNode() instanceof DOMDocument
187188
&& namespace.equals("http://www.springframework.org/schema/beans") && node.getLocalName().equals("beans")) {
188-
return NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node);
189+
return new InternalCompletionList(NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node), false);
189190
}
190191
}
191192
break;
192193
case Whitespace:
193194
if (scanner.getTokenOffset() <= offset && offset < scanner.getTokenEnd()) {
194195
if (node.getParentNode() != null && node.getParentNode() instanceof DOMDocument
195196
&& namespace.equals("http://www.springframework.org/schema/beans") && node.getLocalName().equals("beans")) {
196-
return NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node);
197+
return new InternalCompletionList(NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node), false);
197198
}
198199
}
199200
break;
@@ -203,10 +204,10 @@ public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offs
203204
token = scanner.scan();
204205
}
205206
}
206-
return Collections.emptyList();
207+
return new InternalCompletionList(Collections.emptyList(), false);
207208
}
208209

209-
private Collection<ICompletionProposal> emptySpringXMLConfigSnippet(TextDocument doc) {
210+
private InternalCompletionList emptySpringXMLConfigSnippet(TextDocument doc) {
210211

211212
CompletionItemKind kind = CompletionItemKind.Snippet;
212213

@@ -244,7 +245,7 @@ private Collection<ICompletionProposal> emptySpringXMLConfigSnippet(TextDocument
244245
Collection<ICompletionProposal> completions = new ArrayList<>(1);
245246
completions.add(proposal);
246247

247-
return completions;
248+
return new InternalCompletionList(completions, false);
248249
}
249250

250251
@Override

0 commit comments

Comments
 (0)