PY-16724 Multiline comments folding
authorLiana Bakradze <liana.bakradze@jetbrains.com>
Mon, 23 Nov 2015 12:34:34 +0000 (15:34 +0300)
committerLiana Bakradze <liana.bakradze@jetbrains.com>
Mon, 23 Nov 2015 12:34:34 +0000 (15:34 +0300)
python/src/com/jetbrains/python/PythonFoldingBuilder.java
python/testData/folding/multilineComments.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/PyFoldingTest.java

index ad3fc69879b49975e155f610fcd16d14c1c21308..a7b9c5003410e4a61f1d48ba1af63048b54b6e16 100644 (file)
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.LineTokenizer;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
 import com.jetbrains.python.psi.*;
@@ -78,6 +79,9 @@ public class PythonFoldingBuilder extends CustomFoldingBuilder implements DumbAw
     else if (FOLDABLE_COLLECTIONS_LITERALS.contains(elementType)) {
       foldCollectionLiteral(node, descriptors);
     }
+    else if (elementType == PyTokenTypes.END_OF_LINE_COMMENT) {
+      foldSequentialComments(node, descriptors);
+    }
     ASTNode child = node.getFirstChildNode();
     while (child != null) {
       appendDescriptors(child, descriptors);
@@ -85,6 +89,34 @@ public class PythonFoldingBuilder extends CustomFoldingBuilder implements DumbAw
     }
   }
 
+  private static void foldSequentialComments(ASTNode node, List<FoldingDescriptor> descriptors) {
+    //need to skip previous comments in sequence
+    ASTNode curNode = node.getTreePrev();
+    while (curNode != null) {
+      if (curNode.getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) {
+        return;
+      }
+      curNode = curNode.getPsi() instanceof PsiWhiteSpace ? curNode.getTreePrev() : null;
+    }
+
+    //fold sequence comments in one block
+    curNode = node.getTreeNext();
+    ASTNode lastCommentNode = node;
+    while (curNode != null) {
+      if (curNode.getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) {
+        lastCommentNode = curNode;
+        curNode = curNode.getTreeNext();
+        continue;
+      }
+      curNode = curNode.getPsi() instanceof PsiWhiteSpace ? curNode.getTreeNext() : null;
+    }
+
+    if (lastCommentNode != node) {
+      descriptors.add(new FoldingDescriptor(node, TextRange.create(node.getStartOffset(), lastCommentNode.getTextRange().getEndOffset())));
+    }
+
+  }
+
   private static void foldCollectionLiteral(ASTNode node, List<FoldingDescriptor> descriptors) {
     if (StringUtil.countNewLines(node.getChars()) > 0) {
       TextRange range = node.getTextRange();
diff --git a/python/testData/folding/multilineComments.py b/python/testData/folding/multilineComments.py
new file mode 100644 (file)
index 0000000..43b27c9
--- /dev/null
@@ -0,0 +1,15 @@
+<fold text='...'># the first line in comment
+#    the second line
+# the third line</fold>
+print("")
+<fold text='...'># multiline comment starts here
+#    line in comment
+# line in comment
+#    multiline comment ends here</fold>
+print("")
+
+<fold text='...'># one more comment
+#
+# one more comment
+#
+#</fold>
\ No newline at end of file
index a48c7c032adf0b75d186643c0de490b96426c4ae..77faeeb7ade13c572ff91446874fa8006d9a63ad 100644 (file)
@@ -53,4 +53,8 @@ public class PyFoldingTest extends PyTestCase {
     doTest();
   }
 
+  public void testMultilineComments() {
+    doTest();
+  }
+
 }