1 19 package org.netbeans.modules.xml.text.indent; 20 21 import java.util.regex.Pattern ; 22 import javax.swing.text.BadLocationException ; 23 24 import org.netbeans.editor.Syntax; 25 import org.netbeans.editor.TokenItem; 26 import org.netbeans.editor.ext.AbstractFormatLayer; 27 import org.netbeans.editor.ext.ExtSyntaxSupport; 28 import org.netbeans.editor.ext.FormatTokenPosition; 29 import org.netbeans.editor.ext.FormatSupport; 30 import org.netbeans.editor.ext.FormatWriter; 31 import org.netbeans.editor.BaseDocument; 32 import org.netbeans.modules.editor.structure.formatting.TagBasedFormatter; 33 import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport; 34 import org.netbeans.modules.xml.text.syntax.XMLTokenIDs; 35 36 import org.netbeans.modules.xml.text.syntax.javacc.lib.JJEditorSyntax; 37 38 41 public class XMLFormatter extends TagBasedFormatter { 42 43 private static final String TAG_OPENING_PREFIX = "<"; private static final String TAG_CLOSING_PREFIX = "</"; private static final String TAG_CLOSED_SUFFIX = "/>"; private static final String TAG_CLOSING_SUFFIX = "/>"; 48 private static final Pattern VALID_TAG_NAME = Pattern.compile("[\\w+|-]*"); 51 private static final int WORKUNITS_MAX = 100; 52 53 public XMLFormatter(Class kitClass) { 54 super(kitClass); 55 } 56 57 public FormatSupport createFormatSupport(FormatWriter fw) { 58 return new XMLFormatSupport(fw); 59 } 60 61 protected boolean acceptSyntax(Syntax syntax) { 62 return (syntax instanceof JJEditorSyntax); 63 } 64 65 protected void initFormatLayers() { 66 addFormatLayer(new StripEndWhitespaceLayer()); 67 } 68 69 protected String extractTagName(TokenItem tknTag){ 70 71 String tagImage = tknTag.getImage(); 72 int startIndex = -1; 73 74 if (isOpeningTag(tknTag)){ 75 startIndex = TAG_OPENING_PREFIX.length(); 76 } else if (isClosingTag(tknTag)){ 77 startIndex = TAG_CLOSING_PREFIX.length(); 78 } 79 80 if (startIndex >= 0){ 81 String tagName = tagImage.substring(startIndex); 82 return tagName; 83 } 84 85 return null; 86 } 87 88 @Override protected boolean isOpeningTag(TokenItem token){ 89 return token != null 90 && token.getTokenID() == XMLTokenIDs.TAG 91 && token.getImage().startsWith(TAG_OPENING_PREFIX) 92 && !token.getImage().startsWith(TAG_CLOSING_PREFIX); 93 } 94 95 @Override protected boolean isClosingTag(TokenItem token){ 96 return token != null 97 && token.getTokenID() == XMLTokenIDs.TAG 98 && token.getImage().startsWith(TAG_CLOSING_PREFIX); 99 } 100 101 @Override protected int getTagEndOffset(TokenItem token){ 102 TokenItem t = token.getNext(); 103 104 while (t != null && t.getTokenID() != XMLTokenIDs.TAG){ 105 t = t.getNext(); 106 } 107 108 return t == null ? -1 : t.getOffset(); 109 } 110 111 @Override protected ExtSyntaxSupport getSyntaxSupport(BaseDocument doc){ 112 return (XMLSyntaxSupport)(doc.getSyntaxSupport().get(XMLSyntaxSupport.class)); 113 } 114 115 @Override protected boolean areTagNamesEqual(String tagName1, String tagName2){ 116 return tagName1.equals(tagName2); 117 } 118 119 @Override protected boolean isClosingTagRequired(BaseDocument doc, String tagName){ 120 return true; 121 } 122 123 @Override protected int getOpeningSymbolOffset(TokenItem tknTag){ 124 return tknTag.getOffset(); 125 } 126 127 @Override protected TokenItem getTagTokenEndingAtPosition(BaseDocument doc, int position) throws BadLocationException { 128 if (position >= 0) { 129 ExtSyntaxSupport sup = getSyntaxSupport(doc); 130 TokenItem token = sup.getTokenChain(position, position + 1); 131 132 if (token.getTokenID() == XMLTokenIDs.TAG && 133 token.getImage().equals(">")){ do { 135 token = token.getPrevious(); 136 } 137 while (token != null && !isOpeningTag(token) && !isClosingTag(token)); 138 139 return token; 140 } 141 } 142 return null; 143 } 144 145 @Override protected boolean isUnformattableToken(TokenItem token) { 146 147 if (token.getTokenID() == XMLTokenIDs.BLOCK_COMMENT 148 || token.getTokenID() == XMLTokenIDs.CDATA_SECTION){ 149 return true; 150 } 151 152 return false; 153 } 154 155 @Override protected boolean isUnformattableTag(String tag) { 156 return false; 157 } 158 159 public class StripEndWhitespaceLayer extends AbstractFormatLayer { 160 161 public StripEndWhitespaceLayer() { 162 super("xml-strip-whitespace-at-line-end-layer"); } 164 165 protected FormatSupport createFormatSupport(FormatWriter fw) { 166 return new XMLFormatSupport(fw); 167 } 168 169 public void format(FormatWriter fw) { 170 XMLFormatSupport xfs = (XMLFormatSupport)createFormatSupport(fw); 171 172 FormatTokenPosition pos = xfs.getFormatStartPosition(); 173 174 if ( (xfs.isLineStart(pos) == false) || 175 xfs.isIndentOnly() ) { 177 } else { while (pos.getToken() != null) { 179 pos = xfs.removeLineEndWhitespace(pos); 180 if (pos.getToken() != null) { 181 pos = xfs.getNextPosition(pos); 182 } 183 } 184 } 185 } 186 } 187 } 188 | Popular Tags |