/******************************************************************************* * Copyright (c) 2001, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Jens Lukowski/Innoopract - initial renaming/restructuring * Jesper Steen M�ller - xml:space='preserve' support * *******************************************************************************/ package org.eclipse.wst.xml.core.internal.provisional.format; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.text.BadLocationException; import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints; import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences; import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter; import org.eclipse.wst.sse.core.internal.format.StructuredFormatContraints; import org.eclipse.wst.sse.core.internal.parser.ContextRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; import org.eclipse.wst.sse.core.utils.StringUtils; import org.eclipse.wst.xml.core.internal.Logger; import org.eclipse.wst.xml.core.internal.XMLCorePlugin; import org.eclipse.wst.xml.core.internal.document.CDATASectionImpl; import org.eclipse.wst.xml.core.internal.document.CharacterDataImpl; import org.eclipse.wst.xml.core.internal.document.CommentImpl; import org.eclipse.wst.xml.core.internal.parser.regions.TagNameRegion; import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; import org.w3c.dom.Node; public class NodeFormatter implements IStructuredFormatter { static protected final String EMPTY_STRING = ""; //$NON-NLS-1$ static private final char SPACE_CHAR = ' '; //$NON-NLS-1$ static private final char TAB_CHAR = '\t'; //$NON-NLS-1$ static private final String TAB = "\t"; //$NON-NLS-1$ protected IStructuredFormatContraints fFormatContraints = null; protected IStructuredFormatPreferences fFormatPreferences = null; protected IProgressMonitor fProgressMonitor = null; protected boolean firstStructuredDocumentRegionContainsLineDelimiters(IDOMNode node) { boolean result = false; if (node != null) { IStructuredDocumentRegion firstStructuredDocumentRegion = node.getFirstStructuredDocumentRegion(); if (firstStructuredDocumentRegion != null) { String firstStructuredDocumentRegionText = firstStructuredDocumentRegion.getText(); result = StringUtils.containsLineDelimiter(firstStructuredDocumentRegionText); } } return result; } public void format(Node node) { IStructuredFormatContraints formatContraints = getFormatContraints(); format(node, formatContraints); } public void format(Node node, IStructuredFormatContraints formatContraints) { if (formatContraints.getFormatWithSiblingIndent()) formatContraints.setCurrentIndent(getSiblingIndent(node)); if (node instanceof IDOMNode) formatNode((IDOMNode) node, formatContraints); } protected void formatIndentationAfterNode(IDOMNode node, IStructuredFormatContraints formatContraints) { // [111674] If inside xml:space="preserve" element, we bail if (formatContraints.getInPreserveSpaceElement()) return; if (node != null) { IDOMNode nextSibling = (IDOMNode) node.getNextSibling(); IStructuredDocument doc = node.getModel().getStructuredDocument(); String lineDelimiter = getLineDelimiter(node, doc); if (node.getParentNode() != null) { if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) if (nextSibling != null) if (nextSibling.getNodeType() == Node.TEXT_NODE) getFormatter(nextSibling).format(nextSibling, formatContraints); else if (nextSibling.getNodeType() == Node.COMMENT_NODE) { // do nothing } else { String lineIndent = formatContraints.getCurrentIndent(); insertAfterNode(node, lineDelimiter + lineIndent); } else { } else if (nextSibling != null) if (nextSibling.getNodeType() == Node.TEXT_NODE) getFormatter(nextSibling).format(nextSibling, formatContraints); else if (nextSibling.getNodeType() == Node.COMMENT_NODE) { // do nothing } else { String lineIndent = formatContraints.getCurrentIndent(); insertAfterNode(node, lineDelimiter + lineIndent); } else { IDOMNode indentNode = getParentIndentNode(node); String lineIndent = getNodeIndent(indentNode); IDOMNode lastChild = getDeepestChildNode(node); boolean clearAllBlankLines = formatContraints.getClearAllBlankLines(); if (lastChild != null) { if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue().endsWith(lineDelimiter + lineIndent))) { // this text node already ends with the requested // indentation } else if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue() != null && lastChild.getNodeValue().endsWith(lineDelimiter))) if (clearAllBlankLines) { replaceNodeValue(lastChild, lineDelimiter + lineIndent); } else { // append indentation insertAfterNode(lastChild, lineIndent); } else if (lastChild.getNodeType() == Node.TEXT_NODE) if (lastChild.getNodeValue().length() == 0) { // replace replaceNodeValue(lastChild, lineDelimiter + lineIndent); } else { // append indentation insertAfterNode(lastChild, lineDelimiter + lineIndent); } else { // as long as not at the end of the document IStructuredDocumentRegion endRegion = node.getLastStructuredDocumentRegion(); if (endRegion != null && endRegion.getNext() != null) // append indentation insertAfterNode(lastChild, lineDelimiter + lineIndent); } } } } } } protected void formatIndentationBeforeNode(IDOMNode node, IStructuredFormatContraints formatContraints) { // [111674] If inside xml:space="preserve" element, we bail if (formatContraints.getInPreserveSpaceElement()) return; if (node != null) { IDOMNode previousSibling = (IDOMNode) node.getPreviousSibling(); IStructuredDocument doc = node.getModel().getStructuredDocument(); String lineDelimiter = getLineDelimiter(node, doc); String lineIndent = formatContraints.getCurrentIndent(); if (node.getParentNode() != null) { if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) { if (previousSibling != null) if (previousSibling.getNodeType() == Node.TEXT_NODE) getFormatter(previousSibling).format(previousSibling, formatContraints); else { insertBeforeNode(node, lineDelimiter + lineIndent); } } else { if (previousSibling == null || previousSibling.getNodeType() != Node.TEXT_NODE) { // 261968 - formatting tag without closing bracket: // <t1><t1 // 265673 - Null ptr in formatIndentationBeforeNode int prevEndNodeOffset = -1; int prevEndRegionOffset = -1; if (previousSibling != null) { prevEndNodeOffset = previousSibling.getEndOffset(); IStructuredDocumentRegion endRegion = previousSibling.getEndStructuredDocumentRegion(); if (endRegion != null) { prevEndRegionOffset = endRegion.getTextEndOffset(); } } if ((previousSibling == null) || (prevEndNodeOffset != -1 && prevEndNodeOffset == prevEndRegionOffset)) { insertBeforeNode(node, lineDelimiter + lineIndent); } } else { if (previousSibling.getNodeValue().length() == 0) { // replace replaceNodeValue(previousSibling, lineDelimiter + lineIndent); } else { // append indentation if (!previousSibling.getNodeValue().endsWith(lineDelimiter + lineIndent)) { if (previousSibling.getNodeValue().endsWith(lineDelimiter)) { insertAfterNode(previousSibling, lineIndent); } else getFormatter(previousSibling).format(previousSibling, formatContraints); } } } } } } } private String getLineDelimiter(IDOMNode node, IStructuredDocument doc) { int line = doc.getLineOfOffset(node.getStartOffset()); String lineDelimiter = doc.getLineDelimiter(); try { if (line > 0) { lineDelimiter = doc.getLineDelimiter(line - 1); } } catch (BadLocationException e) { // log for now, unless we find reason not to Logger.log(Logger.INFO, e.getMessage()); } // BUG115716: if cannot get line delimiter from current line, just // use default line delimiter if (lineDelimiter == null) lineDelimiter = doc.getLineDelimiter(); return lineDelimiter; } protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) { if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) { // format indentation before node formatIndentationBeforeNode(node, formatContraints); // format indentation after node formatIndentationAfterNode(node, formatContraints); } } /** * This method will compute the correct indentation after this node * depending on the indentations of its sibling nodes and parent node. Not * needed anymore? */ protected void formatTrailingText(IDOMNode node, IStructuredFormatContraints formatContraints) { // [111674] If inside xml:space="preserve" element, we bail if (formatContraints.getInPreserveSpaceElement()) return; String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter(); String lineIndent = formatContraints.getCurrentIndent(); String parentLineIndent = getNodeIndent(node.getParentNode()); boolean clearAllBlankLines = formatContraints.getClearAllBlankLines(); if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE)) { IDOMNode nextSibling = (IDOMNode) node.getNextSibling(); if ((nextSibling != null) && (nextSibling.getNodeType() == Node.TEXT_NODE)) { String nextSiblingText = nextSibling.getNodeValue(); if (nextSibling.getNextSibling() == null) if ((nextSibling.getParentNode().getNodeType() == Node.DOCUMENT_NODE) && (nextSiblingText.trim().length() == 0)) // delete spaces at the end of the document replaceNodeValue(nextSibling, EMPTY_STRING); else // replace the text node with parent indentation replaceNodeValue(nextSibling, lineDelimiter + parentLineIndent); else // replace the text node with indentation replaceNodeValue(nextSibling, lineDelimiter + lineIndent); } else { if (nextSibling == null) { lineIndent = parentLineIndent; if (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE) if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) { // this text node already ends with the requested // indentation } else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter))) if (clearAllBlankLines) replaceNodeValue(node, lineDelimiter + lineIndent); else // append indentation insertAfterNode(node, lineIndent); else if (node.getNodeType() == Node.TEXT_NODE) if (node.getNodeValue().length() == 0) // replace replaceNodeValue(node, lineDelimiter + lineIndent); else // append indentation if (!node.getNodeValue().endsWith(lineDelimiter + lineIndent)) if (node.getNodeValue().endsWith(lineDelimiter)) insertAfterNode(node, lineIndent); else insertAfterNode(node, lineDelimiter + lineIndent); else replaceNodeValue(node, lineDelimiter + lineIndent); } else { if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) { // this text node already ends with the requested // indentation } else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter))) if (clearAllBlankLines) replaceNodeValue(node, lineDelimiter + lineIndent); else // append indentation insertAfterNode(node, lineIndent); else if (node.getNodeType() == Node.TEXT_NODE) if (node.getNodeValue().length() == 0) // replace replaceNodeValue(node, lineDelimiter + lineIndent); else // append indentation insertAfterNode(node, lineDelimiter + lineIndent); else // append indentation insertAfterNode(node, lineDelimiter + lineIndent); } } } } protected IDOMNode getDeepestChildNode(IDOMNode node) { IDOMNode result = null; IDOMNode lastChild = (IDOMNode) node.getLastChild(); if (lastChild == null) result = node; else { result = getDeepestChildNode(lastChild); if ((result.getNodeType() == Node.TEXT_NODE || result.getNodeType() == Node.COMMENT_NODE) && !isEndTagMissing(node)) result = node; } return result; } public IStructuredFormatContraints getFormatContraints() { if (fFormatContraints == null) { fFormatContraints = new StructuredFormatContraints(); fFormatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines()); } return fFormatContraints; } public IStructuredFormatPreferences getFormatPreferences() { if (fFormatPreferences == null) { fFormatPreferences = new StructuredFormatPreferencesXML(); Preferences preferences = getModelPreferences(); if (preferences != null) { fFormatPreferences.setLineWidth(preferences.getInt(XMLCorePreferenceNames.LINE_WIDTH)); ((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS)); ((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET)); ((StructuredFormatPreferencesXML) fFormatPreferences).setPreservePCDATAContent(preferences.getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT)); fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES)); char indentChar = ' '; String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR); if (XMLCorePreferenceNames.TAB.equals(indentCharPref)) { indentChar = '\t'; } int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE); StringBuffer indent = new StringBuffer(); for (int i = 0; i < indentationWidth; i++) { indent.append(indentChar); } fFormatPreferences.setIndent(indent.toString()); } } return fFormatPreferences; } protected IStructuredFormatter getFormatter(IDOMNode node) { // 262135 - NPE during format of empty document if (node == null) return null; short nodeType = ((Node) node).getNodeType(); IStructuredFormatter formatter = null; switch (nodeType) { case Node.ELEMENT_NODE : { formatter = new ElementNodeFormatter(); break; } case Node.TEXT_NODE : { formatter = new TextNodeFormatter(); break; } case Node.CDATA_SECTION_NODE : { formatter = new NoMoveFormatter(); break; } case Node.COMMENT_NODE : { formatter = new CommentNodeFormatter(); break; } case Node.PROCESSING_INSTRUCTION_NODE : { formatter = new NodeFormatter(); break; } case Node.DOCUMENT_NODE : { formatter = new DocumentNodeFormatter(); break; } case Node.ENTITY_REFERENCE_NODE : { formatter = new NoMoveFormatter(); break; } default : { formatter = new NodeFormatter(); } } // init fomatter formatter.setFormatPreferences(getFormatPreferences()); formatter.setProgressMonitor(fProgressMonitor); return formatter; } protected int getIndentationLength(String indent) { // TODO Kit : The calculation of IndentationLength is not correct // here. // nodeIndentation may contain tabs. Multiply by 4 temporarily to get // approx. width. // Need to re-work. int indentationLength = 0; for (int i = 0; i < indent.length(); i++) { if (indent.substring(i, i + 1).compareTo(TAB) == 0) indentationLength += 4; else indentationLength++; } return indentationLength; } protected Preferences getModelPreferences() { return XMLCorePlugin.getDefault().getPluginPreferences(); } /** * This method will find the indentation for this node. It will search * backwards starting from the beginning of the node until a character * other than a space or a tab is found. If this node is null or it's a * document node or it's a first level node (node's parent is a document * node) the default empty string will be returned as the indentation. */ protected String getNodeIndent(Node node) { String result = EMPTY_STRING; if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) { IDOMNode siblingTextNode = (IDOMNode) node.getPreviousSibling(); if ((siblingTextNode != null) && (siblingTextNode.getNodeType() == Node.TEXT_NODE)) { // find the indentation String siblingText = siblingTextNode.getNodeValue(); int siblingTextLength = siblingText.length(); if ((siblingText != null) && (siblingTextLength > 0) && ((siblingText.charAt(siblingTextLength - 1) == SPACE_CHAR) || (siblingText.charAt(siblingTextLength - 1) == TAB_CHAR))) { int searchIndex = siblingTextLength - 1; while ((searchIndex >= 0) && ((siblingText.charAt(searchIndex) == SPACE_CHAR) || (siblingText.charAt(searchIndex) == TAB_CHAR))) searchIndex--; if (searchIndex < siblingTextLength) result = siblingText.substring(searchIndex + 1, siblingTextLength); } } } return result; } protected String getNodeName(IDOMNode node) { return node.getNodeName(); } protected String getNodeText(IDOMNode node) { String text = null; if ((node instanceof CharacterDataImpl) && !(node instanceof CommentImpl) && !(node instanceof CDATASectionImpl) && !isJSPTag(node)) text = ((CharacterDataImpl) node).getSource(); else text = node.getFirstStructuredDocumentRegion().getText(); return text; } protected IDOMNode getParentIndentNode(IDOMNode node) { IDOMNode result = null; IDOMNode parentNode = (IDOMNode) node.getParentNode(); if (parentNode.getNodeType() == Node.DOCUMENT_NODE) result = parentNode; else { ITextRegion region = parentNode.getLastStructuredDocumentRegion().getFirstRegion(); if (region.getType() == DOMRegionContext.XML_END_TAG_OPEN) result = parentNode; else result = getParentIndentNode(parentNode); } return result; } /** * This method will find the indentation for a node sibling to this node. * It will try to find a sibling node before this node first. If there is * no sibling node before this node, it will try to find a sibling node * after this node. If still not found, we will check if this node is * already indented from its parent. If yes, this node's indentation will * be used. Otherwise, the parent node's indentation plus one indentation * will be used. If this node is null or it's a document node or it's a * first level node (node's parent is a document node) the default empty * string will be returned as the indentation. */ protected String getSiblingIndent(Node node) { String result = EMPTY_STRING; if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) { // find the text node before the previous non-text sibling // if that's not found, we will try the text node before the next // non-text sibling IDOMNode sibling = (IDOMNode) node.getPreviousSibling(); while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE || sibling.getNodeType() == Node.COMMENT_NODE)) { if (sibling.getNodeType() == Node.COMMENT_NODE && sibling.getPreviousSibling() != null && sibling.getPreviousSibling().getNodeType() == Node.TEXT_NODE && StringUtils.containsLineDelimiter(sibling.getPreviousSibling().getNodeValue())) break; sibling = (IDOMNode) sibling.getPreviousSibling(); } if (sibling == null) { sibling = (IDOMNode) node.getNextSibling(); while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE)) sibling = (IDOMNode) sibling.getNextSibling(); } String singleIndent = getFormatPreferences().getIndent(); String parentLineIndent = getNodeIndent(node.getParentNode()); if (sibling != null) { String siblingIndent = getNodeIndent(sibling); if (siblingIndent.length() > 0) result = siblingIndent; else { String nodeIndent = getNodeIndent(node); if (nodeIndent.length() > parentLineIndent.length()) // this node is indented from its parent, its // indentation will be used result = nodeIndent; else result = parentLineIndent + singleIndent; } } else { String nodeIndent = getNodeIndent(node); if (nodeIndent.length() > parentLineIndent.length()) // this node is indented from its parent, its indentation // will be used result = nodeIndent; else result = parentLineIndent + singleIndent; } } return result; } protected void insertAfterNode(IDOMNode node, String string) { IDOMModel structuredModel = node.getModel(); IStructuredDocument structuredDocument = structuredModel.getStructuredDocument(); int offset = node.getEndOffset(); int length = 0; // 261968 - formatting tag without closing bracket: <t1><t1 if (node.getEndStructuredDocumentRegion() != null) { offset = node.getEndStructuredDocumentRegion().getTextEndOffset(); length = node.getEndOffset() - offset; } replace(structuredDocument, offset, length, string); } protected void insertBeforeNode(IDOMNode node, String string) { IDOMModel structuredModel = node.getModel(); IStructuredDocument structuredDocument = structuredModel.getStructuredDocument(); replace(structuredDocument, node.getStartOffset(), 0, string); } /** * Allowing the INodeAdapter to compare itself against the type allows it * to return true in more than one case. */ public boolean isAdapterForType(Object type) { return type.equals(IStructuredFormatter.class); } protected boolean isEndTagMissing(IDOMNode node) { boolean result = false; if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && !isJSPTag(node)) { IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getFirstStructuredDocumentRegion(); IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion(); ITextRegion startTagNameRegion = null; if (startTagStructuredDocumentRegion.getRegions().size() > 1) startTagNameRegion = startTagStructuredDocumentRegion.getRegions().get(1); ITextRegion endTagNameRegion = null; if (endTagStructuredDocumentRegion.getRegions().size() > 1) endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1); ITextRegionList startTagRegions = startTagStructuredDocumentRegion.getRegions(); if (startTagNameRegion == endTagNameRegion && startTagNameRegion != null && (startTagRegions.get(0)).getType() != DOMRegionContext.XML_END_TAG_OPEN && (startTagRegions.get(startTagRegions.size() - 1).getType()) != DOMRegionContext.XML_EMPTY_TAG_CLOSE) // end tag missing result = true; } return result; } protected boolean nodeHasSiblings(IDOMNode node) { return (node.getPreviousSibling() != null) || (node.getNextSibling() != null); } /** * Node changed. No format should be performed automatically. */ public void notifyChanged(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) { } protected void removeRegionSpaces(IDOMNode node, IStructuredDocumentRegion flatNode, ITextRegion region) { if ((region != null) && (region instanceof ContextRegion || region instanceof TagNameRegion) && (flatNode.getEndOffset(region) > flatNode.getTextEndOffset(region))) { IDOMModel structuredModel = node.getModel(); IStructuredDocument structuredDocument = structuredModel.getStructuredDocument(); replace(structuredDocument, flatNode.getTextEndOffset(region), flatNode.getEndOffset(region) - flatNode.getTextEndOffset(region), EMPTY_STRING); } } /** * This method will replace the string at offset and length with a new * string. If the string to be replaced is the same as the new string, the * string will not be replaced. */ protected void replace(IStructuredDocument structuredDocument, int offset, int length, String string) { try { String structuredDocumentString = structuredDocument.get(offset, length); if (structuredDocumentString.compareTo(string) != 0) structuredDocument.replaceText(structuredDocument, offset, length, string); } catch (BadLocationException e) { // log for now, unless we find reason not to Logger.log(Logger.INFO, e.getMessage()); } } /** * This method will replace the node value with a new string. If the node * value to be replaced is the same as the new string, the node value will * not be replaced. */ protected void replaceNodeValue(IDOMNode node, String string) { IDOMModel structuredModel = node.getModel(); IStructuredDocument structuredDocument = structuredModel.getStructuredDocument(); int offset = node.getStartOffset(); int length = node.getEndOffset() - node.getStartOffset(); try { String structuredDocumentString = structuredDocument.get(offset, length); if (structuredDocumentString.compareTo(string) != 0) replace(structuredDocument, offset, length, string); } catch (BadLocationException e) { // log for now, unless we find reason not to Logger.log(Logger.INFO, e.getMessage()); } } public void setFormatPreferences(IStructuredFormatPreferences formatPreferences) { fFormatPreferences = formatPreferences; } /* * (non-Javadoc) * * @see org.eclipse.wst.sse.core.format.IStructuredFormatter#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) */ public void setProgressMonitor(IProgressMonitor monitor) { fProgressMonitor = monitor; } /** * ISSUE: this is a bit of hidden JSP knowledge that was implemented this * way for expedency. Should be evolved in future to depend on * "nestedContext". */ private boolean isJSPTag(Node node) { final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$ // final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$ // final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$ // final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$ final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$ final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$ final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$ final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$ final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$ final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$ // final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$ final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$ boolean result = false; if (node instanceof IDOMNode) { IStructuredDocumentRegion flatNode = ((IDOMNode) node).getFirstStructuredDocumentRegion(); // in some cases, the nodes exists, but hasn't been associated // with // a flatnode yet (the screen updates can be initiated on a // different thread, // so the request for a flatnode can come in before the node is // fully formed. // if the flatnode is null, we'll just allow the defaults to // apply. if (flatNode != null) { String flatNodeType = flatNode.getType(); // should not be null, but just to be sure if (flatNodeType != null) { if ((flatNodeType.equals(JSP_CONTENT)) || (flatNodeType.equals(JSP_EXPRESSION_OPEN)) || (flatNodeType.equals(JSP_SCRIPTLET_OPEN)) || (flatNodeType.equals(JSP_DECLARATION_OPEN)) || (flatNodeType.equals(JSP_DIRECTIVE_CLOSE)) || (flatNodeType.equals(JSP_DIRECTIVE_NAME)) || (flatNodeType.equals(JSP_DIRECTIVE_OPEN)) || (flatNodeType.equals(JSP_CLOSE))) { result = true; } } } } return result; } }