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

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

commit 45bf3b3beec5ee7bb1c41778a2be8ebb8b3a2f95
Author: Arthur Sadykov <arthur-sady...@mail.ru>
AuthorDate: Fri Oct 23 06:08:21 2020 +0500

    [NETBEANS-3588] Code Templates not working in Java Editor in for loops 
(#2444)
    
    * [NETBEANS-3588] Code Templates not working in Java Editor in for loops
    
    * [NETBEANS-3588] Code Templates not working in Java Editor in for loops
---
 .../editor/java/JavaCodeTemplateFilter.java        | 175 ++++++++++++---------
 .../editor/java/JavaCodeTemplateProcessorTest.java |  47 +++++-
 2 files changed, 150 insertions(+), 72 deletions(-)

diff --git 
a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCodeTemplateFilter.java
 
b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCodeTemplateFilter.java
index 3d8b6ef..bbfbe4f 100644
--- 
a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCodeTemplateFilter.java
+++ 
b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCodeTemplateFilter.java
@@ -20,27 +20,28 @@
 package org.netbeans.modules.editor.java;
 
 import com.sun.source.tree.Tree;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Logger;
 import javax.swing.text.JTextComponent;
-
 import com.sun.source.tree.CaseTree;
 import com.sun.source.tree.ClassTree;
 import com.sun.source.tree.ExpressionTree;
 import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
 import org.netbeans.api.java.lexer.JavaTokenId;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.JavaSource.Phase;
 import org.netbeans.api.java.source.SourceUtils;
 import org.netbeans.api.java.source.TreeUtilities;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenId;
 import org.netbeans.api.lexer.TokenSequence;
-import org.netbeans.api.progress.ProgressUtils;
+import org.netbeans.api.progress.BaseProgressUtils;
 import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
 import org.netbeans.lib.editor.codetemplates.spi.CodeTemplateFilter;
 import org.netbeans.modules.parsing.api.ParserManager;
@@ -58,7 +59,6 @@ import org.openide.util.NbBundle;
  */
 public class JavaCodeTemplateFilter implements CodeTemplateFilter {
     
-    private static final Logger LOG = 
Logger.getLogger(JavaCodeTemplateFilter.class.getName());
     private static final String EXPRESSION = "EXPRESSION"; //NOI18N
     private static final String CLASS_HEADER = "CLASS_HEADER"; //NOI18N
     
@@ -72,88 +72,121 @@ public class JavaCodeTemplateFilter implements 
CodeTemplateFilter {
             final Source source = Source.create(component.getDocument());
             if (source != null) {
                 final AtomicBoolean cancel = new AtomicBoolean();
-                ProgressUtils.runOffEventDispatchThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            ParserManager.parse(Collections.singleton(source), 
new UserTask() {
-                                @Override
-                                public void run(ResultIterator resultIterator) 
throws Exception {
-                                    if (cancel.get()) {
-                                        return;
+                BaseProgressUtils.runOffEventDispatchThread(() -> {
+                    try {
+                        ParserManager.parse(Collections.singleton(source), new 
UserTask() {
+                            @Override
+                            public void run(ResultIterator resultIterator) 
throws Exception {
+                                if (cancel.get()) {
+                                    return;
+                                }
+                                Parser.Result result = 
resultIterator.getParserResult(startOffset);
+                                CompilationController controller = result != 
null ? CompilationController.get(result) : null;
+                                if (controller != null && 
Phase.PARSED.compareTo(controller.toPhase(Phase.PARSED)) <= 0) {
+                                    TreeUtilities tu = 
controller.getTreeUtilities();
+                                    int eo = endOffset;
+                                    int so = startOffset;
+                                    if (so >= 0) {
+                                        so = 
result.getSnapshot().getEmbeddedOffset(startOffset);
                                     }
-                                    Parser.Result result = 
resultIterator.getParserResult(startOffset);
-                                    CompilationController controller = result 
!= null ? CompilationController.get(result) : null;
-                                    if (controller != null && 
Phase.PARSED.compareTo(controller.toPhase(Phase.PARSED)) <= 0) {
-                                        TreeUtilities tu = 
controller.getTreeUtilities();
-                                        int eo = endOffset;
-                                        int so = startOffset;
-                                        if (so >= 0) {
-                                            so = 
result.getSnapshot().getEmbeddedOffset(startOffset);
-                                        }
-                                        if (endOffset >= 0) {
-                                            eo = 
result.getSnapshot().getEmbeddedOffset(endOffset);
-                                            TokenSequence<JavaTokenId> ts = 
SourceUtils.getJavaTokenSequence(controller.getTokenHierarchy(), so);
-                                            int delta = ts.move(so);
+                                    if (endOffset >= 0) {
+                                        eo = 
result.getSnapshot().getEmbeddedOffset(endOffset);
+                                        TokenSequence<JavaTokenId> ts = 
SourceUtils.getJavaTokenSequence(controller.getTokenHierarchy(), so);
+                                        int delta = ts.move(so);
+                                        if (delta == 0 || ts.moveNext() && 
ts.token().id() == JavaTokenId.WHITESPACE) {
+                                            delta = ts.move(eo);
                                             if (delta == 0 || ts.moveNext() && 
ts.token().id() == JavaTokenId.WHITESPACE) {
-                                                delta = ts.move(eo);
-                                                if (delta == 0 || 
ts.moveNext() && ts.token().id() == JavaTokenId.WHITESPACE) {
-                                                    String selectedText = 
controller.getText().substring(so, eo).trim();
-                                                    SourcePositions[] sp = new 
SourcePositions[1];
-                                                    ExpressionTree expr = 
selectedText.length() > 0 ? tu.parseExpression(selectedText, sp) : null;
-                                                    if (expr != null && 
expr.getKind() != Tree.Kind.IDENTIFIER && !Utilities.containErrors(expr) && 
sp[0].getEndPosition(null, expr) >= selectedText.length()) {
-                                                        stringCtx = EXPRESSION;
-                                                    }
+                                                String selectedText = 
controller.getText().substring(so, eo).trim();
+                                                SourcePositions[] sp = new 
SourcePositions[1];
+                                                ExpressionTree expr = 
selectedText.length() > 0 ? tu.parseExpression(selectedText, sp) : null;
+                                                if (expr != null && 
expr.getKind() != Tree.Kind.IDENTIFIER && !Utilities.containErrors(expr) && 
sp[0].getEndPosition(null, expr) >= selectedText.length()) {
+                                                    stringCtx = EXPRESSION;
                                                 }
                                             }
                                         }
-                                        Tree tree = tu.pathFor(so).getLeaf();
-                                        if (eo >= 0 && so != eo) {
-                                            if (tu.pathFor(eo).getLeaf() != 
tree) {
-                                                return;
-                                            }
+                                    }
+                                    Tree tree = tu.pathFor(so).getLeaf();
+                                    if (eo >= 0 && so != eo) {
+                                        if (tu.pathFor(eo).getLeaf() != tree) {
+                                            return;
                                         }
-                                        treeKindCtx = tree.getKind();
-                                        switch (treeKindCtx) {
-                                            case CASE:
-                                                if (so < 
controller.getTrees().getSourcePositions().getEndPosition(controller.getCompilationUnit(),
 ((CaseTree)tree).getExpression())) {
-                                                    treeKindCtx = null;
-                                                }
-                                                break;
-                                            case CLASS:
-                                                SourcePositions sp = 
controller.getTrees().getSourcePositions();
-                                                int startPos = 
(int)sp.getEndPosition(controller.getCompilationUnit(), 
((ClassTree)tree).getModifiers());
-                                                if (startPos <= 0) {
-                                                    startPos = 
(int)sp.getStartPosition(controller.getCompilationUnit(), tree);
-                                                }
-                                                String headerText = 
controller.getText().substring(startPos, so);
-                                                int idx = 
headerText.indexOf('{'); //NOI18N
-                                                if (idx < 0) {
-                                                    treeKindCtx = null;
-                                                    stringCtx = CLASS_HEADER;
-                                                }
-                                                break;
-                                            case FOR_LOOP:
-                                            case ENHANCED_FOR_LOOP:
-                                            case WHILE_LOOP:
-                                                sp = 
controller.getTrees().getSourcePositions();
+                                    }
+                                    treeKindCtx = tree.getKind();
+                                    switch (treeKindCtx) {
+                                        case CASE:
+                                            if (so < 
controller.getTrees().getSourcePositions().getEndPosition(controller.getCompilationUnit(),
 ((CaseTree)tree).getExpression())) {
+                                                treeKindCtx = null;
+                                            }
+                                            break;
+                                        case CLASS:
+                                            SourcePositions sp = 
controller.getTrees().getSourcePositions();
+                                            int startPos = 
(int)sp.getEndPosition(controller.getCompilationUnit(), 
((ClassTree)tree).getModifiers());
+                                            if (startPos <= 0) {
                                                 startPos = 
(int)sp.getStartPosition(controller.getCompilationUnit(), tree);
-                                                String text = 
controller.getText().substring(startPos, so);
-                                                if 
(!text.trim().endsWith(")")) {
+                                            }
+                                            String headerText = 
controller.getText().substring(startPos, so);
+                                            int idx = headerText.indexOf('{'); 
//NOI18N
+                                            if (idx < 0) {
+                                                treeKindCtx = null;
+                                                stringCtx = CLASS_HEADER;
+                                            }
+                                            break;
+                                        case FOR_LOOP:
+                                        case ENHANCED_FOR_LOOP:
+                                            if 
(!isRightParenthesisOfLoopPresent(controller, so)) {
+                                                treeKindCtx = null;
+                                            }
+                                            break;
+                                        case PARENTHESIZED:
+                                            if (isPartOfWhileLoop(controller, 
so)) {
+                                                if 
(!isRightParenthesisOfLoopPresent(controller, so)) {
                                                     treeKindCtx = null;
                                                 }
-                                        }
+                                            }
+                                            break;
                                     }
                                 }
-                            });
-                        } catch (ParseException ex) {
-                            Exceptions.printStackTrace(ex);
-                        }
+                            }
+                        });
+                    } catch (ParseException ex) {
+                        Exceptions.printStackTrace(ex);
                     }
                 }, NbBundle.getMessage(JavaCodeTemplateProcessor.class, 
"JCT-init"), cancel, false); //NOI18N
             }
         }
     }
+    
+    private boolean isRightParenthesisOfLoopPresent(CompilationController 
controller, int abbrevStartOffset) {
+        TokenHierarchy<?> tokenHierarchy = controller.getTokenHierarchy();
+        TokenSequence<?> tokenSequence = tokenHierarchy.tokenSequence();
+        tokenSequence.move(abbrevStartOffset);
+        if (tokenSequence.moveNext()) {
+            TokenId tokenId = skipNextWhitespaces(tokenSequence);
+            return tokenId == null ? false : (tokenId == JavaTokenId.RPAREN);
+        }
+        return false;
+    }
+    
+    private TokenId skipNextWhitespaces(TokenSequence<?> tokenSequence) {
+        TokenId tokenId = null;
+        while (tokenSequence.moveNext()) {
+            Token<?> token = tokenSequence.token();
+            if (token != null) {
+                tokenId = token.id();
+            }
+            if (tokenId != JavaTokenId.WHITESPACE) {
+                break;
+            }
+        }
+        return tokenId;
+    }
+    
+    private boolean isPartOfWhileLoop(CompilationController controller, int 
abbrevStartOffset) {
+        TreeUtilities treeUtilities = controller.getTreeUtilities();
+        TreePath currentPath = treeUtilities.pathFor(abbrevStartOffset);
+        TreePath parentPath = 
treeUtilities.getPathElementOfKind(Tree.Kind.WHILE_LOOP, currentPath);
+        return parentPath != null;
+    }
 
     @Override
     public synchronized boolean accept(CodeTemplate template) {
diff --git 
a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaCodeTemplateProcessorTest.java
 
b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaCodeTemplateProcessorTest.java
index 08b5d41..e4843ca 100644
--- 
a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaCodeTemplateProcessorTest.java
+++ 
b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaCodeTemplateProcessorTest.java
@@ -157,7 +157,52 @@ public class JavaCodeTemplateProcessorTest extends 
NbTestCase {
                              "}");
         assertFileObjectTextMatchesRegex("(?s)\\s*?public class Test.*?");
     }
-    
+
+    public void testCodeTemplatesShouldWorkInsideParenthesesOfForEachLoop() 
throws Exception {
+         doTestTemplateInsert("${name newVarName}",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        for (String |) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        for (String name|) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}");
+         doTestTemplateInsert("${names iterable}",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        for (String name: |) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        for (String name: args|) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}");
+    }
+
+    public void testCodeTemplatesShouldWorkInsideParenthesesOfWhileLoop() 
throws Exception {
+         doTestTemplateInsert("${list 
instanceof=\"java.util.List\"}.isEmpty()",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        while (|) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}",
+                             "public class Test {\n" +
+                             "    private void t(String... args) {\n" +
+                             "        while (list|.isEmpty()) {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}");
+    }
+
     private void assertFileObjectTextMatchesRegex(String regex) throws 
IOException {
         String text = testFile.asText();
         assertTrue("The file text must match the regular expression", 
text.matches(regex));


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

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

Reply via email to