You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by lk...@apache.org on 2020/11/04 04:02:32 UTC

[netbeans] branch master updated: [NETBEANS-4646] Fix completionInvoke hint in code templates

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

lkishalmi 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 a9871c5  [NETBEANS-4646] Fix completionInvoke hint in code templates
a9871c5 is described below

commit a9871c5085106f1ffd6c1c7ec594774185cf69d6
Author: Arthur Sadykov <ar...@mail.ru>
AuthorDate: Fri Oct 30 22:22:33 2020 +0500

    [NETBEANS-4646] Fix completionInvoke hint in code templates
---
 .../codetemplates/CodeTemplateInsertHandler.java   | 42 ++++--------
 .../codetemplates/CodeTemplateParameterImpl.java   |  8 +++
 .../textsync/TextRegionManagerEvent.java           | 11 ++++
 .../editor/codetemplates/textsync/TextSync.java    | 27 ++++++++
 .../CodeTemplateInsertHandlerTest.java             | 49 +++++++++++++-
 .../CodeTemplateParameterImplTest.java             | 77 ++++++++++++++++++++++
 6 files changed, 184 insertions(+), 30 deletions(-)

diff --git a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandler.java b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandler.java
index 0841c65..87f794a 100644
--- a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandler.java
+++ b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandler.java
@@ -99,8 +99,6 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
     
     private boolean released;
     
-    private boolean completionInvoke;
-    
     private TextRegion completeTextRegion;
 
     private String completeInsertString;
@@ -110,6 +108,8 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
     
     private TextSyncGroup textSyncGroup;
     
+    private boolean completionInvoked;
+    
     public CodeTemplateInsertHandler(
         CodeTemplate codeTemplate,
         JTextComponent component, 
@@ -224,12 +224,8 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
         for (CodeTemplateProcessor processor : processors) {
             processor.updateDefaultValues();
         }
-
         // Insert the template into document
         insertTemplate();
-
-        if (!isEditable())
-            checkInvokeCompletion();
     }
 
     void checkInsertTextBuilt() {
@@ -275,6 +271,10 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
         }
     }
 
