You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2021/09/17 08:00:11 UTC

[netbeans] branch master updated: LSP: Various Surround With refactoring fixes. (#3169)

This is an automated email from the ASF dual-hosted git repository.

dbalek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 907112b  LSP: Various Surround With refactoring fixes. (#3169)
907112b is described below

commit 907112b6c5966002d6462967c9a81a916886010e
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Fri Sep 17 09:59:53 2021 +0200

    LSP: Various Surround With refactoring fixes. (#3169)
---
 .../CodeTemplateCompletionProvider.java            | 16 ++++++---
 .../java/editor/resources/Bundle.properties        |  4 +++
 .../java/editor/resources/DefaultAbbrevs.xml       | 34 +++++++++++++++---
 .../java/lsp/server/protocol/SurroundWithHint.java | 41 +++++++++++++++++-----
 java/java.lsp.server/vscode/src/extension.ts       | 17 +++++++++
 5 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateCompletionProvider.java b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateCompletionProvider.java
index e0ec7e9..5a56179 100644
--- a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateCompletionProvider.java
+++ b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateCompletionProvider.java
@@ -89,8 +89,9 @@ public final class CodeTemplateCompletionProvider implements CompletionProvider
     public static class Collector implements CompletionCollector {
 
         private static final String SELECTED_TEXT_VAR = "${0:$TM_SELECTED_TEXT}";
-        private static final Pattern SNIPPET_VAR_PATTERN = Pattern.compile("\\$\\{\\s*([-\\w]++)([^}]*)?}");
-        private static final Pattern SNIPPET_HINT_PATTERN = Pattern.compile("([-\\w]++)(?:\\s*=\\s*(\\\"([^\\\"]*)\\\"|\\S*))?");
+        private static final Pattern SNIPPET_VAR_PATTERN = Pattern.compile("\\$\\{\\s*([-\\w]++)((?:\\s*[-\\w]++(?:\\s*=\\s*(?:\\\"[^\\\"]*\\\"|[-\\w]++))?)*\\s*)?}");
+        private static final Pattern SNIPPET_HINT_PATTERN = Pattern.compile("([-\\w]++)(?:\\s*=\\s*(\\\"([^\\\"]*)\\\"|[-\\w]++))?");
+        private static final String UNCAUGHT_EXCEPTION_CATCH_STATEMENTS = "uncaughtExceptionCatchStatements";
 
         @Override
         public boolean collectCompletions(Document doc, int offset, Completion.Context context, Consumer<Completion> consumer) {
@@ -100,8 +101,9 @@ public final class CodeTemplateCompletionProvider implements CompletionProvider
                     description = CodeTemplateApiPackageAccessor.get().getSingleLineText(ct);
                 }
                 String label = html2text(description.trim());
+                String sortText = String.format("%04d%s", 1650, "fore".equals(ct.getAbbreviation()) ? label.substring(0, 3) : label);
                 consumer.accept(CompletionCollector.newBuilder(label)
-                        .sortText(String.format("%04d%s", 1650, label))
+                        .sortText(sortText)
                         .documentation(() -> {
                             StringBuffer sb = new StringBuffer("<html><pre>");
                             ParametrizedTextParser.parseToHtml(sb, ct.getParametrizedText());
@@ -148,7 +150,9 @@ public final class CodeTemplateCompletionProvider implements CompletionProvider
                             if (defaultValue != null) {
                                 values.put(name, defaultValue);
                             }
-                            if ("false".equalsIgnoreCase(hints.get(CodeTemplateParameter.EDITABLE_HINT_NAME))) {
+                            if (hints.containsKey(UNCAUGHT_EXCEPTION_CATCH_STATEMENTS)) {
+                                sb.append("catch (${").append(last.incrementAndGet()).append(":Exception} ${").append(last.incrementAndGet()).append(":e}) {\n}");
+                            } else if ("false".equalsIgnoreCase(hints.get(CodeTemplateParameter.EDITABLE_HINT_NAME))) {
                                 nonEditables.add(name);
                                 sb.append(values.getOrDefault(name, ""));
                             } else {
@@ -171,7 +175,9 @@ public final class CodeTemplateCompletionProvider implements CompletionProvider
             Matcher matcher = SNIPPET_HINT_PATTERN.matcher(text);
             int idx = 0;
             while (matcher.find(idx)) {
-                hint2Values.put(matcher.group(1), matcher.groupCount() > 2 ? matcher.group(3) : matcher.groupCount() > 1 ? matcher.group(2) : null);
+                String insideString = matcher.groupCount() > 2 ? matcher.group(3) : null;
+                String value = matcher.groupCount() > 1 ? matcher.group(2) : null;
+                hint2Values.put(matcher.group(1), insideString!= null ? insideString : value);
                 idx = matcher.end();
             }
             return hint2Values;
diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/resources/Bundle.properties b/java/java.editor/src/org/netbeans/modules/java/editor/resources/Bundle.properties
index b1b2ef3..1816240 100644
--- a/java/java.editor/src/org/netbeans/modules/java/editor/resources/Bundle.properties
+++ b/java/java.editor/src/org/netbeans/modules/java/editor/resources/Bundle.properties
@@ -89,6 +89,10 @@ remove-surround-code-remain=Remove Surrounding Code (part to keep)
 # Code Templates
 CT_iff=if (<b>exp</b>) { ...| }
 CT_ifelse=if (<b>exp</b>) { ...| } else { ... }
+CT_sw=switch (<b>exp</b>) { ...| }
+CT_trycatch=try { ...| } catch(Exception e) { ... }
+CT_trycatchfin=try { ...| } catch(Exception e) { ... } finally { ... }
+CT_tryfin=try { ...| } finally { ... }
 CT_form=for (Map.Entry&lt;KeyType, ValueType&gt; <b>entry</b> : <b>map</b>.entrySet()) { ...
 CT_bcom=/* ... */
 
diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/resources/DefaultAbbrevs.xml b/java/java.editor/src/org/netbeans/modules/java/editor/resources/DefaultAbbrevs.xml
index 45d9e3c..0f65c96 100644
--- a/java/java.editor/src/org/netbeans/modules/java/editor/resources/DefaultAbbrevs.xml
+++ b/java/java.editor/src/org/netbeans/modules/java/editor/resources/DefaultAbbrevs.xml
@@ -58,7 +58,7 @@
     <codetemplate abbreviation="serr" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION"><code><![CDATA[System.err.println("${cursor}");]]></code></codetemplate> 
     <codetemplate abbreviation="sout" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION"><code><![CDATA[System.out.println("${cursor}");]]></code></codetemplate> 
     <codetemplate abbreviation="st"><code><![CDATA[${no-indent}static ]]></code></codetemplate> 
-    <codetemplate abbreviation="sw" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION">
+    <codetemplate abbreviation="sw" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION" descriptionId="CT_sw">
         <code>
 <![CDATA[switch (${var instanceof="java.lang.Enum"}) {
     case ${val completionInvoke}:
@@ -91,7 +91,13 @@
     } while (${expr instanceof="boolean" default="true"});
 ]]></code></codetemplate>
 
-    <codetemplate abbreviation="sy"><code><![CDATA[${no-indent}synchronized ]]></code></codetemplate> 
+    <codetemplate abbreviation="sy" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION">
+        <code>
+<![CDATA[synchronized (${OBJ instanceof="java.lang.Object" default="this"}) {
+    ${selection}${cursor}
+}]]>
+        </code>
+    </codetemplate>
     <codetemplate abbreviation="tds"><code><![CDATA[Thread.dumpStack();]]></code></codetemplate> 
     <codetemplate abbreviation="th"><code><![CDATA[${no-indent}throws ]]></code></codetemplate> 
     <codetemplate abbreviation="En"><code><![CDATA[${no-indent}Enumeration]]></code></codetemplate> 
@@ -250,11 +256,31 @@
 ]]>
         </code>
     </codetemplate>
-    <codetemplate abbreviation="trycatch" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION">
+    <codetemplate abbreviation="trycatch" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION" descriptionId="CT_trycatch">
         <code>
 <![CDATA[try {
     ${selection}${cursor}
-} ${CATCH_STMTS uncaughtExceptionCatchStatements default="catch (Exception e) {}" editable=false}
+} ${CATCH_STMTS uncaughtExceptionCatchStatements default="catch (Exception e) {
+}" editable=false}
+]]>
+        </code>
+    </codetemplate>
+    <codetemplate abbreviation="trycatchfin" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION" descriptionId="CT_trycatchfin">
+        <code>
+<![CDATA[try {
+    ${selection}${cursor}
+} ${CATCH_STMTS uncaughtExceptionCatchStatements default="catch (Exception e) {
+}" editable=false} finally {
+}
+]]>
+        </code>
+    </codetemplate>
+    <codetemplate abbreviation="tryfin" contexts="BLOCK,CASE,LABELED_STATEMENT,DO_WHILE_LOOP,ENHANCED_FOR_LOOP,FOR_LOOP,IF,WHILE_LOOP,LAMBDA_EXPRESSION" descriptionId="CT_tryfin">
+        <code>
+<![CDATA[try {
+    ${selection}${cursor}
+} finally {
+}
 ]]>
         </code>
     </codetemplate>
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
index 904815d..5aad8d4 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
@@ -29,6 +29,7 @@ import com.sun.source.util.Trees;
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -79,24 +80,28 @@ import org.openide.util.lookup.ServiceProvider;
 public final class SurroundWithHint extends CodeActionsProvider {
 
     private static final String COMMAND_INSERT_SNIPPET = "editor.action.insertSnippet";
+    private static final String COMMAND_SURROUND_WITH = "java.surround.with";
     private static final String DOTS = "...";
     private static final String SNIPPET = "snippet";
     private static final String SELECTION_VAR = "${selection}";
     private static final String SELECTED_TEXT_VAR = "${0:$TM_SELECTED_TEXT}";
-    private static final Pattern SNIPPET_VAR_PATTERN = Pattern.compile("\\$\\{\\s*([-\\w]++)([^}]*)?}");
-    private static final Pattern SNIPPET_HINT_PATTERN = Pattern.compile("([-\\w]++)(?:\\s*=\\s*(\\\"([^\\\"]*)\\\"|\\S*))?");
+    private static final Pattern SNIPPET_VAR_PATTERN = Pattern.compile("\\$\\{\\s*([-\\w]++)((?:\\s*[-\\w]++(?:\\s*=\\s*(?:\\\"[^\\\"]*\\\"|[-\\w]++))?)*\\s*)?}");
+    private static final Pattern SNIPPET_HINT_PATTERN = Pattern.compile("([-\\w]++)(?:\\s*=\\s*(\\\"([^\\\"]*)\\\"|[-\\w]++))?");
+    private static final String UNCAUGHT_EXCEPTION_CATCH_STATEMENTS = "uncaughtExceptionCatchStatements";
     private static final Set<String> TO_FILTER = Collections.singleton("fcom");
+    private static final Set<String> TO_SHOW = Collections.unmodifiableSet(new HashSet(Arrays.asList("bcom", "dowhile", "iff", "fore", "sy", "trycatch", "whilexp")));
 
     @Override
     @NbBundle.Messages({
-        "DN_SurroundWith=Surround with \"{0}\"",
+        "DN_SurroundWith=Surround with {0}",
+        "DN_SurroundWithAll=Surround with ...",
     })
     public List<CodeAction> getCodeActions(ResultIterator resultIterator, CodeActionParams params) throws Exception {
         CompilationController info = CompilationController.get(resultIterator.getParserResult());
         if (info == null) {
             return Collections.emptyList();
         }
-        info.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
+        info.toPhase(JavaSource.Phase.RESOLVED);
         int startOffset = getOffset(info, params.getRange().getStart());
         int endOffset = getOffset(info, params.getRange().getEnd());
         if (startOffset >= endOffset) {
@@ -110,6 +115,7 @@ public final class SurroundWithHint extends CodeActionsProvider {
         }
         Collection<? extends CodeTemplateFilter> filters = getTemplateFilters(doc, startOffset, endOffset);
         List<CodeAction> codeActions = new ArrayList<>();
+        List<QuickPickItem> items = new ArrayList<>();
         for (CodeTemplate codeTemplate : CodeTemplateManager.get(doc).getCodeTemplates()) {
             String parametrizedText = codeTemplate.getParametrizedText();
             if (parametrizedText.toLowerCase().contains(SELECTION_VAR) && !TO_FILTER.contains(codeTemplate.getAbbreviation())) {
@@ -127,14 +133,21 @@ public final class SurroundWithHint extends CodeActionsProvider {
                     if (sb.length() > 0) {
                         snippet = sb.append(snippet).toString();
                     }
-                    CodeAction codeAction = createCodeAction(Bundle.DN_SurroundWith(label), CodeActionKind.RefactorRewrite, COMMAND_INSERT_SNIPPET, Collections.singletonMap(SNIPPET, snippet));
+                    int idx = label.indexOf(' ');
+                    CodeAction codeAction = createCodeAction(Bundle.DN_SurroundWith(idx < 0 ? label : label.substring(0, idx)), CodeActionKind.RefactorRewrite, COMMAND_INSERT_SNIPPET, Collections.singletonMap(SNIPPET, snippet));
                     if (!edits.isEmpty()) {
                         codeAction.setEdit(new WorkspaceEdit(Collections.singletonMap(params.getTextDocument().getUri(), edits)));
                     }
-                    codeActions.add(codeAction);
+                    if (TO_SHOW.contains(codeTemplate.getAbbreviation())) {
+                        codeActions.add(codeAction);
+                    }
+                    items.add(new QuickPickItem(label, null, text, false, codeAction));
                 }
             }
         }
+        if (items.size() > codeActions.size()) {
+            codeActions.add(createCodeAction(Bundle.DN_SurroundWithAll(), CodeActionKind.RefactorRewrite, COMMAND_SURROUND_WITH, items));
+        }
         return codeActions;
     }
 
@@ -184,7 +197,9 @@ public final class SurroundWithHint extends CodeActionsProvider {
                 case CodeTemplateParameter.NO_INDENT_PARAMETER_NAME:
                     break;
                 case CodeTemplateParameter.SELECTION_PARAMETER_NAME:
-                    if (last != null) {
+                    if (last == null) {
+                        sb.append(' ');
+                    } else {
                         sb.append(SELECTED_TEXT_VAR);
                     }
                     break;
@@ -202,7 +217,13 @@ public final class SurroundWithHint extends CodeActionsProvider {
                         if (defaultValue != null) {
                             values.put(name, defaultValue);
                         }
-                        if ("false".equalsIgnoreCase(hints.get(CodeTemplateParameter.EDITABLE_HINT_NAME))) {
+                        if (hints.containsKey(UNCAUGHT_EXCEPTION_CATCH_STATEMENTS)) {
+                            if (last == null) {
+                                sb.append(defaultValue);
+                            } else {
+                                sb.append("catch (${").append(last.incrementAndGet()).append(":Exception} ${").append(last.incrementAndGet()).append(":e}) {\n}");
+                            }
+                        } else if ("false".equalsIgnoreCase(hints.get(CodeTemplateParameter.EDITABLE_HINT_NAME))) {
                             nonEditables.add(name);
                             sb.append(values.getOrDefault(name, ""));
                         } else {
@@ -231,7 +252,9 @@ public final class SurroundWithHint extends CodeActionsProvider {
         Matcher matcher = SNIPPET_HINT_PATTERN.matcher(text);
         int idx = 0;
         while (matcher.find(idx)) {
-            hint2Values.put(matcher.group(1), matcher.groupCount() > 2 ? matcher.group(3) : matcher.groupCount() > 1 ? matcher.group(2) : null);
+            String insideString = matcher.groupCount() > 2 ? matcher.group(3) : null;
+            String value = matcher.groupCount() > 1 ? matcher.group(2) : null;
+            hint2Values.put(matcher.group(1), insideString!= null ? insideString : value);
             idx = matcher.end();
         }
         return hint2Values;
diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts
index 706d66b..2b6723c 100644
--- a/java/java.lsp.server/vscode/src/extension.ts
+++ b/java/java.lsp.server/vscode/src/extension.ts
@@ -288,6 +288,23 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
             ]);
         }
     }));
+    context.subscriptions.push(commands.registerCommand('java.surround.with', async (items) => {
+        const selected: any = await window.showQuickPick(items, { placeHolder: 'Surround with ...' });
+        if (selected) {
+            if (selected.userData.edit && selected.userData.edit.changes) {
+                let edit = new vscode.WorkspaceEdit();
+                Object.keys(selected.userData.edit.changes).forEach(key => {
+                    edit.set(vscode.Uri.parse(key), selected.userData.edit.changes[key].map((change: any) => {
+                        let start = new vscode.Position(change.range.start.line, change.range.start.character);
+                        let end = new vscode.Position(change.range.end.line, change.range.end.character);
+                        return new vscode.TextEdit(new vscode.Range(start, end), change.newText);
+                    }));
+                });
+                await workspace.applyEdit(edit);
+            }
+            await commands.executeCommand(selected.userData.command.command, ...(selected.userData.command.arguments || []));
+        }
+    }));
     const runDebug = async (noDebug: boolean, testRun: boolean, uri: string, methodName?: string, launchConfiguration?: string) => {
         const docUri = uri ? vscode.Uri.file(uri) : window.activeTextEditor?.document.uri;
         if (docUri) {

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists