Stylus. Parsing of mixins implemented
authorAndrey Vokin <andrey.vokin@jetbrains.com>
Mon, 15 Jul 2013 11:46:10 +0000 (15:46 +0400)
committerAndrey Vokin <andrey.vokin@jetbrains.com>
Wed, 17 Jul 2013 08:04:56 +0000 (12:04 +0400)
platform/lang-impl/src/com/intellij/indentation/AbstractIndentParser.java

index ba29c5def7ff4616ab47f087edfc4a734af3fb4c..da1920e4040e4b9d68c77ac2690598a308f35d0e 100644 (file)
@@ -6,6 +6,7 @@ import com.intellij.lang.PsiParser;
 import com.intellij.psi.TokenType;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
+import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -18,23 +19,39 @@ public abstract class AbstractIndentParser implements PsiParser {
 
   private int myCurrentIndent;
 
+  private HashMap<PsiBuilder.Marker, Integer> myIndents;
+  private HashMap<PsiBuilder.Marker, Boolean> myNewLines;
+
   private boolean myNewLine = true;
 
   @NotNull
   public ASTNode parse(IElementType root, PsiBuilder builder) {
+    myNewLines = new HashMap<PsiBuilder.Marker, Boolean>();
+    myIndents = new HashMap<PsiBuilder.Marker, Integer>();
     myBuilder = builder;
-    myBuilder.setDebugMode(true);
     parseRoot(root);
     return myBuilder.getTreeBuilt();
   }
 
   protected abstract void parseRoot(IElementType root);
 
+  public PsiBuilder.Marker mark(boolean couldBeRolledBack) {
+    final PsiBuilder.Marker marker = myBuilder.mark();
+    if (couldBeRolledBack) {
+      myIndents.put(marker, myCurrentIndent);
+      myNewLines.put(marker, myNewLine);
+    }
+    return marker;
+  }
+
   public PsiBuilder.Marker mark() {
-    return myBuilder.mark();
+    return mark(false);
   }
 
   public void done(@NotNull final PsiBuilder.Marker marker, @NotNull final IElementType elementType) {
+    myIndents.remove(marker);
+    myNewLines.remove(marker);
+
     marker.done(elementType);
   }
 
@@ -47,24 +64,15 @@ public abstract class AbstractIndentParser implements PsiParser {
   }
 
   protected void rollbackTo(@NotNull final PsiBuilder.Marker marker) {
-    marker.rollbackTo();
-
-    myNewLine = rawLookup(-1) == null || tokenIn(rawLookup(-1), getIndentElementType(), getEolElementType());
-
-    //recount indent
-    //duty hack for current indent calculation. it's not me started all this crap.
-    int step = 0;
-    while (rawLookup(step) != null && !tokenIn(rawLookup(step), getEolElementType())) {
-      step--;
-    }
-    step++;
-    int indentStartOffset = myBuilder.rawTokenTypeStart(step);
-    int indentStopOffset = indentStartOffset;
-    while (tokenIn(rawLookup(step), getIndentElementType(), TokenType.WHITE_SPACE)) {
-      step++;
-      indentStopOffset = myBuilder.rawTokenTypeStart(step);
+    if (myIndents.get(marker) == null) {
+      throw new RuntimeException("Parser can't rollback marker that was created by mark() method, use mark(true) instead");
     }
-    myCurrentIndent = indentStopOffset - indentStartOffset;
+    myCurrentIndent = myIndents.get(marker);
+    myNewLine = myNewLines.get(marker);
+
+    myIndents.remove(marker);
+    myNewLines.remove(marker);
+    marker.rollbackTo();
   }
 
   protected boolean eof() {