2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 package com
.intellij
.psi
.impl
.source
.codeStyle
;
22 import com
.intellij
.formatting
.Block
;
23 import com
.intellij
.lang
.ASTNode
;
24 import com
.intellij
.openapi
.diagnostic
.Logger
;
25 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
26 import com
.intellij
.openapi
.project
.Project
;
27 import com
.intellij
.openapi
.util
.TextRange
;
28 import com
.intellij
.psi
.PsiFile
;
29 import com
.intellij
.psi
.PsiWhiteSpace
;
30 import com
.intellij
.psi
.TokenType
;
31 import com
.intellij
.psi
.formatter
.DocumentBasedFormattingModel
;
32 import com
.intellij
.psi
.formatter
.FormatterUtil
;
33 import com
.intellij
.psi
.formatter
.FormattingDocumentModelImpl
;
34 import com
.intellij
.psi
.formatter
.PsiBasedFormattingModel
;
35 import com
.intellij
.psi
.impl
.source
.tree
.TreeUtil
;
36 import com
.intellij
.psi
.tree
.IElementType
;
37 import com
.intellij
.psi
.xml
.XmlElementType
;
38 import org
.jetbrains
.annotations
.NonNls
;
39 import org
.jetbrains
.annotations
.NotNull
;
41 public class PsiBasedFormatterModelWithShiftIndentInside
extends PsiBasedFormattingModel
{
42 private static final Logger LOG
=
43 Logger
.getInstance("#com.intellij.psi.impl.source.codeStyle.PsiBasedFormatterModelWithShiftIndentInside");
45 private final Project myProject
;
47 public PsiBasedFormatterModelWithShiftIndentInside(final PsiFile file
,
48 @NotNull final Block rootBlock
,
49 final FormattingDocumentModelImpl documentModel
) {
50 super(file
, rootBlock
, documentModel
);
51 myProject
= file
.getProject();
54 public TextRange
shiftIndentInsideRange(TextRange textRange
, int shift
) {
55 return shiftIndentInsideWithPsi(textRange
, shift
);
58 public void commitChanges() {
62 private TextRange
shiftIndentInsideWithPsi(final TextRange textRange
, final int shift
) {
63 final int offset
= textRange
.getStartOffset();
65 ASTNode leafElement
= findElementAt(offset
);
66 while (leafElement
!= null && !leafElement
.getTextRange().equals(textRange
)) {
67 leafElement
= leafElement
.getTreeParent();
70 if (leafElement
!= null && leafElement
.getTextRange().equals(textRange
) && ShiftIndentInsideHelper
.mayShiftIndentInside(leafElement
)) {
71 return new ShiftIndentInsideHelper(StdFileTypes
.JAVA
, myProject
).shiftIndentInside(leafElement
, shift
).getTextRange();
78 protected String
replaceWithPsiInLeaf(final TextRange textRange
, String whiteSpace
, ASTNode leafElement
) {
79 if (!myCanModifyAllWhiteSpaces
) {
80 if (leafElement
.getElementType() == TokenType
.WHITE_SPACE
) return null;
81 ASTNode prevNode
= TreeUtil
.prevLeaf(leafElement
);
83 if (prevNode
!= null) {
84 IElementType type
= prevNode
.getElementType();
85 if(type
== TokenType
.WHITE_SPACE
) {
86 final String text
= prevNode
.getText();
88 final @NonNls String cdataStartMarker
= "<![CDATA[";
89 final int cdataPos
= text
.indexOf(cdataStartMarker
);
90 if (cdataPos
!= -1 && whiteSpace
.indexOf(cdataStartMarker
) == -1) {
91 whiteSpace
= DocumentBasedFormattingModel
.mergeWsWithCdataMarker(whiteSpace
, text
, cdataPos
);
92 if (whiteSpace
== null) return null;
95 prevNode
= TreeUtil
.prevLeaf(prevNode
);
96 type
= prevNode
!= null ? prevNode
.getElementType():null;
99 final @NonNls String cdataEndMarker
= "]]>";
100 if(type
== XmlElementType
.XML_CDATA_END
&& whiteSpace
.indexOf(cdataEndMarker
) == -1) {
101 final ASTNode at
= findElementAt(prevNode
.getStartOffset());
103 if (at
!= null && at
.getPsi() instanceof PsiWhiteSpace
) {
104 final String s
= at
.getText();
105 final int cdataEndPos
= s
.indexOf(cdataEndMarker
);
106 whiteSpace
= DocumentBasedFormattingModel
.mergeWsWithCdataMarker(whiteSpace
, s
, cdataEndPos
);
111 if (whiteSpace
== null) return null;
115 FormatterUtil
.replaceWhiteSpace(whiteSpace
, leafElement
, TokenType
.WHITE_SPACE
, textRange
);