/* * Copyright 2000-2014 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.lang.xml; import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; import com.intellij.psi.formatter.WhiteSpaceFormattingStrategyAdapter; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.Factory; import com.intellij.psi.impl.source.tree.LeafElement; import com.intellij.psi.impl.source.tree.SharedImplUtil; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.xml.XmlElementType; import com.intellij.psi.xml.XmlText; import com.intellij.psi.xml.XmlTokenType; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; /** * @author Denis Zhdanov * @since 12/6/11 4:51 PM */ public class XmlWhiteSpaceFormattingStrategy extends WhiteSpaceFormattingStrategyAdapter { private static void addWhitespaceToTagBody(final ASTNode treePrev, final LeafElement whiteSpaceElement) { final CharTable charTable = SharedImplUtil.findCharTableByTree(treePrev); final ASTNode treeParent = treePrev.getTreeParent(); final boolean before; final XmlText xmlText; if(treePrev.getElementType() == XmlElementType.XML_TEXT) { xmlText = (XmlText)treePrev.getPsi(); before = true; } else if(treePrev.getTreePrev().getElementType() == XmlElementType.XML_TEXT){ xmlText = (XmlText)treePrev.getTreePrev().getPsi(); before = false; } else{ xmlText = (XmlText)Factory.createCompositeElement(XmlElementType.XML_TEXT, charTable, treeParent.getPsi().getManager()); CodeEditUtil.setNodeGenerated(xmlText.getNode(), true); treeParent.addChild(xmlText.getNode(), treePrev); before = true; } final ASTNode node = xmlText.getNode(); assert node != null; final TreeElement anchorInText = (TreeElement) (before ? node.getFirstChildNode() : node.getLastChildNode()); if (anchorInText == null) node.addChild(whiteSpaceElement); else if (anchorInText.getElementType() != XmlTokenType.XML_WHITE_SPACE) node.addChild(whiteSpaceElement, before ? anchorInText : null); else { final String text = before ? whiteSpaceElement.getText() + anchorInText.getText() : anchorInText.getText() + whiteSpaceElement.getText(); node.replaceChild(anchorInText, ASTFactory.whitespace(text)); } } protected boolean isInsideTagBody(@NotNull ASTNode place) { final ASTNode treeParent = place.getTreeParent(); if(treeParent.getElementType() != XmlElementType.XML_TAG && treeParent.getElementType() != XmlElementType.HTML_TAG) return false; while(place != null){ if(place.getElementType() == XmlTokenType.XML_TAG_END) return true; place = place.getTreePrev(); } return false; } @Override public boolean addWhitespace(@NotNull final ASTNode treePrev, @NotNull final LeafElement whiteSpaceElement) { if (isInsideTagBody(treePrev)) { addWhitespaceToTagBody(treePrev, whiteSpaceElement); return true; } return false; } @Override public boolean containsWhitespacesOnly(@NotNull final ASTNode node) { return (node.getElementType() == XmlTokenType.XML_DATA_CHARACTERS) && node.getText().trim().length() == 0; } }