From b5e0253f6536df090816732e0a25e3c2618ebca0 Mon Sep 17 00:00:00 2001 From: Svata Dedic Date: Tue, 1 Aug 2023 13:51:57 +0200 Subject: [PATCH 1/2] #6278: Improved whitespace handling when stripping HTML. Centralize whitespace handling for quickpicks --- .../modules/java/lsp/server/Utils.java | 49 ++++++++++++++++--- .../lsp/server/protocol/LspTemplateUI.java | 19 +------ .../server/protocol/NbCodeClientWrapper.java | 13 ++++- .../server/ui/NotifyDescriptorAdapter.java | 6 ++- .../modules/java/lsp/server/UtilsTest.java | 32 ++++++++++++ .../server/protocol/LspTemplateUITest.java | 24 +++++++++ 6 files changed, 115 insertions(+), 28 deletions(-) diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/Utils.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/Utils.java index 011efefebedb..a4f04ce6629d 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/Utils.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/Utils.java @@ -41,7 +41,6 @@ import javax.lang.model.type.ArrayType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import javax.swing.text.BadLocationException; import javax.swing.text.StyledDocument; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; @@ -399,24 +398,34 @@ public static String encode2JSON(String value) { /** * Simple conversion from HTML to plaintext. Removes all html tags incl. attributes, - * replaces BR, P and HR tags with newlines. + * replaces BR, P and HR tags with newlines. The method optionally collapses whitespaces: + * all whitespace characters are replaced by spaces, adjacent spaces collapsed to single one, leading + * and trailing spaces removed. * @param s html text + * @param collapseWhitespaces to collapse * @return plaintext */ - public static String html2plain(String s) { + public static String html2plain(String s, boolean collapseWhitespaces) { + if (s == null) { + return null; + } boolean inTag = false; + boolean whitespace = false; + int tagStart = -1; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); - if (inTag) { + T: if (inTag) { boolean alpha = Character.isAlphabetic(ch); if (tagStart > 0 && !alpha) { String t = s.substring(tagStart, i).toLowerCase(Locale.ENGLISH); switch (t) { case "br": case "p": case "hr": // NOI1N - sb.append("\n"); - break; + ch ='\n'; // NOI18N + // continues to process 'ch' as if it came from the string, but `inTag` remains + // the same. + break T; } // prevent entering tagstart state again tagStart = -2; @@ -426,16 +435,40 @@ public static String html2plain(String s) { } else if (tagStart == -1 && alpha) { tagStart = i; } + continue; } else { if (ch == '<') { // NOI18N tagStart = -1; inTag = true; continue; } - sb.append(ch); } + if (collapseWhitespaces) { + if (ch == '\n') { + ch = ' '; + } + if (Character.isWhitespace(ch)) { + if (whitespace) { + continue; + } + ch = ' '; // NOI18N + whitespace = true; + } else { + whitespace = false; + } + } + sb.append(ch); } - return sb.toString(); + return collapseWhitespaces ? sb.toString().trim() : sb.toString(); } + /** + * Simple conversion from HTML to plaintext. Removes all html tags incl. attributes, + * replaces BR, P and HR tags with newlines. + * @param s html text + * @return plaintext + */ + public static String html2plain(String s) { + return html2plain(s, false); + } } diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUI.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUI.java index 65710539c0aa..2c5ae8967323 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUI.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUI.java @@ -50,6 +50,7 @@ import org.netbeans.api.project.SourceGroupModifier; import org.netbeans.api.templates.CreateDescriptor; import org.netbeans.api.templates.FileBuilder; +import org.netbeans.modules.java.lsp.server.Utils; import org.netbeans.modules.java.lsp.server.input.QuickPickItem; import org.netbeans.modules.java.lsp.server.input.ShowQuickPickParams; import org.netbeans.modules.java.lsp.server.input.ShowInputBoxParams; @@ -459,23 +460,7 @@ private static String findDetail(DataObject obj) { } static String stripHtml(String s) { - boolean inTag = false; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - if (inTag) { - if (ch == '>') { - inTag = false; - } - } else { - if (ch == '<') { - inTag = true; - continue; - } - sb.append(ch); - } - } - return sb.toString(); + return Utils.html2plain(s, true); } private static T raise(Class clazz, Exception ex) throws T { diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java index a11588d2b269..7cef6cec021d 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/NbCodeClientWrapper.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; import org.eclipse.lsp4j.ApplyWorkspaceEditParams; import org.eclipse.lsp4j.ApplyWorkspaceEditResponse; import org.eclipse.lsp4j.ConfigurationParams; @@ -37,6 +38,7 @@ import org.eclipse.lsp4j.WorkDoneProgressCreateParams; import org.eclipse.lsp4j.WorkspaceFolder; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.netbeans.modules.java.lsp.server.Utils; import org.netbeans.modules.java.lsp.server.input.QuickPickItem; import org.netbeans.modules.java.lsp.server.input.ShowQuickPickParams; import org.netbeans.modules.java.lsp.server.input.ShowMutliStepInputParams; @@ -86,7 +88,16 @@ public CompletableFuture execInHtmlPage(HtmlPageParams params) { @Override public CompletableFuture> showQuickPick(ShowQuickPickParams params) { - return remote.showQuickPick(params); + // vscode from version 1.80.2 displays control characters in quickpicks. Let's strip them: + ShowQuickPickParams copy = new ShowQuickPickParams( + params.getTitle(), params.getPlaceHolder(), params.getCanPickMany(), + params.getItems().stream().map( + i -> new QuickPickItem( + i.getLabel(), Utils.html2plain(i.getDescription(), true), Utils.html2plain(i.getDetail(), true), + i.isPicked(), i.getUserData()) + ).collect(Collectors.toList()) + ); + return remote.showQuickPick(copy); } @Override diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java index 1cf63a868057..96ab99ca0012 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ui/NotifyDescriptorAdapter.java @@ -45,6 +45,7 @@ import org.eclipse.lsp4j.MessageType; import org.eclipse.lsp4j.ShowMessageRequestParams; import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.netbeans.modules.java.lsp.server.Utils; import org.netbeans.modules.java.lsp.server.input.InputBoxStep; import org.netbeans.modules.java.lsp.server.input.InputCallbackParams; import org.netbeans.modules.java.lsp.server.input.InputService; @@ -372,7 +373,7 @@ public CompletableFuture clientNotifyCompletion( List items = new ArrayList<>(qpItems.size()); for (int i = 0; i < qpItems.size(); i++) { NotifyDescriptor.QuickPick.Item item = qpItems.get(i); - items.add(new QuickPickItem(item.getLabel(), item.getDescription(), null, item.isSelected(), Integer.toString(i))); + items.add(new QuickPickItem(item.getLabel(), Utils.html2plain(item.getDescription(), true), null, item.isSelected(), Integer.toString(i))); } ShowQuickPickParams params = new ShowQuickPickParams(qp.getLabel(), qp.getTitle(), qp.isMultipleSelection(), items); CompletableFuture> qpF = client.showQuickPick(params); @@ -431,7 +432,8 @@ public CompletableFuture> step(InputCallback List items = new ArrayList<>(); for (int i = 0; i < qpItems.size(); i++) { NotifyDescriptor.QuickPick.Item item = qpItems.get(i); - items.add(new QuickPickItem(item.getLabel(), item.getDescription(), null, item.isSelected(), Integer.toString(i))); + items.add(new QuickPickItem(item.getLabel(), + Utils.html2plain(item.getDescription(), true), null, item.isSelected(), Integer.toString(i))); } QuickPickStep step = new QuickPickStep(ci.getEstimatedNumberOfInputs(), stepId, null, input.getTitle(), ((NotifyDescriptor.QuickPick) input).isMultipleSelection(), diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/UtilsTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/UtilsTest.java index ae225926a3a2..24e997da75cf 100644 --- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/UtilsTest.java +++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/UtilsTest.java @@ -50,4 +50,36 @@ public void testEncode2JSON() { assertEquals("abcd", Utils.encode2JSON("abcd")); assertEquals("'\\\"\\b\\t\\n\\r\\\\", Utils.encode2JSON("'\"\b\t\n\r\\")); } + + @Test + public void testStripHtml() { + String s = "
Pre Text Post
"; + String expResult = "Pre Text Post"; + String result = Utils.html2plain(s); + assertEquals(expResult, result); + } + + /** + * All newlines should be removed + */ + @Test + public void testStripNewlines() { + String s = "\n
Pre \nText Post\n
"; + String expResult = "Pre Text Post"; + String result = Utils.html2plain(s, true); + assertEquals(expResult, result); + } + + + /** + * Consecutive whitespaces should be collapsed to a single space. Leading/trailing whitespaces + * removed. + */ + @Test + public void testStripConsecutiveWhitespces() { + String s = "\t
Pre Text\t \t\t Post
\t"; + String expResult = "Pre Text Post"; + String result = Utils.html2plain(s, true); + assertEquals(expResult, result); + } } diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUITest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUITest.java index 3d73f0d7099d..e1408434ab8e 100644 --- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUITest.java +++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUITest.java @@ -29,4 +29,28 @@ public void testStripHtml() { String result = LspTemplateUI.stripHtml(s); assertEquals(expResult, result); } + + /** + * All newlines should be removed + */ + @Test + public void testStripNewlines() { + String s = "\n
Pre \nText Post\n
"; + String expResult = "Pre Text Post"; + String result = LspTemplateUI.stripHtml(s); + assertEquals(expResult, result); + } + + + /** + * Consecutive whitespaces should be collapsed to a single space. Leading/trailing whitespaces + * removed. + */ + @Test + public void testStripConsecutiveWhitespces() { + String s = "\t
Pre Text\t \t\t Post
\t"; + String expResult = "Pre Text Post"; + String result = LspTemplateUI.stripHtml(s); + assertEquals(expResult, result); + } } From 748ef78152e9f91c7fd6e644e363bceb51577d9d Mon Sep 17 00:00:00 2001 From: Svata Dedic Date: Tue, 1 Aug 2023 13:54:01 +0200 Subject: [PATCH 2/2] Changelog update. --- java/java.lsp.server/vscode/CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/java/java.lsp.server/vscode/CHANGELOG.md b/java/java.lsp.server/vscode/CHANGELOG.md index 008dd31ecad5..343c12a92d8e 100644 --- a/java/java.lsp.server/vscode/CHANGELOG.md +++ b/java/java.lsp.server/vscode/CHANGELOG.md @@ -20,6 +20,17 @@ under the License. --> +## Version 19.0.0 +* Performance improvements in Maven projects loading and priming build +* Navigation for Micronaut URI and Beans in Find Symbol +* Allow for lazy computation of CodeActions +* Database support improvements: + * Generating Entity classes from database improved + * JDBC properties editing + * Display database schema tree improvements + * Adding OCI Autonomous database simplified + * Allow to reenter DB username and password + ## Version 18.0.0 * Java 8+ launch config renamed to Java+ @@ -150,4 +161,4 @@ * Progress bar for long running operation like build actions * Ability to cancel selected operations * Maven projects: Go to Definition source code action downloads and open Java source -* JavaDoc is shown when mouse hoovers over symbol +* JavaDoc is shown when mouse hoovers over symbol \ No newline at end of file