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;
}
@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;
}
*/
package com.intellij.formatting;
+import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
* 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
--- /dev/null
+/*
+ * 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);
+}
}
@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
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();
}
}
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;
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,
myFileType = fileType;
myFile = file;
myDocumentModel = new FormattingDocumentModelImpl(document,file);
+ myOriginalFormattingModel = null;
}
public DocumentBasedFormattingModel(final Block rootBlock,
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
@Override
public TextRange replaceWhiteSpace(TextRange textRange, ASTNode nodeAfter, String whiteSpace) {
+ if (myOriginalFormattingModel instanceof FormattingModelWithShiftIndentInsideDocumentRange) {
+ whiteSpace = ((FormattingModelWithShiftIndentInsideDocumentRange)myOriginalFormattingModel).adjustWhiteSpaceInsideDocument(
+ nodeAfter,
+ whiteSpace);
+ }
+
boolean removesStartMarker;
String marker;
}
@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);
}
}
@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...
}
}
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);
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);
}
}
@Override
- public TextRange shiftIndentInsideRange(TextRange range, int indent) {
+ public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) {
return range;
}
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) {