Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'json/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/format/AbstractJSONSourceFormatter.java')
-rw-r--r--json/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/format/AbstractJSONSourceFormatter.java903
1 files changed, 903 insertions, 0 deletions
diff --git a/json/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/format/AbstractJSONSourceFormatter.java b/json/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/format/AbstractJSONSourceFormatter.java
new file mode 100644
index 0000000000..8d320bd61f
--- /dev/null
+++ b/json/bundles/org.eclipse.wst.json.core/src/org/eclipse/wst/json/core/internal/format/AbstractJSONSourceFormatter.java
@@ -0,0 +1,903 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2016 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
+ * Angelo Zerr <angelo.zerr@gmail.com> - copied from org.eclipse.wst.css.core.internal.formatter.AbstractCSSSourceFormatter
+ * modified in order to process JSON Objects.
+ *******************************************************************************/
+package org.eclipse.wst.json.core.internal.format;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.wst.json.core.JSONCorePlugin;
+import org.eclipse.wst.json.core.cleanup.IJSONCleanupStrategy;
+import org.eclipse.wst.json.core.cleanup.JSONCleanupStrategyImpl;
+import org.eclipse.wst.json.core.document.IJSONArray;
+import org.eclipse.wst.json.core.document.IJSONDocument;
+import org.eclipse.wst.json.core.document.IJSONModel;
+import org.eclipse.wst.json.core.document.IJSONNode;
+import org.eclipse.wst.json.core.document.IJSONObject;
+import org.eclipse.wst.json.core.internal.util.RegionIterator;
+import org.eclipse.wst.json.core.preferences.JSONCorePreferenceNames;
+import org.eclipse.wst.json.core.regions.JSONRegionContexts;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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;
+
+public abstract class AbstractJSONSourceFormatter implements
+ IJSONSourceFormatter {
+
+ protected final static short GENERATE = 0;
+ protected final static short FORMAT = 1;
+ protected final static short CLEANUP = 2;
+ protected static short strategy;
+
+ AbstractJSONSourceFormatter() {
+ super();
+ }
+
+ protected void appendDelimBefore(IJSONNode node, CompoundRegion toAppend,
+ StringBuilder source) {
+ if (node == null || source == null)
+ return;
+ if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
+ return; // for not formatting case on cleanup action
+ String delim = getLineDelimiter(node);
+
+ boolean needIndent = !(node instanceof IJSONDocument);
+ if (toAppend == null) {
+ source.append(delim);
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ } else {
+ String type = toAppend.getType();
+ if (type == JSONRegionContexts.JSON_COMMENT) {
+ RegionIterator it = new RegionIterator(
+ toAppend.getDocumentRegion(), toAppend.getTextRegion());
+ it.prev();
+ ITextRegion prev = it.prev();
+ int[] result = null;
+ if (prev == null
+ || (prev.getType() == JSONRegionContexts.WHITE_SPACE && (result = TextUtilities
+ .indexOf(DefaultLineTracker.DELIMITERS,
+ it.getStructuredDocumentRegion()
+ .getText(prev), 0))[0] >= 0)) {
+ // Collapse to one empty line if there's more than one.
+ if (result != null) {
+ int offset = result[0]
+ + DefaultLineTracker.DELIMITERS[result[1]]
+ .length();
+ if (offset < it.getStructuredDocumentRegion()
+ .getText(prev).length()) {
+ if (TextUtilities.indexOf(
+ DefaultLineTracker.DELIMITERS, it
+ .getStructuredDocumentRegion()
+ .getText(prev), offset)[0] >= 0) {
+ source.append(delim);
+ }
+ }
+ source.append(delim);
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ }
+ } else if (prev.getType() == JSONRegionContexts.JSON_COMMENT) {
+ String fullText = toAppend.getDocumentRegion().getFullText(
+ prev);
+ String trimmedText = toAppend.getDocumentRegion().getText(
+ prev);
+ String whiteSpaces = "";//$NON-NLS-1$
+ if (fullText != null && trimmedText != null)
+ whiteSpaces = fullText.substring(trimmedText.length());
+ int[] delimiterFound = TextUtilities.indexOf(
+ DefaultLineTracker.DELIMITERS, whiteSpaces, 0);
+ if (delimiterFound[0] != -1) {
+ source.append(delim);
+ } else {
+ appendSpaceBefore(node, toAppend.getText(), source);
+
+ /*
+ * If two comments can't be adjusted in one
+ * line(combined length exceeds line width), a tab is
+ * also appended along with next line delimiter , we
+ * need to remove that.
+ */
+ if (source.toString().endsWith(getIndentString())) {
+ source.delete((source.length() - getIndentString()
+ .length()), source.length());
+ }
+ }
+ } else {
+ appendSpaceBefore(node, toAppend.getText(), source);
+ }
+ } else if (type == JSONRegionContexts.JSON_COMMA) {
+ RegionIterator it = new RegionIterator(
+ toAppend.getDocumentRegion(), toAppend.getTextRegion());
+ it.prev();
+ ITextRegion prev = it.prev();
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+
+ if (prev.getType() == JSONRegionContexts.WHITE_SPACE
+ && TextUtilities.indexOf(DefaultLineTracker.DELIMITERS,
+ it.getStructuredDocumentRegion().getText(prev),
+ 0)[0] >= 0) {
+ source.append(delim);
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ } else if (preferences
+ .getInt(JSONCorePreferenceNames.LINE_WIDTH) > 0
+ && (!preferences
+ .getBoolean(JSONCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR) || node
+ .getOwnerDocument().getNodeType() != IJSONNode.PAIR_NODE)) {
+ int length = getLastLineLength(node, source);
+ int append = 1;
+ if (length + append > preferences
+ .getInt(JSONCorePreferenceNames.LINE_WIDTH)) {
+ source.append(getLineDelimiter(node));
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ }
+ }
+ } else
+ if (type == JSONRegionContexts.JSON_OBJECT_OPEN
+ || type == JSONRegionContexts.JSON_OBJECT_CLOSE
+ || type == JSONRegionContexts.JSON_ARRAY_OPEN
+ || type == JSONRegionContexts.JSON_ARRAY_CLOSE) {
+ source.append(delim);
+ source.append(getIndent(node));
+ } else {
+ source.append(delim);
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ }
+ }
+ }
+
+ protected void appendSpaceBefore(IJSONNode node, CompoundRegion toAppend,
+ StringBuilder source) {
+ if (node == null || toAppend == null || source == null)
+ return;
+ if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
+ return; // for not formatting case on cleanup action
+ String type = toAppend.getType();
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+
+ boolean needIndent = !(node instanceof IJSONDocument);
+ /*if (type == JSONRegionContexts.JSON_COMMENT) {
+ // check whether previous region is 'S' and has CR-LF
+ String delim = getLineDelimiter(node);
+ RegionIterator it = new RegionIterator(
+ toAppend.getDocumentRegion(), toAppend.getTextRegion());
+ it.prev();
+ ITextRegion prev = it.prev();
+ // bug390904
+ if (prev.getType() == JSONRegionContexts.JSON_LBRACE
+ && TextUtilities
+ .indexOf(DefaultLineTracker.DELIMITERS,
+ it.getStructuredDocumentRegion()
+ .getFullText(prev), 0)[0] > 0) {
+ source.append(delim);
+ source.append(getIndent(node));
+ source.append(getIndentString());
+ } else if (prev.getType() == JSONRegionContexts.WHITE_SPACE
+ && TextUtilities.indexOf(DefaultLineTracker.DELIMITERS, it
+ .getStructuredDocumentRegion().getText(prev), 0)[0] >= 0) {
+ source.append(delim);
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ } else {
+ appendSpaceBefore(node, toAppend.getText(), source);
+ }
+ }*/
+ if ((type == JSONRegionContexts.JSON_OBJECT_OPEN || type == JSONRegionContexts.JSON_ARRAY_OPEN)
+ && preferences
+ .getBoolean(JSONCorePreferenceNames.WRAPPING_NEWLINE_ON_OPEN_BRACE)) {
+ String delim = getLineDelimiter(node);
+ source.append(delim);
+ source.append(getIndent(node));
+ // } else if (type == JSONRegionContexts.JSON_CURLY_BRACE_CLOSE) {
+ // } else if (type == JSONRegionContexts.JSON_INCLUDES || type ==
+ // JSONRegionContexts.JSON_DASHMATCH) {
+ /*} else if (type == JSONRegionContexts.JSON_DECLARATION_SEPARATOR
+ && node instanceof IJSONStyleDeclItem) {
+ int n = preferences
+ .getInt(JSONCorePreferenceNames.FORMAT_PROP_PRE_DELIM);
+ // no delimiter case
+ while (n-- > 0)
+ source.append(" ");//$NON-NLS-1$
+ } else if (type == JSONRegionContexts.JSON_DECLARATION_VALUE_OPERATOR
+ || type == JSONRegionContexts.JSON_DECLARATION_VALUE_PARENTHESIS_CLOSE) {
+ if (preferences.getInt(JSONCorePreferenceNames.LINE_WIDTH) > 0
+ && (!preferences
+ .getBoolean(JSONCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR) || node
+ .getOwnerDocument().getNodeType() != IJSONNode.STYLEDECLARATION_NODE)) {
+ int length = getLastLineLength(node, source);
+ int append = 1;
+ if (length + append > preferences
+ .getInt(JSONCorePreferenceNames.LINE_WIDTH)) {
+ source.append(getLineDelimiter(node));
+ source.append(getIndent(node));
+ if (needIndent)
+ source.append(getIndentString());
+ }
+ }
+ } else if (JSONRegionContexts.JSON_FOREIGN_ELEMENT == type
+ || JSONRegionContexts.JSON_DECLARATION_DELIMITER == type) {
+ return;
+ */
+ } else
+ appendSpaceBefore(node, toAppend.getText(), source);
+ }
+
+ protected void appendSpaceBefore(IJSONNode node, String toAppend,
+ StringBuilder source) {
+ if (node == null || source == null)
+ return;
+ if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
+ return; // for not formatting case on cleanup action
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+ if (toAppend != null
+ && toAppend.startsWith("{") && preferences.getBoolean(JSONCorePreferenceNames.WRAPPING_NEWLINE_ON_OPEN_BRACE)) {//$NON-NLS-1$
+ source.append(getLineDelimiter(node));
+ source.append(getIndent(node));
+ return;
+ } else if (/* ! mgr.isOnePropertyPerLine() && */preferences
+ .getInt(JSONCorePreferenceNames.LINE_WIDTH) > 0
+ && (!preferences
+ .getBoolean(JSONCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR)
+ /*|| node
+ .getOwnerDocument().getNodeType() != IJSONNode.STYLEDECLARATION_NODE*/)) {
+ int n = getLastLineLength(node, source);
+ int append = (toAppend != null) ? TextUtilities.indexOf(
+ DefaultLineTracker.DELIMITERS, toAppend, 0)[0] : 0;
+ if (toAppend != null)
+ append = (append < 0) ? toAppend.length() : append;
+ if (n + append + 1 > preferences
+ .getInt(JSONCorePreferenceNames.LINE_WIDTH)) {
+ source.append(getLineDelimiter(node));
+ source.append(getIndent(node));
+ source.append(getIndentString());
+ return;
+ }
+ }
+ // bug412395
+ // just verify if the source and the toAppend strings do not end with a
+ // whitespace to avoid the whitespace duplication.
+ if (!(source.length() > 0 && source.toString().charAt(
+ source.length() - 1) == ' ')
+ && !(toAppend.length() > 0 && toAppend
+ .charAt(toAppend.length() - 1) == ' ')) {
+ source.append(" ");//$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public final StringBuilder cleanup(IJSONNode node) {
+ short oldStrategy = strategy;
+ strategy = CLEANUP;
+ StringBuilder source = formatProc(node);
+ strategy = oldStrategy;
+ return source;
+ }
+
+ @Override
+ public final StringBuilder cleanup(IJSONNode node, IRegion region) {
+ short oldStrategy = strategy;
+ strategy = CLEANUP;
+ StringBuilder source = formatProc(node, region);
+ strategy = oldStrategy;
+
+ return source;
+ }
+
+ protected String decoratedIdentRegion(CompoundRegion region,
+ IJSONCleanupStrategy stgy) {
+ if (isFormat())
+ return region.getText();
+
+ String text = null;
+ if (!stgy.isFormatSource())
+ text = region.getFullText();
+ else
+ text = region.getText();
+
+// if (region.getType() == JSONRegionContexts.WHITE_SPACETRING
+// || region.getType() == JSONRegionContexts.JSON_URI)
+// return decoratedRegion(region, 0, stgy);
+
+ if (isCleanup()) {
+ if (stgy.getIdentCase() == IJSONCleanupStrategy.ASIS
+ /*|| region.getType() == JSONRegionContexts.JSON_COMMENT*/)
+ return text;
+ else if (stgy.getIdentCase() == IJSONCleanupStrategy.UPPER)
+ return text.toUpperCase();
+ else
+ return text.toLowerCase();
+ }
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+// if (region.getType() == JSONRegionContexts.JSON_COMMENT)
+// return text;
+// else if (preferences.getInt(JSONCorePreferenceNames.CASE_IDENTIFIER) == JSONCorePreferenceNames.UPPER)
+// return text.toUpperCase();
+// else
+ return text.toLowerCase();
+ }
+
+ protected String decoratedPropNameRegion(CompoundRegion region,
+ IJSONCleanupStrategy stgy) {
+ if (isFormat())
+ return region.getText();
+
+ String text = null;
+ if (!stgy.isFormatSource())
+ text = region.getFullText();
+ else
+ text = region.getText();
+
+// if (region.getType() == JSONRegionContexts.WHITE_SPACETRING
+// || region.getType() == JSONRegionContexts.JSON_URI)
+// return decoratedRegion(region, 1, stgy);
+ if (isCleanup()) {
+ /*if (stgy.getPropNameCase() == JSONCleanupStrategy.ASIS
+ || region.getType() != JSONRegionContexts.JSON_DECLARATION_PROPERTY)
+ return text;
+ else*/
+ if (stgy.getPropNameCase() == IJSONCleanupStrategy.UPPER)
+ return text.toUpperCase();
+ else
+ return text.toLowerCase();
+ }
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+
+// if (region.getType() != JSONRegionContexts.JSON_DECLARATION_PROPERTY)
+// return text;
+ //else
+ if (preferences.getInt(JSONCorePreferenceNames.CASE_PROPERTY_NAME) == JSONCorePreferenceNames.UPPER)
+ return text.toUpperCase();
+ else
+ return text.toLowerCase();
+ }
+
+ protected String decoratedPropValueRegion(CompoundRegion region,
+ IJSONCleanupStrategy stgy) {
+ if (isFormat())
+ return region.getText();
+
+ String text = null;
+ if (!stgy.isFormatSource())
+ text = region.getFullText();
+ else
+ text = region.getText();
+
+ String type = region.getType();
+// if (type == JSONRegionContexts.WHITE_SPACETRING
+// || type == JSONRegionContexts.JSON_URI
+// || type == JSONRegionContexts.JSON_DECLARATION_VALUE_URI)
+// return decoratedRegion(region, 2, stgy);
+ if (isCleanup()) {
+ if (stgy.getPropValueCase() != IJSONCleanupStrategy.ASIS) {
+ //if (type == JSONRegionContexts.JSON_COMMENT) {
+ //} else {
+ if (stgy.getPropValueCase() == IJSONCleanupStrategy.UPPER)
+ text = text.toUpperCase();
+ else
+ text = text.toLowerCase();
+ //}
+ }
+ }
+ return text;
+ }
+
+ protected String decoratedRegion(CompoundRegion region, int type,
+ IJSONCleanupStrategy stgy) {
+ if (isFormat())
+ return region.getText();
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+
+ String text = null;
+ if (!stgy.isFormatSource())
+ text = region.getFullText();
+ else
+ text = region.getText();
+ return text;
+ }
+
+ @Override
+ public final StringBuilder format(IJSONNode node) {
+ short oldStrategy = strategy;
+ strategy = FORMAT;
+ StringBuilder source = formatProc(node);
+ strategy = oldStrategy;
+
+ return source;
+ }
+
+ @Override
+ public final StringBuilder format(IJSONNode node, IRegion region) {
+ short oldStrategy = strategy;
+ strategy = FORMAT;
+ StringBuilder source = formatProc(node, region);
+ strategy = oldStrategy;
+ return source;
+ }
+
+ protected void formatChildren(IJSONNode node, StringBuilder source) {
+ IJSONNode child = node.getFirstChild();
+ IJSONNode last = null;
+ while (child != null) {
+ // append child
+ IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) child)
+ .getAdapterFor(IJSONSourceFormatter.class);
+ if (formatter == null) {
+ formatter = JSONSourceFormatterFactory.getInstance()
+ .getSourceFormatter(child);
+ }
+ StringBuilder childSource = ((AbstractJSONSourceFormatter) formatter)
+ .formatProc(child);
+ source.append(childSource);
+ last = child;
+ child = child.getNextSibling();
+ }
+ }
+
+ protected void formatChildren(IJSONNode node, IRegion region,
+ StringBuilder source) {
+ IJSONNode child = node.getFirstChild();
+ int start = region.getOffset();
+ int end = region.getOffset() + region.getLength();
+ while (child != null) {
+ int curEnd = child.getEndOffset();
+ StringBuilder childSource = null;
+ boolean toFinish = false;
+ if (start < curEnd) {
+ int curStart = child.getStartOffset();
+ if (curStart < end) {
+ // append child
+ IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) child)
+ .getAdapterFor(IJSONSourceFormatter.class);
+ if (formatter == null) {
+ formatter = JSONSourceFormatterFactory.getInstance()
+ .getSourceFormatter(child);
+ }
+ if (includes(region, curStart, curEnd))
+ childSource = ((AbstractJSONSourceFormatter) formatter)
+ .formatProc(child);
+ else
+ childSource = ((AbstractJSONSourceFormatter) formatter)
+ .formatProc(
+ child,
+ overlappedRegion(region, curStart,
+ curEnd));
+ } else
+ toFinish = true;
+ }
+ if (childSource != null) {
+ source.append(childSource);
+ }
+ if (toFinish)
+ break;
+ child = child.getNextSibling();
+ }
+ }
+
+ /**
+ * Generate or format source after the last child and append to string
+ * buffer
+ */
+ protected abstract void formatPost(IJSONNode node, StringBuilder source);
+
+ /**
+ * Generate or format source after the last child and append to string
+ * buffer
+ */
+ protected abstract void formatPost(IJSONNode node, IRegion region,
+ StringBuilder source);
+
+ /**
+ * Generate or format source before the first child and append to string
+ * buffer
+ */
+ protected abstract void formatPre(IJSONNode node, StringBuilder source);
+
+ /**
+ * Generate or format source before the first child and append to string
+ * buffer
+ */
+ abstract protected void formatPre(IJSONNode node, IRegion region,
+ StringBuilder source);
+
+ /**
+ *
+ * @return java.lang.StringBuilder
+ * @param node
+ * org.eclipse.wst.css.core.model.interfaces.IJSONNode
+ */
+ protected final StringBuilder formatProc(IJSONNode node) {
+ StringBuilder source = new StringBuilder();
+ formatPre(node, source);
+ formatChildren(node, source);
+ formatPost(node, source);
+ return source;
+ }
+
+ /**
+ *
+ * @return java.lang.StringBuilder
+ * @param node
+ * org.eclipse.wst.css.core.model.interfaces.IJSONNode
+ * @param region
+ * org.eclipse.jface.text.IRegion
+ */
+ protected StringBuilder formatProc(IJSONNode node, IRegion region) {
+ StringBuilder source = new StringBuilder();
+ int curStart = node.getStartOffset();
+ int curEnd = node.getEndOffset();
+ if (node.hasChildNodes()) {
+ curEnd = node.getFirstChild().getStartOffset();
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd))
+ formatPre(node, source);
+ else
+ formatPre(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ curStart = curEnd;
+ curEnd = node.getLastChild().getEndOffset();
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd))
+ formatChildren(node, source);
+ else
+ formatChildren(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ curStart = curEnd;
+ curEnd = node.getEndOffset();
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd))
+ formatPost(node, source);
+ else
+ formatPost(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ } else if (node instanceof IJSONArray || node instanceof IJSONObject) {
+ curStart = node.getStartOffset();
+ curEnd = node.getEndOffset();
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd)) {
+ formatPre(node, source);
+ formatPost(node, source);
+ } else {
+ formatPre(node, overlappedRegion(region, curStart, curEnd), source);
+ formatPost(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ }
+ } else {
+ // curEnd = getChildInsertPos(node);
+ curEnd = node.getEndOffset() > 0 ? node.getEndOffset() : -1;
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd))
+ formatPre(node, source);
+ else
+ formatPre(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ curStart = curEnd;
+ curEnd = node.getEndOffset();
+ if (overlaps(region, curStart, curEnd)) {
+ if (includes(region, curStart, curEnd))
+ formatPost(node, source);
+ else
+ formatPost(node, overlappedRegion(region, curStart, curEnd), source);
+ }
+ }
+ return source;
+ }
+
+ /**
+ * Insert the method's description here.
+ *
+ * @return org.eclipse.wst.css.core.internal.cleanup.JSONCleanupStrategy
+ * @param node
+ * org.eclipse.wst.css.core.model.interfaces.IJSONNode
+ */
+ protected IJSONCleanupStrategy getCleanupStrategy(IJSONNode node) {
+ IJSONCleanupStrategy currentStrategy = JSONCleanupStrategyImpl
+ .getInstance();
+ IJSONDocument doc = node.getOwnerDocument();
+ if (doc == null)
+ return currentStrategy;
+ IJSONModel model = doc.getModel();
+ if (model == null)
+ return currentStrategy;
+ return currentStrategy;
+ }
+
+ protected String getIndent(IJSONNode node) {
+ if (node == null)
+ return "";//$NON-NLS-1$
+ IJSONNode parent = node.getParentNode();
+ if (parent == null || parent instanceof IJSONDocument)
+ return "";//$NON-NLS-1$
+ String parentIndent = getIndent(parent);
+ return parentIndent + getIndentString();
+ }
+
+ protected int getLastLineLength(IJSONNode node, StringBuilder source) {
+ if (node == null || source == null)
+ return 0;
+ String delim = getLineDelimiter(node);
+ String str = new String(source);
+ int n = str.lastIndexOf(delim);
+ if (n < 0)
+ return str.length();
+
+ return str.length() - n - delim.length();
+ }
+
+ String getLineDelimiter(IJSONNode node) {
+ IJSONModel model = node != null ?
+ node.getOwnerDocument().getModel() :
+ null;
+ IStructuredDocument structuredDocument = model != null ?
+ model.getStructuredDocument() :
+ null;
+ return structuredDocument != null ?
+ structuredDocument.getLineDelimiter() :
+ "\n"; //$NON-NLS-1$
+ }
+
+ protected CompoundRegion[] getOutsideRegions(IStructuredDocument model,
+ IRegion reg) {
+ CompoundRegion[] ret = new CompoundRegion[2];
+ RegionIterator it = new RegionIterator(model, reg.getOffset());
+ it.prev();
+ if (it.hasPrev()) {
+ ITextRegion textRegion = it.prev();
+ IStructuredDocumentRegion documentRegion = it
+ .getStructuredDocumentRegion();
+ ret[0] = new CompoundRegion(documentRegion, textRegion);
+ } else {
+ ret[0] = null;
+ }
+ it.reset(model, reg.getOffset() + reg.getLength());
+ if (it.hasNext()) {
+ ITextRegion textRegion = it.next();
+ IStructuredDocumentRegion documentRegion = it
+ .getStructuredDocumentRegion();
+ ret[1] = new CompoundRegion(documentRegion, textRegion);
+ } else {
+ ret[1] = null;
+ }
+ return ret;
+ }
+
+ protected IJSONSourceFormatter getParentFormatter(IJSONNode node) {
+ IJSONNode parent = node.getParentNode();
+ if (parent != null) {
+ IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) parent)
+ .getAdapterFor(IJSONSourceFormatter.class);
+ if (formatter == null) {
+ formatter = JSONSourceFormatterFactory.getInstance()
+ .getSourceFormatter(parent);
+ }
+ return formatter;
+ }
+ return null;
+ }
+
+ protected CompoundRegion[] getRegions(IStructuredDocument model,
+ IRegion reg, IRegion exceptFor, String pickupType) {
+ int start = reg.getOffset();
+ int end = reg.getOffset() + reg.getLength();
+ int startE = (exceptFor != null) ? exceptFor.getOffset() : -1;
+ int endE = (exceptFor != null) ? exceptFor.getOffset()
+ + exceptFor.getLength() : 0;
+
+ ArrayList list = new ArrayList();
+ IStructuredDocumentRegion flatNode = model
+ .getRegionAtCharacterOffset(start);
+ boolean pickuped = false;
+ while (flatNode != null && flatNode.getStartOffset() < end) {
+ ITextRegionList regionList = flatNode.getRegions();
+ Iterator it = regionList.iterator();
+ while (it.hasNext()) {
+ ITextRegion region = (ITextRegion) it.next();
+ if (flatNode.getStartOffset(region) < start)
+ continue;
+ if (end <= flatNode.getStartOffset(region))
+ break;
+ if (startE >= 0 && startE <= flatNode.getStartOffset(region)
+ && flatNode.getEndOffset(region) <= endE)
+ continue;
+// if (region.getType() == JSONRegionContexts.JSON_COMMENT
+// || region.getType() == JSONRegionContexts.JSON_CDC
+// || region.getType() == JSONRegionContexts.JSON_CDO)
+// list.add(new CompoundRegion(flatNode, region));
+// else
+ if (!pickuped && region.getType() == pickupType) {
+ list.add(new CompoundRegion(flatNode, region));
+ pickuped = true;
+ }
+ }
+ flatNode = flatNode.getNext();
+ }
+ if (list.size() > 0) {
+ CompoundRegion[] regions = new CompoundRegion[list.size()];
+ list.toArray(regions);
+ return regions;
+ }
+ return new CompoundRegion[0];
+ }
+
+ protected CompoundRegion[] getRegionsWithoutWhiteSpaces(
+ IStructuredDocument model, IRegion reg, IJSONCleanupStrategy stgy) {
+ int start = reg.getOffset();
+ int end = reg.getOffset() + reg.getLength() - 1;
+ ArrayList list = new ArrayList();
+ IStructuredDocumentRegion flatNode = model
+ .getRegionAtCharacterOffset(start);
+ while (flatNode != null && flatNode.getStartOffset() <= end) {
+ ITextRegionList regionList = flatNode.getRegions();
+ Iterator it = regionList.iterator();
+ while (it.hasNext()) {
+ ITextRegion region = (ITextRegion) it.next();
+ if (flatNode.getStartOffset(region) < start)
+ continue;
+ if (end < flatNode.getStartOffset(region))
+ break;
+ if (region.getType() != JSONRegionContexts.WHITE_SPACE
+ || (isCleanup() && !stgy.isFormatSource())) // for
+ // not
+ // formatting
+ // case
+ // on
+ // cleanup
+ // action
+ list.add(new CompoundRegion(flatNode, region));
+ }
+ flatNode = flatNode.getNext();
+ }
+ if (list.size() > 0) {
+ CompoundRegion[] regions = new CompoundRegion[list.size()];
+ list.toArray(regions);
+ return regions;
+ }
+ return new CompoundRegion[0];
+ }
+
+ public static boolean includes(IRegion region, int start, int end) {
+ if (region == null)
+ return false;
+
+ return (region.getOffset() <= start)
+ && (end <= region.getOffset() + region.getLength());
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ protected static boolean isCleanup() {
+ return strategy == CLEANUP;
+ }
+
+ /**
+ *
+ * @return boolean
+ */
+ protected static boolean isFormat() {
+ return strategy == FORMAT;
+ }
+
+ protected boolean isIncludesPreEnd(IJSONNode node, IRegion region) {
+ return (node.getFirstChild() != null && ((IndexedRegion) node
+ .getFirstChild()).getStartOffset() == (region.getOffset() + region
+ .getLength()));
+ }
+
+ static protected boolean needS(CompoundRegion region) {
+ return (region != null && region.getType() != JSONRegionContexts.WHITE_SPACE);
+ }
+
+ public static IRegion overlappedRegion(IRegion region, int start, int end) {
+ if (overlaps(region, start, end)) {
+ int offset = (region.getOffset() <= start) ? start : region
+ .getOffset();
+ int length = ((end <= region.getOffset() + region.getLength()) ? end
+ : region.getOffset() + region.getLength())
+ - offset;
+ return new FormatRegion(offset, length);
+ }
+ return null;
+ }
+
+ public static boolean overlaps(IRegion region, int start, int end) {
+ if (region == null)
+ return false;
+
+ return (start < region.getOffset() + region.getLength())
+ && (region.getOffset() < end);
+ }
+
+ protected String getIndentString() {
+ StringBuilder indent = new StringBuilder();
+
+ Preferences preferences = JSONCorePlugin.getDefault()
+ .getPluginPreferences();
+ if (preferences != null) {
+ char indentChar = ' ';
+ String indentCharPref = preferences
+ .getString(JSONCorePreferenceNames.INDENTATION_CHAR);
+ if (JSONCorePreferenceNames.TAB.equals(indentCharPref)) {
+ indentChar = '\t';
+ }
+ int indentationWidth = preferences
+ .getInt(JSONCorePreferenceNames.INDENTATION_SIZE);
+
+ for (int i = 0; i < indentationWidth; i++) {
+ indent.append(indentChar);
+ }
+ }
+ return indent.toString();
+ }
+
+ protected void formatValue(IJSONNode node, StringBuilder source, IJSONNode value) {
+ IJSONCleanupStrategy stgy = getCleanupStrategy(node);
+ IStructuredDocument structuredDocument = node.getOwnerDocument().getModel().getStructuredDocument();
+ int start = node.getStartOffset();
+ int end = node.getEndOffset();
+ CompoundRegion[] regions = getRegionsWithoutWhiteSpaces(structuredDocument,
+ new FormatRegion(start, end - start), stgy);
+ if (regions.length > 2) {
+ for (int i = 2; i < regions.length; i++) {
+ source.append(decoratedRegion(regions[i], 0, stgy));
+ }
+ }
+ }
+
+ protected void formatObject(IJSONNode node, StringBuilder source, IJSONNode jsonObject) {
+ IJSONCleanupStrategy stgy = getCleanupStrategy(node);
+ IStructuredDocument structuredDocument = node.getOwnerDocument().getModel().getStructuredDocument();
+ IStructuredDocumentRegion[] structuredRegions = structuredDocument
+ .getStructuredDocumentRegions(node.getStartOffset(), node.getEndOffset());
+ if (structuredRegions.length >= 2) {
+ int start = structuredRegions[1].getStartOffset();
+ int end = node.getEndOffset();
+ IJSONSourceFormatter formatter = (IJSONSourceFormatter) ((INodeNotifier) jsonObject)
+ .getAdapterFor(IJSONSourceFormatter.class);
+ if (formatter == null) {
+ formatter = JSONSourceFormatterFactory.getInstance().getSourceFormatter(jsonObject);
+ }
+ StringBuilder objectSource = formatter.format(jsonObject, new FormatRegion(start, end - start));
+ if (objectSource != null) {
+ source.append(objectSource);
+ }
+ }
+ }
+
+} \ No newline at end of file

Back to the top