+    boolean isCompletionInvoked() {
+        return completionInvoked;
+    }
+
     public void run() {
         boolean success = false;
         try {
@@ -321,7 +321,6 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
                 if (CodeTemplateParameter.CURSOR_PARAMETER_NAME.equals(master.getName())) {
                     // Add explicit ${cursor} as last into text sync group to jump to it by TAB as last param
                     caretTextRegion = masterImpl.textRegion(); 
-                    completionInvoke = master.getHints().get(CodeTemplateParameter.COMPLETION_INVOKE_HINT_NAME) != null;
                 } else {
                     textSyncGroup.addTextSync(masterImpl.textRegion().textSync());
                 }
@@ -457,18 +456,24 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
             textSync.setEditable(true);
         if (CodeTemplateParameter.CURSOR_PARAMETER_NAME.equals(paramImpl.getName()))
             textSync.setCaretMarker(true);
+        textSync.setCompletionInvoke(paramImpl.isCompletionInvoke());
     }
 
+    @Override
     public void stateChanged(TextRegionManagerEvent evt) {
+        completionInvoked = false;
         TextRegionManager trm = evt.textRegionManager();
         if (evt.isFocusChange()) {
+            TextSync activeTextSync = evt.activeTextSync();
+            if (activeTextSync != null && activeTextSync.isCompletionInvoke()) {
+                SwingUtilities.invokeLater(Completion.get()::showCompletion);
+                completionInvoked = true;
+            }
             List<TextSyncGroup<CodeTemplateInsertHandler>> removedGroups = evt.<CodeTemplateInsertHandler>removedGroups();
             for (int i = removedGroups.size() - 1; i >= 0; i--) {
                 CodeTemplateInsertHandler handler = removedGroups.get(i).clientInfo();
                 if (handler == this) {
                     release();
-                    if (isEditable())
-                        checkInvokeCompletion();
                     break;
                 }
             }
@@ -530,25 +535,6 @@ public final class CodeTemplateInsertHandler implements TextRegionManagerListene
         return parametrizedTextParser.buildInsertText(allParameters);
     }
 
-    private void checkInvokeCompletion() {
-        if (completionInvoke) {
-            completionInvoke = false;
-            SwingUtilities.invokeLater(new Runnable() {
-                public void run() {
-                    Completion.get().showCompletion();
-                }
-            });
-        }
-    }
-    
-    private boolean isEditable() {
-        for (CodeTemplateParameter param : masterParameters) {
-            if (param.isEditable())
-                return true;
-        }
-        return false;
-    }
-
     @Override
     public String toString() {
         return "Abbrev: \"" + codeTemplate.getAbbreviation() + "\"";
diff --git a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImpl.java b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImpl.java
index c17af35..74a26c4 100644
--- a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImpl.java
+++ b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImpl.java
@@ -78,6 +78,7 @@ public final class CodeTemplateParameterImpl {
     
     private boolean userModified;
 
+    private boolean completionInvoke;
 
     CodeTemplateParameterImpl(CodeTemplateInsertHandler handler,
     String parametrizedText, int parametrizedTextOffset) {
@@ -145,6 +146,10 @@ public final class CodeTemplateParameterImpl {
         return userModified;
     }
     
+    boolean isCompletionInvoke() {
+        return completionInvoke;
+    }
+    
     void markUserModified() {
         this.userModified = true;
     }
@@ -345,6 +350,9 @@ public final class CodeTemplateParameterImpl {
         }
         value = defaultValue;
         
+        String completionInvokeHint = getHints().get(CodeTemplateParameter.COMPLETION_INVOKE_HINT_NAME);
+        completionInvoke = Boolean.parseBoolean(completionInvokeHint);
+        
         if (name.equals(CodeTemplateParameter.CURSOR_PARAMETER_NAME)
                 || name.equals(CodeTemplateParameter.NO_FORMAT_PARAMETER_NAME)
                 || name.equals(CodeTemplateParameter.NO_INDENT_PARAMETER_NAME)) {
diff --git a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextRegionManagerEvent.java b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextRegionManagerEvent.java
index d2f3bc4..dd992c0 100644
--- a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextRegionManagerEvent.java
+++ b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextRegionManagerEvent.java
@@ -63,4 +63,15 @@ public final class TextRegionManagerEvent extends EventObject {
         return previousTextSync;
     }
 
+    /**
+     * Returns text sync for which the document modifications are being replicated across the respective regions.
+     * 
+     * @return active text sync, can be {@code null}.
+     * 
+     * @since 1.53
+     */
+    public TextSync activeTextSync() {
+        return textRegionManager().activeTextSync();
+    }
+
 }
diff --git a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextSync.java b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextSync.java
index 35b911d..d4c35c2 100644
--- a/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextSync.java
+++ b/ide/editor.codetemplates/src/org/netbeans/lib/editor/codetemplates/textsync/TextSync.java
@@ -35,6 +35,7 @@ public final class TextSync {
     
     private static int EDITABLE_FLAG = 1;
     private static int CARET_MARKER_FLAG = 2;
+    private static int COMPLETION_INVOKE_FLAG = 4;
 
     private TextSyncGroup<?> textSyncGroup;
     
@@ -140,6 +141,32 @@ public final class TextSync {
             flags &= ~CARET_MARKER_FLAG;
     }
 
+    /**
+     * Returns whether the code completion should be invoked when this text sync becomes active.
+     * 
+     * @return  {@code true} if the code completion should be invoked, {@code false} otherwise.
+     * 
+     * @since 1.53
+     */
+    public boolean isCompletionInvoke() {
+        return (flags & COMPLETION_INVOKE_FLAG) != 0;
+    }
+
+    /**
+     * Sets whether the code completion should be invoked when this text sync becomes active.
+     * 
+     * @param completionInvoke determines whether the code completion should be invoked.
+     * 
+     * @since 1.53
+     */
+    public void setCompletionInvoke(boolean completionInvoke) {
+        if (completionInvoke) {
+            flags |= COMPLETION_INVOKE_FLAG;
+        } else {
+            flags &= ~COMPLETION_INVOKE_FLAG;
+        }
+    }
+
     public void addRegion(TextRegion<?> region) {
         if (region == null)
             throw new IllegalArgumentException("region cannot be null");
diff --git a/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandlerTest.java b/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandlerTest.java
index 35b8760..a55e9e5 100644
--- a/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandlerTest.java
+++ b/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateInsertHandlerTest.java
@@ -19,17 +19,42 @@
 package org.netbeans.lib.editor.codetemplates;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.text.Document;
 import org.junit.Test;
-import static org.junit.Assert.*;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
+import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
 import org.netbeans.lib.editor.codetemplates.spi.CodeTemplateParameter;
+import org.netbeans.lib.editor.codetemplates.storage.CodeTemplateSettingsImpl;
+import org.netbeans.modules.editor.NbEditorKit;
 
 /**
  *
  * @author markiewb
  */
-public class CodeTemplateInsertHandlerTest {
+public class CodeTemplateInsertHandlerTest  extends NbTestCase {
+    
+    private CodeTemplateInsertHandler handler;
+    private CodeTemplateManager manager;
+    private JEditorPane editor;
 
+    public CodeTemplateInsertHandlerTest(String testName) {
+        super(testName);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        editor = new JEditorPane();
+        SwingUtilities.invokeAndWait(() -> editor.setEditorKit(new NbEditorKit()));
+        Document document = editor.getDocument();
+        manager = CodeTemplateManager.get(document);
+    }
+    
     @Test
     public void testPrioritizeParameters() {
         CodeTemplateSpiPackageAccessor get = CodeTemplateSpiPackageAccessor.get();
@@ -41,4 +66,24 @@ public class CodeTemplateInsertHandlerTest {
         assertEquals(Arrays.asList(paramC, paramB, paramA), prioritizeParameters);
     }
 
+    @Test
+    public void test_WhenActiveTextRegionHasCompletionInvokeHint_ThenInvokeCodeCompletion() {
+        CodeTemplate codeTemplate = manager.createTemporary("${param completionInvoke}");
+        handler = new CodeTemplateInsertHandler(
+                codeTemplate, editor, Collections.emptyList(), CodeTemplateSettingsImpl.OnExpandAction.FORMAT);
+        assertFalse(handler.isCompletionInvoked());
+        handler.insertTemplate();
+        assertTrue(handler.isCompletionInvoked());
+    }
+    
+    @Test
+    public void test_WhenActiveTextRegionHasNoCompletionInvokeHint_ThenDoNotInvokeCodeCompletion() {
+        CodeTemplate codeTemplate = manager.createTemporary("${param default=\"\"}");
+        handler = new CodeTemplateInsertHandler(
+                codeTemplate, editor, Collections.emptyList(), CodeTemplateSettingsImpl.OnExpandAction.FORMAT);
+        assertFalse(handler.isCompletionInvoked());
+        handler.insertTemplate();
+        assertFalse(handler.isCompletionInvoked());
+    }
+    
 }
diff --git a/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImplTest.java b/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImplTest.java
new file mode 100644
index 0000000..03e2b28
--- /dev/null
+++ b/ide/editor.codetemplates/test/unit/src/org/netbeans/lib/editor/codetemplates/CodeTemplateParameterImplTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.lib.editor.codetemplates;
+
+import java.util.Collections;
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.text.Document;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
+import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
+import org.netbeans.lib.editor.codetemplates.storage.CodeTemplateSettingsImpl;
+import org.netbeans.modules.editor.NbEditorKit;
+
+/**
+ *
+ * @author: Arthur Sadykov
+ */
+public class CodeTemplateParameterImplTest extends NbTestCase {
+
+    private CodeTemplateInsertHandler handler;
+
+    public CodeTemplateParameterImplTest(String testName) {
+        super(testName);
+    }
+
+    @Override
+    public void setUp() throws Exception  {
+        JEditorPane editor = new JEditorPane();
+        SwingUtilities.invokeAndWait(() -> editor.setEditorKit(new NbEditorKit()));
+        Document document = editor.getDocument();
+        CodeTemplateManager manager = CodeTemplateManager.get(document);
+        CodeTemplate codeTemplate = manager.createTemporary("${param}");
+        handler = new CodeTemplateInsertHandler(
+                codeTemplate, editor, Collections.emptyList(), CodeTemplateSettingsImpl.OnExpandAction.FORMAT);
+    }
+
+    public void test_WhenParameterNotContainsCompletionInvokeHint_ThenCompletionInvokeFieldMustBeSetToFalse() {
+        assertCompletionInvokeFieldIsSetToFalse("${param editable=true default=\"name\"}");
+    }
+
+    public void test_WhenParameterContainsCompletionInvokeHintSetToTrue_ThenCompletionInvokeFieldMustBeSetToTrue() {
+        assertCompletionInvokeFieldIsSetToTrue("${param editable=true completionInvoke}");
+        assertCompletionInvokeFieldIsSetToTrue("${param editable=true completionInvoke=true default=\"name\"}");
+    }
+
+    public void test_WhenParameterContainsCompletionInvokeHintSetToFalse_ThenCompletionInvokeFieldMustBeSetToFalse() {
+        assertCompletionInvokeFieldIsSetToFalse("${param editable=false completionInvoke=false}");
+        assertCompletionInvokeFieldIsSetToFalse("${param editable=true completionInvoke=\"maybe\" default=\"name\"}");
+    }
+
+    private void assertCompletionInvokeFieldIsSetToTrue(String parametrizedText) {
+        CodeTemplateParameterImpl parameterImpl = new CodeTemplateParameterImpl(handler, parametrizedText, 0);
+        assertTrue("Parameter must have completionInvoke hint set to true", parameterImpl.isCompletionInvoke());
+    }
+
+    private void assertCompletionInvokeFieldIsSetToFalse(String parametrizedText) {
+        CodeTemplateParameterImpl parameterImpl = new CodeTemplateParameterImpl(handler, parametrizedText, 0);
+        assertFalse("Parameter must have completionInvoke hint set to false", parameterImpl.isCompletionInvoke());
+    }
+}


---------------------------------------------------------------------
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