Skip to content

Commit 5d25259

Browse files
authored
Merge pull request #9633 from lahodaj/typescript-fixes
Fixing edit application and code completion filtering in the LSP client.
2 parents d5a2acd + 2bde6d4 commit 5d25259

4 files changed

Lines changed: 122 additions & 12 deletions

File tree

‎ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.net.URI;
2626
import java.net.URISyntaxException;
2727
import java.util.ArrayList;
28+
import java.util.Collections;
2829
import java.util.Comparator;
2930
import java.util.List;
3031
import java.util.Map;
@@ -186,9 +187,10 @@ public static void applyEditsNoLock(Document doc, List<? extends TextEdit> edits
186187
* document.
187188
*/
188189
public static void applyEditsNoLock(Document doc, List<? extends TextEdit> edits, Integer startLimit, Integer endLimit) {
189-
edits
190-
.stream()
191-
.sorted(rangeReverseSort)
190+
List<TextEdit> sorted = new ArrayList<>(edits);
191+
Collections.sort(sorted, rangeSort);
192+
Collections.reverse(sorted);
193+
sorted
192194
.forEach(te -> {
193195
try {
194196
int start = Utils.getOffset(doc, te.getRange().getStart());
@@ -315,15 +317,15 @@ public static void open(String targetUri, Range targetRange) {
315317
}
316318
}
317319

318-
private static final Comparator<TextEdit> rangeReverseSort = (s1, s2) -> {
320+
private static final Comparator<TextEdit> rangeSort = (s1, s2) -> {
319321
int l1 = s1.getRange().getEnd().getLine();
320322
int l2 = s2.getRange().getEnd().getLine();
321323
int c1 = s1.getRange().getEnd().getCharacter();
322324
int c2 = s2.getRange().getEnd().getCharacter();
323325
if (l1 != l2) {
324-
return l2 - l1;
326+
return l1 - l2;
325327
} else {
326-
return c2 - c1;
328+
return c1 - c2;
327329
}
328330
};
329331

‎ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImpl.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,25 @@ private void handleCompletionResult(CompletionResultSet resultSet, JTextComponen
203203
items = completionResult.getRight().getItems();
204204
incomplete = completionResult.getRight().isIncomplete();
205205
}
206+
int[] identSpan;
207+
String ident;
208+
try {
209+
identSpan = Utilities.getIdentifierBlock((BaseDocument) doc, caretOffset); //TODO: what is an identifier might (should?) be taken from language configuration?
210+
if (identSpan != null) {
211+
int end = Math.min(caretOffset, identSpan[1]);
212+
ident = doc.getText(identSpan[0], end - identSpan[0]);
213+
} else {
214+
ident = "";
215+
}
216+
} catch (BadLocationException ex) {
217+
Exceptions.printStackTrace(ex);
218+
return ;
219+
}
206220
for (CompletionItem i : items) {
221+
String filterText = i.getFilterText() != null ? i.getFilterText() : i.getLabel();
222+
if (!filterText.startsWith(ident)) {
223+
continue;
224+
}
207225
String insert = i.getInsertText() != null ? i.getInsertText() : i.getLabel();
208226
String leftLabel;
209227
String rightLabel;

‎ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/UtilsTest.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,28 @@ public void testApplyTextEdit() throws Exception {
9595
LifecycleManager.getDefault().saveAll();
9696
}
9797

98+
public void testSamePosition() throws Exception {
99+
//what happens when there are two edits at the same location:
100+
//apply them in a reverse original order - but not clear what's correct,
101+
//this is pretty broken
102+
clearWorkDir();
103+
FileObject wd = FileUtil.toFileObject(getWorkDir());
104+
FileObject sourceFile1 = wd.createData("Test1.txt");
105+
try (OutputStream out = sourceFile1.getOutputStream()) {
106+
out.write(("0123456789\n" +
107+
"0123456789\n").getBytes(StandardCharsets.UTF_8));
108+
}
109+
Map<String, List<TextEdit>> changes = new HashMap<>();
110+
changes.put(Utils.toURI(sourceFile1), Arrays.asList(new TextEdit(new Range(new Position(1, 3), new Position(1, 3)), "a"),
111+
new TextEdit(new Range(new Position(1, 3), new Position(1, 3)), "b")));
112+
WorkspaceEdit edit = new WorkspaceEdit(changes);
113+
Utils.applyWorkspaceEdit(edit);
114+
assertContent("0123456789\n" +
115+
"012ab3456789\n",
116+
sourceFile1);
117+
LifecycleManager.getDefault().saveAll();
118+
}
119+
98120
public void testApplyChanges() throws Exception {
99121
clearWorkDir();
100122
FileObject wd = FileUtil.toFileObject(getWorkDir());

‎ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImplTest.java‎

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ public void testCommitWithResolveInsertPlainTextAndAdditionalEdits() throws IOEx
111111
new TestTextDocumentService() {
112112
@Override
113113
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
114+
CompletionItem item = new CompletionItem("to-be-resolved");
115+
item.setFilterText("insert");
114116
return CompletableFuture.completedFuture(Either.forLeft(List.of(
115-
new CompletionItem("to-be-resolved")
117+
item
116118
)));
117119
}
118120
@Override
@@ -141,8 +143,10 @@ public void testCommitWithResolveInsertSnippetAndAdditionalEdits() throws IOExce
141143
new TestTextDocumentService() {
142144
@Override
143145
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
146+
CompletionItem item = new CompletionItem("to-be-resolved");
147+
item.setFilterText("insert");
144148
return CompletableFuture.completedFuture(Either.forLeft(List.of(
145-
new CompletionItem("to-be-resolved")
149+
item
146150
)));
147151
}
148152
@Override
@@ -171,8 +175,10 @@ public void testCommitWithResolveSnippetMainEditAndAdditionalEdits() throws IOEx
171175
new TestTextDocumentService() {
172176
@Override
173177
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
178+
CompletionItem item = new CompletionItem("to-be-resolved");
179+
item.setFilterText("insert");
174180
return CompletableFuture.completedFuture(Either.forLeft(List.of(
175-
new CompletionItem("to-be-resolved")
181+
item
176182
)));
177183
}
178184
@Override
@@ -201,8 +207,10 @@ public void testCommitWithResolveMainEditAndAdditionalEdits() throws IOException
201207
new TestTextDocumentService() {
202208
@Override
203209
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
210+
CompletionItem item = new CompletionItem("to-be-resolved");
211+
item.setFilterText("insert");
204212
return CompletableFuture.completedFuture(Either.forLeft(List.of(
205-
new CompletionItem("to-be-resolved")
213+
item
206214
)));
207215
}
208216
@Override
@@ -227,7 +235,7 @@ public void testLabelDetails() throws IOException {
227235

228236
runCompletionTest(
229237
"""
230-
foo.ins|
238+
foo.|
231239
""",
232240
new TestTextDocumentService() {
233241
@Override
@@ -305,6 +313,66 @@ public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completio
305313
assertFalse(notInvoked.get());
306314
}
307315

316+
public void testFiltering() throws IOException {
317+
List<String> actualItems = new ArrayList<>();
318+
CompletionValidator printItems = (c, items) -> {
319+
actualItems.addAll(printCompletionItems(items));
320+
};
321+
TextDocumentService textDocumentService;
322+
textDocumentService =
323+
new TestTextDocumentService() {
324+
@Override
325+
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
326+
List<CompletionItem> result = new ArrayList<>();
327+
328+
{
329+
CompletionItem resultItem = new CompletionItem("addTest1");
330+
331+
result.add(resultItem);
332+
}
333+
{
334+
CompletionItem resultItem = new CompletionItem("X: addTest2");
335+
336+
resultItem.setFilterText("addTest2");
337+
result.add(resultItem);
338+
}
339+
{
340+
CompletionItem resultItem = new CompletionItem("removeTest1");
341+
342+
result.add(resultItem);
343+
}
344+
{
345+
CompletionItem resultItem = new CompletionItem("X: removeTest2");
346+
347+
resultItem.setFilterText("removeTest2");
348+
result.add(resultItem);
349+
}
350+
351+
return CompletableFuture.completedFuture(Either.forLeft(result));
352+
}
353+
};
354+
355+
actualItems.clear();
356+
runCompletionTest("""
357+
foo.|
358+
""",
359+
textDocumentService, printItems);
360+
assertEquals(List.of("addTest1",
361+
"X: addTest2",
362+
"removeTest1",
363+
"X: removeTest2"),
364+
actualItems);
365+
366+
actualItems.clear();
367+
runCompletionTest("""
368+
foo.add|
369+
""",
370+
textDocumentService, printItems);
371+
assertEquals(List.of("addTest1",
372+
"X: addTest2"),
373+
actualItems);
374+
}
375+
308376
public void testNoResolveProvider() throws IOException {
309377
AtomicBoolean notInvoked = new AtomicBoolean();
310378

@@ -466,7 +534,7 @@ private void runAnyCompletionTest(String testCodeWithCaret,
466534
JEditorPane c = new JEditorPane();
467535
c.setEditorKit(new NbEditorKit());
468536
c.setDocument(doc);
469-
c.setCaretPosition(4);
537+
c.setCaretPosition(caret);
470538
runCompletion.accept(c);
471539
}
472540

0 commit comments

Comments
 (0)