CPP-3103: Conditionally uncompiled code unexpectedly formatted
authorAlexey Utkin <alexey.utkin@jetbrains.com>
Fri, 22 May 2015 08:56:16 +0000 (11:56 +0300)
committerAlexey Utkin <alexey.utkin@jetbrains.com>
Fri, 22 May 2015 09:33:31 +0000 (12:33 +0300)
java/java-impl/src/com/intellij/psi/impl/source/codeStyle/PsiBasedFormatterModelWithShiftIndentInside.java
platform/lang-api/src/com/intellij/formatting/FormattingModel.java
platform/lang-api/src/com/intellij/formatting/FormattingModelWithShiftIndentInsideDocumentRange.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/formatting/DelegatingFormattingModel.java
platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
platform/lang-impl/src/com/intellij/psi/formatter/DocumentBasedFormattingModel.java
platform/lang-impl/src/com/intellij/psi/formatter/PsiBasedFormattingModel.java
platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
platform/platform-tests/testSrc/com/intellij/formatting/TestFormattingModel.java
xml/impl/src/com/intellij/lang/xml/XmlFormattingModel.java

index 9782b56305004a564bc81d92704f196cac780d1f..7fffb41fb6dcf9d0323d8c8950abafb77e56f7d2 100644 (file)
@@ -34,7 +34,6 @@ import com.intellij.psi.formatter.FormattingDocumentModelImpl;
 import com.intellij.psi.formatter.PsiBasedFormattingModel;
 import com.intellij.psi.impl.source.tree.TreeUtil;
 import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.xml.XmlElementType;
 import com.intellij.psi.xml.XmlTokenType;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -53,21 +52,14 @@ public class PsiBasedFormatterModelWithShiftIndentInside extends PsiBasedFormatt
   }
 
   @Override
