diff -r 026ced2727d3 xml.text/src/org/netbeans/modules/xml/text/folding/TokenElement.java --- a/xml.text/src/org/netbeans/modules/xml/text/folding/TokenElement.java Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/src/org/netbeans/modules/xml/text/folding/TokenElement.java Sat Jan 02 15:57:27 2010 +0000 @@ -80,6 +80,7 @@ return indentLevel; } + @Override public String toString() { return type + ", " + name + ", " + startOffset + ", " + endOffset; } diff -r 026ced2727d3 xml.text/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatter.java --- a/xml.text/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatter.java Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatter.java Sat Jan 02 15:57:27 2010 +0000 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common @@ -42,6 +42,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Stack; import javax.swing.text.AbstractDocument; @@ -53,7 +54,6 @@ import org.netbeans.api.lexer.TokenSequence; import org.netbeans.api.xml.lexer.XMLTokenId; import org.netbeans.editor.BaseDocument; -import org.netbeans.editor.Formatter; import org.netbeans.editor.Utilities; import org.netbeans.modules.editor.indent.api.IndentUtils; import org.netbeans.modules.editor.indent.spi.Context; @@ -61,7 +61,6 @@ import org.netbeans.modules.editor.structure.formatting.TagBasedLexerFormatter; import org.netbeans.modules.xml.text.folding.TokenElement; import org.netbeans.modules.xml.text.folding.TokenElement.TokenType; -import org.netbeans.modules.xml.text.syntax.XMLKit; /** * New XML formatter based on Lexer APIs. @@ -71,7 +70,6 @@ private static final String TAG_OPENING_PREFIX = "<"; //NOI18N private static final String TAG_CLOSING_PREFIX = "")) { //NOI18N + if (token.id() == XMLTokenId.TAG + && !token.text().toString().endsWith("/>")) { //NOI18N while (jts.movePrevious()) { int tokenOffset = jts.offset(); @@ -218,25 +216,31 @@ } // # 170343 -// @Override -// public void reformat(Context context, final int startOffset, final int endOffset) -// throws BadLocationException { -// final BaseDocument doc = (BaseDocument) context.document(); -// doc.render(new Runnable() { -// public void run() { -// doReformat(doc, startOffset, endOffset); -// } -// }); -// } + @Override + public void reformat(Context context, final int startOffset, final int endOffset) + throws BadLocationException { + final BaseDocument doc = (BaseDocument) context.document(); + doc.render(new Runnable() { + + public void run() { + doReformat(doc, startOffset, endOffset); + } + }); + } public BaseDocument doReformat(BaseDocument doc, int startOffset, int endOffset) { spacesPerTab = IndentUtils.indentLevelSize(doc); try { - List tags = getTags(doc, startOffset, endOffset); + List tags = getTags(doc, startOffset, endOffset); for (int i = tags.size() - 1; i >= 0; i--) { - TokenElement tag = tags.get(i); + if (tags.get(i).isPreserveIndent()) { + continue; + } + TokenElement tag = tags.get(i).getToken(); + int so = tag.getStartOffset(); int lineOffset = Utilities.getLineOffset(doc, so); + String tagName = tag.getName(); if (tagName.startsWith(" getTags(BaseDocument basedoc, int startOffset, int endOffset) + private List getTags(BaseDocument basedoc, int startOffset, int endOffset) throws BadLocationException, IOException { - List tags = new ArrayList(); + List tags = new ArrayList(); + LinkedList preserveNesting_outdent = new LinkedList(); + preserveNesting_outdent.add(Boolean.FALSE); + boolean preserveWhitespace = false; + boolean settingSpaceValue = false; + int indentLevel = -1; basedoc.readLock(); int incrIndentLevelBy = 0; try { //are we formatting from the beginning of doc or a subsection int line = Utilities.getLineOffset(basedoc, startOffset); - if(line > 0) { + if (line > 0) { boolean nested = isSubSectionToFormatNested(basedoc, startOffset); //we are formatting a subsection - int precedingWordLoc = Utilities.getFirstNonWhiteBwd(basedoc, startOffset) ; + int precedingWordLoc = Utilities.getFirstNonWhiteBwd(basedoc, startOffset); int previousLine = Utilities.getLineOffset(basedoc, precedingWordLoc); int previousLineIndentation = 0; //we need to get the previous line and find its indentation @@ -323,23 +329,25 @@ //has selected the entire line to format //the previous line will be the same as current line if user //selected a part of line to format - if(previousLine != line){ + if (previousLine != line) { previousLineIndentation = Utilities.getRowIndent(basedoc, precedingWordLoc); - } else + } else { previousLineIndentation = Utilities.getRowIndent(basedoc, startOffset); + } //the section being formatted should be idented wrt to previous line's indentation - - int div = previousLineIndentation / spacesPerTab; - if(nested) - incrIndentLevelBy = div +1; - else - incrIndentLevelBy = div; - + + int div = previousLineIndentation / spacesPerTab; + if (nested) { + incrIndentLevelBy = div + 1; + } else { + incrIndentLevelBy = div; + } + } TokenHierarchy tokenHierarchy = TokenHierarchy.get(basedoc); TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); org.netbeans.api.lexer.Token token = tokenSequence.token(); - // Add the text token, if any, before xml decalration to document node + // Add the text token, if any, before xml declaration to document node if (token != null && token.id() == XMLTokenId.TEXT) { if (tokenSequence.moveNext()) { token = tokenSequence.token(); @@ -347,21 +355,23 @@ } int currentTokensSize = 0; Stack stack = new Stack(); - String currentNode = null; while (tokenSequence.moveNext()) { token = tokenSequence.token(); XMLTokenId tokenId = token.id(); String image = token.text().toString(); - if( ! (tokenSequence.offset() >= startOffset && tokenSequence.offset() endOffset) { + break; } + boolean tokenInSelectionRange = tokenSequence.offset() >= startOffset; TokenType tokenType = TokenType.TOKEN_WHITESPACE; switch (tokenId) { case TAG: { int len = image.length(); if (image.charAt(len - 1) == '>') {// '/>' if (len == 2) { + if (!preserveWhitespace) { + --indentLevel; + } if (!stack.empty()) { stack.pop(); } @@ -369,27 +379,35 @@ } else { tokenType = TokenType.TOKEN_ELEMENT_START_TAG; if (image.startsWith("")) - return false; - if(tagText.startsWith("<")) - return true; - } - } catch (Exception ex) { - //return false anyway - } finally { - doc.readUnlock(); - } - return false; + + private boolean isSubSectionToFormatNested(BaseDocument baseDoc, int startOffset) { + AbstractDocument doc = (AbstractDocument) baseDoc; + doc.readLock(); + try { + TokenHierarchy th = TokenHierarchy.get(doc); + TokenSequence ts = th.tokenSequence(); + ts.move(startOffset); + while (ts.movePrevious()) { + Token t = ts.token(); + if (t.id() == XMLTokenId.PI_END) { + return false; + } + String tagText = t.text().toString(); + if (tagText.startsWith("")) { + return false; + } + if (tagText.startsWith("<")) { + return true; + } + } + } catch (Exception ex) { + //return false anyway + } finally { + doc.readUnlock(); + } + return false; + } + + private class TokenIndent { + + private TokenElement token; + private boolean preserveIndent; + + public TokenIndent(TokenElement token, boolean preserveIndent) { + this.token = token; + this.preserveIndent = preserveIndent; + } + + public TokenElement getToken() { + return token; + } + + public boolean isPreserveIndent() { + return preserveIndent; + } + + public void setPreserveIndent(boolean preserveIndent) { + this.preserveIndent = preserveIndent; + } + + @Override + public String toString() { + return "TokenIndent: name=" + token.getName() + " preserveIndent=" + preserveIndent; + } } } diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatterTest.java --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatterTest.java Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/XMLLexerFormatterTest.java Sat Jan 02 15:57:27 2010 +0000 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common @@ -48,7 +48,7 @@ * @author Samaresh (samaresh.panda@sun.com) */ public class XMLLexerFormatterTest extends AbstractTestCase { - + public XMLLexerFormatterTest(String testName) { super(testName); } @@ -61,9 +61,12 @@ suite.addTest(new XMLLexerFormatterTest("testFormatPerformance")); suite.addTest(new XMLLexerFormatterTest("testFormatSubsection1")); suite.addTest(new XMLLexerFormatterTest("testFormatSubsection2")); + suite.addTest(new XMLLexerFormatterTest("testFormat_PreserveWhitespace")); + suite.addTest(new XMLLexerFormatterTest("testFormat_WithNestedPreserveWhitespace")); + suite.addTest(new XMLLexerFormatterTest("testFormatSubsection_PreserveWhitespace")); return suite; } - + /** * Formats an input document and then compares the formatted doc * with a document that represents expected outcome. @@ -74,20 +77,20 @@ XMLLexerFormatter formatter = new XMLLexerFormatter(null); BaseDocument formattedDoc = formatter.doReformat(inputDoc, 0, inputDoc.getLength()); System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); - BaseDocument outputDoc = getDocument("indent/output.xml"); - assert(compare(formattedDoc, outputDoc)); + BaseDocument outputDoc = getDocument("indent/output.xml"); + assert (compare(formattedDoc, outputDoc)); } - + public void testFormatSubsection() throws Exception { BaseDocument inputDoc = getDocument("indent/input_sub.xml"); //format a subsection of the inputDoc XMLLexerFormatter formatter = new XMLLexerFormatter(null); BaseDocument formattedDoc = formatter.doReformat(inputDoc, 72, 97); System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); - BaseDocument outputDoc = getDocument("indent/output_sub.xml"); - assert(compare(formattedDoc, outputDoc)); + BaseDocument outputDoc = getDocument("indent/output_sub.xml"); + assert (compare(formattedDoc, outputDoc)); } - + //for bug 139160 public void testFormatForTab() throws Exception { BaseDocument inputDoc = getDocument("indent/input2.xsd"); @@ -95,11 +98,10 @@ XMLLexerFormatter formatter = new XMLLexerFormatter(null); BaseDocument formattedDoc = formatter.doReformat(inputDoc, 0, inputDoc.getLength()); System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); - BaseDocument outputDoc = getDocument("indent/output2.xsd"); - assert(compare(formattedDoc, outputDoc)); + BaseDocument outputDoc = getDocument("indent/output2.xsd"); + assert (compare(formattedDoc, outputDoc)); } - - + public void testFormatPerformance() throws Exception { BaseDocument inputDoc = getDocument("indent/1998stats.xml"); //format the inputDoc @@ -107,8 +109,8 @@ long t1 = System.currentTimeMillis(); formatter.doReformat(inputDoc, 0, inputDoc.getLength()); long t2 = System.currentTimeMillis(); - System.out.println("Time taken to format NFL XML in ms:: " + (t2-t1) ); - + System.out.println("Time taken to format NFL XML in ms:: " + (t2 - t1)); + //try OTA Schema inputDoc = getDocument("indent/1998stats.xml"); //format the inputDoc @@ -116,25 +118,60 @@ t1 = System.currentTimeMillis(); formatter.doReformat(inputDoc, 0, inputDoc.getLength()); t2 = System.currentTimeMillis(); - System.out.println("Time taken to format OTA Schema in ms:: " + (t2-t1) ); + System.out.println("Time taken to format OTA Schema in ms:: " + (t2 - t1)); } + public void testFormatSubsection1() throws Exception { BaseDocument inputDoc = getDocument("indent/input_sub1.xml"); //format a subsection of the inputDoc XMLLexerFormatter formatter = new XMLLexerFormatter(null); - BaseDocument formattedDoc = formatter.doReformat(inputDoc, 39, 68); + BaseDocument formattedDoc = formatter.doReformat(inputDoc, 46, 74); System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); - BaseDocument outputDoc = getDocument("indent/output_sub1.xml"); - assert(compare(formattedDoc, outputDoc)); + BaseDocument outputDoc = getDocument("indent/output_sub1.xml"); + assert (compare(formattedDoc, outputDoc)); } - + public void testFormatSubsection2() throws Exception { BaseDocument inputDoc = getDocument("indent/input_sub2.xml"); //format a subsection of the inputDoc XMLLexerFormatter formatter = new XMLLexerFormatter(null); - BaseDocument formattedDoc = formatter.doReformat(inputDoc, 68, 83); + BaseDocument formattedDoc = formatter.doReformat(inputDoc, 51, 80); System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); - BaseDocument outputDoc = getDocument("indent/output_sub2.xml"); - assert(compare(formattedDoc, outputDoc)); + BaseDocument outputDoc = getDocument("indent/output_sub2.xml"); + assert (compare(formattedDoc, outputDoc)); + } + + //for bug 170343 + public void testFormat_PreserveWhitespace() throws Exception { + BaseDocument inputDoc = getDocument("indent/input_preserve.xml"); + //format the inputDoc + XMLLexerFormatter formatter = new XMLLexerFormatter(null); + BaseDocument formattedDoc = formatter.doReformat(inputDoc, 0, inputDoc.getLength()); + System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); + BaseDocument outputDoc = getDocument("indent/output_preserve.xml"); + assert (compare(formattedDoc, outputDoc)); + } + + //for bug 170343 + public void testFormat_WithNestedPreserveWhitespace() throws Exception { + BaseDocument inputDoc = getDocument("indent/input_withpreserve.xml"); + //format the inputDoc + XMLLexerFormatter formatter = new XMLLexerFormatter(null); + BaseDocument formattedDoc = formatter.doReformat(inputDoc, 0, inputDoc.getLength()); + System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); + BaseDocument outputDoc = getDocument("indent/output_withpreserve.xml"); + assert (compare(formattedDoc, outputDoc)); + } + + //for bug 170343 + public void testFormatSubsection_PreserveWhitespace() throws Exception { + BaseDocument inputDoc = getDocument("indent/input_preserve.xml"); + //format the inputDoc + XMLLexerFormatter formatter = new XMLLexerFormatter(null); + System.out.println("SECTION:" + inputDoc.getText(91, 87)); + BaseDocument formattedDoc = formatter.doReformat(inputDoc, 91, 91 + 87); + System.out.println(formattedDoc.getText(0, formattedDoc.getLength())); + BaseDocument outputDoc = getDocument("indent/output_preserve.xml"); + assert (compare(formattedDoc, outputDoc)); } } diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,31 +1,32 @@ + + + hello world + - - hello world - + + - - - - - - test - - - - + - - - - test - - + test - - - 1 - + + + + + + + + test + + + + + + 1 + + \ No newline at end of file diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub1.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub1.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub1.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,5 +1,5 @@ + - + - diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub2.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub2.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/input_sub2.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,4 +1,5 @@ + + - diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,33 +1,34 @@ + + + + hello world + + - - - hello world - - + + - - - - - - test - - - - + - - - - test - - + test - - - 1 - + + + + + + + + test + + + + + + 1 + + diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub1.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub1.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub1.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,5 +1,5 @@ - + + - diff -r 026ced2727d3 xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub2.xml --- a/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub2.xml Tue Dec 29 22:17:26 2009 +0100 +++ b/xml.text/test/unit/src/org/netbeans/modules/xml/text/indent/output_sub2.xml Sat Jan 02 15:57:27 2010 +0000 @@ -1,4 +1,5 @@ + + -