-  public TextRange shiftIndentInsideRange(TextRange textRange, int shift) {
-    return shiftIndentInsideWithPsi(textRange, shift);
+  public TextRange shiftIndentInsideRange(ASTNode node, TextRange textRange, int shift) {
+    return shiftIndentInsideWithPsi(node, textRange, shift);
   }
 
 
-  private TextRange shiftIndentInsideWithPsi(final TextRange textRange, final int shift) {
-    final int offset = textRange.getStartOffset();
-
-    ASTNode leafElement = findElementAt(offset);
-    while (leafElement != null && !leafElement.getTextRange().equals(textRange)) {
-      leafElement = leafElement.getTreeParent();
-    }
-
-    if (leafElement != null && leafElement.getTextRange().equals(textRange) && ShiftIndentInsideHelper.mayShiftIndentInside(leafElement)) {
-      return new ShiftIndentInsideHelper(StdFileTypes.JAVA, myProject).shiftIndentInside(leafElement, shift).getTextRange();
+  private TextRange shiftIndentInsideWithPsi(ASTNode node, final TextRange textRange, final int shift) {
+    if (node != null && node.getTextRange().equals(textRange) && ShiftIndentInsideHelper.mayShiftIndentInside(node)) {
+      return new ShiftIndentInsideHelper(StdFileTypes.JAVA, myProject).shiftIndentInside(node, shift).getTextRange();
     } else {
       return textRange;
     }
index 1663cc77df8d05561e6799cf3675e2e71bbdd797..cf0a56b1b36488af5245fb0c55a793534b5645bc 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.formatting;
 
+import com.intellij.lang.ASTNode;
 import com.intellij.openapi.util.TextRange;
 import org.jetbrains.annotations.NotNull;
 
@@ -68,11 +69,13 @@ public interface FormattingModel {
    * Indents every line except for the first in the specified text range representing a multiline block
    * by the specified amount.
    *
+   *
+   * @param node the owner of the text range, if defined
    * @param range  the text range to indent.
    * @param indent the amount by which every line should be indented.
    * @return the text range covering the block with added indents.
    */
-  TextRange shiftIndentInsideRange(TextRange range, int indent);
+  TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent);
 
   /**
    * Commits the changes made by the formatter to the document. Called after the formatter
diff --git a/platform/lang-api/src/com/intellij/formatting/FormattingModelWithShiftIndentInsideDocumentRange.java b/platform/lang-api/src/com/intellij/formatting/FormattingModelWithShiftIndentInsideDocumentRange.java
new file mode 100644 (file)
index 0000000..11a9cdb
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed 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 com.intellij.formatting;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.util.TextRange;
+
+/**
+ * Defines the formatting model that is responsible for multi-line AST nodes indentation
+ * at the stage of document-based formatting. The [shiftIndentInsideDocumentRange] method
+ * is called in the model, instead of standard procedure.
+ */
+public interface FormattingModelWithShiftIndentInsideDocumentRange extends FormattingModelEx {
+  /**
+   * Indents every line except for the first in the specified text range representing a multiline block
+   * by the specified amount.
+   *
+   * @param document the document for modification.
+   * @param node     the owner of the text range, if defined
+   * @param range    the text range to indent.
+   * @param indent   the amount by which every line should be indented.
+   * @return the text range covering the block with added indents or null for call of default procedure.
+   */
+  TextRange shiftIndentInsideDocumentRange(Document document, ASTNode node, TextRange range, int indent);
+
+  String adjustWhiteSpaceInsideDocument(ASTNode afterNode, String whiteSpace);
+}
index edce2ee8d443537980e419c30f96aff60a5e003c..866007bf32a74237a573d0fe2937c982d96f0395 100644 (file)
@@ -57,8 +57,8 @@ public class DelegatingFormattingModel implements FormattingModelEx {
   }
 
   @Override
-  public TextRange shiftIndentInsideRange(TextRange range, int indent) {
-    return myBaseModel.shiftIndentInsideRange(range, indent);
+  public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) {
+    return myBaseModel.shiftIndentInsideRange(node, range, indent);
   }
 
   @Override
index c5e30b3183dd0987cd4e5079181c060dbaa38b32..50a8e7ab1fc0019690092cca52ad19691c1e4bb4 100644 (file)
@@ -427,7 +427,7 @@ class FormatProcessor {
       final int shiftInside = calcShift(oldBlockIndent, whiteSpaceIndent, options);
 
       if (shiftInside != 0 || !oldBlockIndent.equals(whiteSpaceIndent)) {
-        final TextRange newBlockRange = model.shiftIndentInsideRange(currentBlockRange, shiftInside);
+        final TextRange newBlockRange = model.shiftIndentInsideRange(block.getNode(), currentBlockRange, shiftInside);
         shift += newBlockRange.getLength() - block.getLength();
       }
     }
index 92b29cb88df7ecdc0e9d3a224efd5a2f394ba935..2fa65d513eebced9e7bbed22e800c0da304866ff 100644 (file)
@@ -18,7 +18,9 @@ package com.intellij.psi.formatter;
 
 import com.intellij.formatting.Block;
 import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.formatting.FormattingModel;
 import com.intellij.formatting.FormattingModelEx;
+import com.intellij.formatting.FormattingModelWithShiftIndentInsideDocumentRange;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileTypes.FileType;
@@ -40,12 +42,14 @@ import org.jetbrains.annotations.Nullable;
 public class DocumentBasedFormattingModel implements FormattingModelEx {
   private final Block                   myRootBlock;
   private final FormattingDocumentModel myDocumentModel;
+  @Nullable private final FormattingModel myOriginalFormattingModel;
   @NotNull private final Document       myDocument;
   private final Project                 myProject;
   private final CodeStyleSettings       mySettings;
   private final FileType                myFileType;
   private final PsiFile                 myFile;
 
+  @Deprecated
   public DocumentBasedFormattingModel(final Block rootBlock,
                                       @NotNull final Document document,
                                       final Project project,
@@ -59,6 +63,7 @@ public class DocumentBasedFormattingModel implements FormattingModelEx {
     myFileType = fileType;
     myFile = file;
     myDocumentModel = new FormattingDocumentModelImpl(document,file);
+    myOriginalFormattingModel = null;
   }
 
   public DocumentBasedFormattingModel(final Block rootBlock,
@@ -73,6 +78,23 @@ public class DocumentBasedFormattingModel implements FormattingModelEx {
     myFile = file;
     myDocumentModel = FormattingDocumentModelImpl.createOn(file);
     myDocument = myDocumentModel.getDocument();
+    myOriginalFormattingModel = null;
+  }
+
+  public DocumentBasedFormattingModel(@NotNull final FormattingModel originalModel,
+                                      @NotNull final Document document,
+                                      final Project project,
+                                      final CodeStyleSettings settings,
+                                      final FileType fileType,
+                                      final PsiFile file) {
+    myOriginalFormattingModel = originalModel;
+    myRootBlock = originalModel.getRootBlock();
+    myDocument = document;
+    myProject = project;
+    mySettings = settings;
+    myFileType = fileType;
+    myFile = file;
+    myDocumentModel = new FormattingDocumentModelImpl(document,file);
   }
 
   @Override
@@ -95,6 +117,12 @@ public class DocumentBasedFormattingModel implements FormattingModelEx {
 
   @Override
   public TextRange replaceWhiteSpace(TextRange textRange, ASTNode nodeAfter, String whiteSpace) {
+    if (myOriginalFormattingModel instanceof FormattingModelWithShiftIndentInsideDocumentRange) {
+      whiteSpace = ((FormattingModelWithShiftIndentInsideDocumentRange)myOriginalFormattingModel).adjustWhiteSpaceInsideDocument(
+        nodeAfter,
+        whiteSpace);
+    }
+
     boolean removesStartMarker;
     String marker;
 
@@ -144,7 +172,14 @@ public class DocumentBasedFormattingModel implements FormattingModelEx {
   }
 
   @Override
-  public TextRange shiftIndentInsideRange(TextRange range, int indent) {
+  public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) {
+    if (myOriginalFormattingModel instanceof FormattingModelWithShiftIndentInsideDocumentRange) {
+      final TextRange newRange =
+        ((FormattingModelWithShiftIndentInsideDocumentRange)myOriginalFormattingModel).shiftIndentInsideDocumentRange(myDocument, node, range, indent);
+      if (newRange != null)
+        return newRange;
+    }
+
     final int newLength = shiftIndentInside(range, indent);
     return new TextRange(range.getStartOffset(), range.getStartOffset() + newLength);
   }
index e2a0958c4e2a39275ba4234345640d4efc1e97f0..9f0d00dde356c0a75d949ec147812656d27cab32 100644 (file)
@@ -73,7 +73,7 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
   }
 
   @Override
-  public TextRange shiftIndentInsideRange(TextRange textRange, int shift) {
+  public TextRange shiftIndentInsideRange(ASTNode node, TextRange textRange, int shift) {
     return textRange; // TODO: Remove this method from here...
   }
 
index f1cf75b4a2febff7a6bf50b81d07afef4fba5cc4..16cf2ef6271e9d2819b567c59474b39c4c2cc93c 100644 (file)
@@ -228,7 +228,7 @@ public class CodeFormatterFacade {
           }
 
           final FormattingModel originalModel = CoreFormatterUtil.buildModel(builder, file, mySettings, FormattingMode.REFORMAT);
-          final FormattingModel model = new DocumentBasedFormattingModel(originalModel.getRootBlock(),
+          final FormattingModel model = new DocumentBasedFormattingModel(originalModel,
                                                                          document,
                                                                          project, mySettings, file.getFileType(), file);
 
index c220e5078f2746c509642ae1c5d4b7e1aae68cee..60e41cc7963544108d5c78764789abc4f644b40e 100644 (file)
@@ -99,7 +99,7 @@ abstract class CodeStyleManagerRunnable<T> {
       myModel = CoreFormatterUtil.buildModel(builder, file, mySettings, myMode);
 
       if (document != null && useDocumentBaseFormattingModel()) {
-        myModel = new DocumentBasedFormattingModel(myModel.getRootBlock(), document, myCodeStyleManager.getProject(), mySettings,
+        myModel = new DocumentBasedFormattingModel(myModel, document, myCodeStyleManager.getProject(), mySettings,
                                                    file.getFileType(), file);
       }
 
index 877709fc8961b86a582a5bed19a335653eced981..d720ecec23fc0803e6e1364488150ea4b8396189 100644 (file)
@@ -111,7 +111,7 @@ public class TestFormattingModel implements FormattingModel, FormattingDocumentM
   }
 
   @Override
-  public TextRange shiftIndentInsideRange(TextRange range, int indent) {
+  public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) {
     return range;
   }
 
index 0bf523f5e343cebc4344a35979df83e23c293ed2..43ffe00a494c735b9c636a5f0c741ad506356ed8 100644 (file)
@@ -49,27 +49,10 @@ public class XmlFormattingModel extends PsiBasedFormattingModel {
     myProject = file.getProject();
   }
 
-  @Override
-  public TextRange shiftIndentInsideRange(TextRange textRange, int shift) {
-    return shiftIndentInsideWithPsi(textRange, shift);
-  }
-
   @Override
   public void commitChanges() {
   }
 
-
-  private TextRange shiftIndentInsideWithPsi(final TextRange textRange, final int shift) {
-    final int offset = textRange.getStartOffset();
-
-    ASTNode leafElement = findElementAt(offset);
-    while (leafElement != null && !leafElement.getTextRange().equals(textRange)) {
-      leafElement = leafElement.getTreeParent();
-    }
-
-    return textRange;
-  }
-
   @Override
   protected String replaceWithPsiInLeaf(final TextRange textRange, String whiteSpace, ASTNode leafElement) {
      if (!myCanModifyAllWhiteSpaces) {