class="net.sourceforge.phpdt.internal.ui.preferences.TemplatePreferencePage"
id="net.sourceforge.phpeclipse.preference.TemplatePreferencePage">
</page>
+ <page
+ name="Formatter"
+ id="net.sourceforge.phpeclipse.preference.CodeFormatterPreferencePage"
+ class="net.sourceforge.phpdt.internal.ui.preferences.CodeFormatterPreferencePage"
+ category="net.sourceforge.phpeclipse.preference.PHPEclipsePreferencePage">
+ </page>
<page
name="Language Settings"
category="net.sourceforge.phpeclipse.preference.PHPEclipsePreferencePage"
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Specification for a generic source code formatter. Client plug-ins can contribute
+ * an implementation for an ICodeFormatter, through the extension point "org.phpeclipse.phpdt.core.codeFormatter".
+ * In case none is found, a default formatter can be provided through the ToolFactory.
+ *
+ * @see ToolFactory#createCodeFormatter()
+ * @see ToolFactory#createDefaultCodeFormatter(Map options)
+ * @since 2.0
+ */
+public interface ICodeFormatter {
+
+ /**
+ * Formats the String <code>sourceString</code>,
+ * and returns a string containing the formatted version.
+ *
+ * @param string the string to format
+ * @param indentationLevel the initial indentation level, used
+ * to shift left/right the entire source fragment. An initial indentation
+ * level of zero has no effect.
+ * @param positions an array of positions to map. These are
+ * character-based source positions inside the original source,
+ * for which corresponding positions in the formatted source will
+ * be computed (so as to relocate elements associated with the original
+ * source). It updates the positions array with updated positions.
+ * If set to <code>null</code>, then no positions are mapped.
+ * @param lineSeparator the line separator to use in formatted source,
+ * if set to <code>null</code>, then the platform default one will be used.
+ * @return the formatted output string.
+ */
+ String format(String string, int indentationLevel, int[] positions, String lineSeparator);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added #createScanner allowing to make comment check stricter
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.PHPCore;
+
+import org.eclipse.core.runtime.Plugin;
+import org.phpeclipse.phpdt.internal.formatter.CodeFormatter;
+
+/**
+ * Factory for creating various compiler tools, such as scanners, parsers and compilers.
+ * <p>
+ * This class provides static methods only; it is not intended to be instantiated or subclassed by clients.
+ * </p>
+ *
+ * @since 2.0
+ */
+public class ToolFactory {
+
+ /**
+ * Create an instance of a code formatter. A code formatter implementation can be contributed via the
+ * extension point "org.phpeclipse.phpdt.core.codeFormatter". If unable to find a registered extension, the factory
+ * will default to using the default code formatter.
+ *
+ * @return an instance of a code formatter
+ * @see ICodeFormatter
+ * @see ToolFactory#createDefaultCodeFormatter(Map)
+ */
+ public static ICodeFormatter createCodeFormatter(){
+
+ Plugin jdtCorePlugin = PHPCore.getPlugin();
+ if (jdtCorePlugin == null) return null;
+
+// IExtensionPoint extension = jdtCorePlugin.getDescriptor().getExtensionPoint(JavaModelManager.FORMATTER_EXTPOINT_ID);
+// if (extension != null) {
+// IExtension[] extensions = extension.getExtensions();
+// for(int i = 0; i < extensions.length; i++){
+// IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+// for(int j = 0; j < configElements.length; j++){
+// try {
+// Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
+// if (execExt instanceof ICodeFormatter){
+// // use first contribution found
+// return (ICodeFormatter)execExt;
+// }
+// } catch(CoreException e){
+// }
+// }
+// }
+// }
+ // no proper contribution found, use default formatter
+ return createDefaultCodeFormatter(null);
+ }
+
+ /**
+ * Create an instance of the built-in code formatter. A code formatter implementation can be contributed via the
+ * extension point "org.phpeclipse.phpdt.core.codeFormatter". If unable to find a registered extension, the factory will
+ * default to using the default code formatter.
+ *
+ * @param options - the options map to use for formatting with the default code formatter. Recognized options
+ * are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
+ * the current settings from <code>JavaCore#getOptions</code>.
+ * @return an instance of the built-in code formatter
+ * @see ICodeFormatter
+ * @see ToolFactory#createCodeFormatter()
+ * @see JavaCore#getOptions()
+ */
+ public static ICodeFormatter createDefaultCodeFormatter(Map options){
+
+ if (options == null) options = PHPCore.getOptions();
+ return new CodeFormatter(options);
+ }
+
+ /**
+ * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+ * used to tokenize some source in a Java aware way.
+ * Here is a typical scanning loop:
+ *
+ * <code>
+ * <pre>
+ * IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+ * scanner.setSource("int i = 0;".toCharArray());
+ * while (true) {
+ * int token = scanner.getNextToken();
+ * if (token == ITerminalSymbols.TokenNameEOF) break;
+ * System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+ * }
+ * </pre>
+ * </code>
+ *
+ * <p>
+ * The returned scanner will tolerate unterminated line comments (missing line separator). It can be made stricter
+ * by using API with extra boolean parameter (<code>strictCommentMode</code>).
+ * <p>
+ * @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
+ * @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
+ * @param assertKeyword if set to <code>false</code>, occurrences of 'assert' will be reported as identifiers
+ * (<code>ITerminalSymbols#TokenNameIdentifier</code>), whereas if set to <code>true</code>, it
+ * would report assert keywords (<code>ITerminalSymbols#TokenNameassert</code>). Java 1.4 has introduced
+ * a new 'assert' keyword.
+ * @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
+ * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+ * can then be extracted using <code>IScanner#getLineEnds</code>. Only non-unicode escape sequences are
+ * considered as valid line separators.
+ * @return a scanner
+ * @see ToolFactory#createScanner(boolean,boolean,boolean,boolean, boolean)
+ * @see org.phpeclipse.phpdt.core.compiler.IScanner
+ */
+// public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator){
+// return createScanner(tokenizeComments, tokenizeWhiteSpace, assertMode, recordLineSeparator, false);
+// }
+
+ /**
+ * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+ * used to tokenize some source in a Java aware way.
+ * Here is a typical scanning loop:
+ *
+ * <code>
+ * <pre>
+ * IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+ * scanner.setSource("int i = 0;".toCharArray());
+ * while (true) {
+ * int token = scanner.getNextToken();
+ * if (token == ITerminalSymbols.TokenNameEOF) break;
+ * System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+ * }
+ * </pre>
+ * </code>
+ *
+ * @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
+ * @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
+ * @param assertMode if set to <code>false</code>, occurrences of 'assert' will be reported as identifiers
+ * (<code>ITerminalSymbols#TokenNameIdentifier</code>), whereas if set to <code>true</code>, it
+ * would report assert keywords (<code>ITerminalSymbols#TokenNameassert</code>). Java 1.4 has introduced
+ * a new 'assert' keyword.
+ * @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
+ * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+ * can then be extracted using <code>IScanner#getLineEnds</code>. Only non-unicode escape sequences are
+ * considered as valid line separators.
+ * @param strictCommentMode if set to <code>true</code>, line comments with no trailing line separator will be
+ * treated as invalid tokens.
+ * @return a scanner
+ *
+ * @see org.phpeclipse.phpdt.core.compiler.IScanner
+ * @since 2.1
+ */
+// public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator, boolean strictCommentMode){
+//
+// PublicScanner scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/, assertMode, strictCommentMode /*strict comment*/, null/*taskTags*/, null/*taskPriorities*/);
+// scanner.recordLineSeparator = recordLineSeparator;
+// return scanner;
+// }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core.compiler;
+
+/**
+ * This class is a collection of helper methods to manipulate char arrays.
+ *
+ * @since 2.1
+ */
+public final class CharOperation {
+
+ /**
+ * Constant for an empty char array
+ */
+ public static final char[] NO_CHAR = new char[0];
+
+ /**
+ * Constant for an empty char array with two dimensions.
+ */
+ public static final char[][] NO_CHAR_CHAR = new char[0][];
+
+ /**
+ * Answers a new array with appending the suffix character at the end of the array.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * array = { 'a', 'b' }
+ * suffix = 'c'
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = null
+ * suffix = 'c'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @param array the array that is concanated with the suffix character
+ * @param suffix the suffix character
+ * @return the new array
+ */
+ public static final char[] append(char[] array, char suffix) {
+ if (array == null)
+ return new char[] { suffix };
+ int length = array.length;
+ System.arraycopy(array, 0, array = new char[length + 1], 0, length);
+ array[length] = suffix;
+ return array;
+ }
+ /**
+ * Append the given subarray to append to the target array starting at the given index in the target array.
+ * The start of the subarray is inclusive, the end is exclusive.
+ * Answers a new target array if it needs to grow, otherwise answers the same target array.
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * target = { 'a', 'b', -1 }
+ * index = 0
+ * array = { 'c', 'd' }
+ * start = 0
+ * end = 1
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * target = { 'a', 'b' }
+ * index = 0
+ * array = { 'c', 'd' }
+ * start = 0
+ * end = 1
+ * => result = new { 'a', 'b' , 'c', -1 }
+ * </pre></li>
+ * <li><pre>
+ * target = { 'a', 'b', 'c' }
+ * index = 1
+ * array = { 'c', 'd', 'e', 'f' }
+ * start = 1
+ * end = 4
+ * => result = new { 'a', 'd' , 'e', 'f', -1, -1 }
+ * </pre></li>
+ * </ol>
+ */
+ public static final char[] append(char[] target, int index, char[] array, int start, int end) {
+ int targetLength = target.length;
+ int subLength = end-start;
+ int newTargetLength = subLength+index;
+ if (newTargetLength > targetLength) {
+ System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
+ }
+ System.arraycopy(array, start, target, index, subLength);
+ return target;
+ }
+
+ /**
+ * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * => result = null
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = null
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = null
+ * second = { { ' a' } }
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' b' } }
+ * second = { { ' a' } }
+ * => result = { { ' b' }, { ' a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @return the concatenation of the two arrays, or null if the two arrays are null.
+ */
+ public static final char[][] arrayConcat(char[][] first, char[][] second) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+
+ int length1 = first.length;
+ int length2 = second.length;
+ char[][] result = new char[length1 + length2][];
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ return result;
+ }
+
+ /**
+ * Answers a new array adding the second array at the end of first array.
+ * It answers null if the first and second are null.
+ * If the first array is null, then a new array char[][] is created with second.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * => result = { { ' a' } }
+ * </pre>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = null
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = { ' b' }
+ * => result = { { ' a' } , { ' b' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the array to add at the end of the first array
+ * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
+ */
+ public static final char[][] arrayConcat(char[][] first, char[] second) {
+ if (second == null)
+ return first;
+ if (first == null)
+ return new char[][] { second };
+
+ int length = first.length;
+ char[][] result = new char[length + 1][];
+ System.arraycopy(first, 0, result, 0, length);
+ result[length] = second;
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = null
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = { ' b' }
+ * => result = { ' a' , ' b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @return the concatenation of the two arrays, or null if the two arrays are null.
+ */
+ public static final char[] concat(char[] first, char[] second) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+
+ int length1 = first.length;
+ int length2 = second.length;
+ char[] result = new char[length1 + length2];
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
+ * If first is null, it answers the concatenation of second and third.
+ * If second is null, it answers the concatenation of first and third.
+ * If third is null, it answers the concatenation of first and second.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = null
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = null
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = null
+ * second = null
+ * third = null
+ * => result = null
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = { 'c' }
+ * => result = { 'a', 'b', 'c' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @param third the third array to concatenate
+ *
+ * @return the concatenation of the three arrays, or null if the three arrays are null.
+ */
+ public static final char[] concat(
+ char[] first,
+ char[] second,
+ char[] third) {
+ if (first == null)
+ return concat(second, third);
+ if (second == null)
+ return concat(first, third);
+ if (third == null)
+ return concat(first, second);
+
+ int length1 = first.length;
+ int length2 = second.length;
+ int length3 = third.length;
+ char[] result = new char[length1 + length2 + length3];
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ System.arraycopy(third, 0, result, length1 + length2, length3);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
+ * It answers null if the two arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = null
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = { ' b' }
+ * separator = '/'
+ * => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @param separator the character to insert
+ * @return the concatenation of the two arrays inserting the separator character
+ * between the two arrays , or null if the two arrays are null.
+ */
+ public static final char[] concat(
+ char[] first,
+ char[] second,
+ char separator) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+
+ int length1 = first.length;
+ if (length1 == 0)
+ return second;
+ int length2 = second.length;
+ if (length2 == 0)
+ return first;
+
+ char[] result = new char[length1 + length2 + 1];
+ System.arraycopy(first, 0, result, 0, length1);
+ result[length1] = separator;
+ System.arraycopy(second, 0, result, length1 + 1, length2);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the three arrays inserting the sep1 character between the
+ * two arrays and sep2 between the last two.
+ * It answers null if the three arrays are null.
+ * If the first array is null, then it answers the concatenation of second and third inserting
+ * the sep2 character between them.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = null
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = { ' b' }
+ * separator = '/'
+ * => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @param separator the character to insert
+ * @return the concatenation of the two arrays inserting the separator character
+ * between the two arrays , or null if the two arrays are null.
+ */
+ public static final char[] concat(
+ char[] first,
+ char sep1,
+ char[] second,
+ char sep2,
+ char[] third) {
+ if (first == null)
+ return concat(second, third, sep2);
+ if (second == null)
+ return concat(first, third, sep1);
+ if (third == null)
+ return concat(first, second, sep1);
+
+ int length1 = first.length;
+ int length2 = second.length;
+ int length3 = third.length;
+ char[] result = new char[length1 + length2 + length3 + 2];
+ System.arraycopy(first, 0, result, 0, length1);
+ result[length1] = sep1;
+ System.arraycopy(second, 0, result, length1 + 1, length2);
+ result[length1 + length2 + 1] = sep2;
+ System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
+ return result;
+ }
+
+ /**
+ * Answers a new array with prepending the prefix character and appending the suffix
+ * character at the end of the array. If array is null, it answers a new array containing the
+ * prefix and the suffix characters.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * prefix = 'a'
+ * array = { 'b' }
+ * suffix = 'c'
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = 'a'
+ * array = null
+ * suffix = 'c'
+ * => result = { 'a', 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @param prefix the prefix character
+ * @param array the array that is concanated with the prefix and suffix characters
+ * @param suffix the suffix character
+ * @return the new array
+ */
+ public static final char[] concat(char prefix, char[] array, char suffix) {
+ if (array == null)
+ return new char[] { prefix, suffix };
+
+ int length = array.length;
+ char[] result = new char[length + 2];
+ result[0] = prefix;
+ System.arraycopy(array, 0, result, 1, length);
+ result[length + 1] = suffix;
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given separator between each
+ * part and appending the given name at the end.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * name = { 'c' }
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' , '.', 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * name = null
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre></li>
+ * <li><pre>
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @param name the given name
+ * @param array the given array
+ * @param separator the given separator
+ * @return the concatenation of the given array parts using the given separator between each
+ * part and appending the given name at the end
+ */
+ public static final char[] concatWith(
+ char[] name,
+ char[][] array,
+ char separator) {
+ int nameLength = name == null ? 0 : name.length;
+ if (nameLength == 0)
+ return concatWith(array, separator);
+
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return name;
+
+ int size = nameLength;
+ int index = length;
+ while (--index >= 0)
+ if (array[index].length > 0)
+ size += array[index].length + 1;
+ char[] result = new char[size];
+ index = size;
+ for (int i = length - 1; i >= 0; i--) {
+ int subLength = array[i].length;
+ if (subLength > 0) {
+ index -= subLength;
+ System.arraycopy(array[i], 0, result, index, subLength);
+ result[--index] = separator;
+ }
+ }
+ System.arraycopy(name, 0, result, 0, nameLength);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given separator between each
+ * part and appending the given name at the end.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * name = { 'c' }
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' , '.', 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * name = null
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre></li>
+ * <li><pre>
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param name the given name
+ * @param separator the given separator
+ * @return the concatenation of the given array parts using the given separator between each
+ * part and appending the given name at the end
+ */
+ public static final char[] concatWith(
+ char[][] array,
+ char[] name,
+ char separator) {
+ int nameLength = name == null ? 0 : name.length;
+ if (nameLength == 0)
+ return concatWith(array, separator);
+
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return name;
+
+ int size = nameLength;
+ int index = length;
+ while (--index >= 0)
+ if (array[index].length > 0)
+ size += array[index].length + 1;
+ char[] result = new char[size];
+ index = 0;
+ for (int i = 0; i < length; i++) {
+ int subLength = array[i].length;
+ if (subLength > 0) {
+ System.arraycopy(array[i], 0, result, index, subLength);
+ index += subLength;
+ result[index++] = separator;
+ }
+ }
+ System.arraycopy(name, 0, result, index, nameLength);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given separator between each part.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = null
+ * separator = '.'
+ * => result = { }
+ * </pre></li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param separator the given separator
+ * @return the concatenation of the given array parts using the given separator between each part
+ */
+ public static final char[] concatWith(char[][] array, char separator) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return CharOperation.NO_CHAR;
+
+ int size = length - 1;
+ int index = length;
+ while (--index >= 0) {
+ if (array[index].length == 0)
+ size--;
+ else
+ size += array[index].length;
+ }
+ if (size <= 0)
+ return CharOperation.NO_CHAR;
+ char[] result = new char[size];
+ index = length;
+ while (--index >= 0) {
+ length = array[index].length;
+ if (length > 0) {
+ System.arraycopy(
+ array[index],
+ 0,
+ result,
+ (size -= length),
+ length);
+ if (--size >= 0)
+ result[size] = separator;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Answers true if the array contains an occurrence of character, false otherwise.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * character = 'c'
+ * array = { { ' a' }, { ' b' } }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * character = 'a'
+ * array = { { ' a' }, { ' b' } }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param character the character to search
+ * @param array the array in which the search is done
+ * @exception NullPointerException if array is null.
+ *
+ * @return true if the array contains an occurrence of character, false otherwise.
+ */
+ public static final boolean contains(char character, char[][] array) {
+ for (int i = array.length; --i >= 0;) {
+ char[] subarray = array[i];
+ for (int j = subarray.length; --j >= 0;)
+ if (subarray[j] == character)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Answers true if the array contains an occurrence of character, false otherwise.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * character = 'c'
+ * array = { ' b' }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * character = 'a'
+ * array = { ' a' , ' b' }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param character the character to search
+ * @param array the array in which the search is done
+ * @exception NullPointerException if array is null.
+ *
+ * @return true if the array contains an occurrence of character, false otherwise.
+ */
+ public static final boolean contains(char character, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (array[i] == character)
+ return true;
+ return false;
+ }
+
+ /**
+ * Answers a deep copy of the toCopy array.
+ *
+ * @param toCopy the array to copy
+ * @return a deep copy of the toCopy array.
+ */
+ public static final char[][] deepCopy(char[][] toCopy) {
+ int toCopyLength = toCopy.length;
+ char[][] result = new char[toCopyLength][];
+ for (int i = 0; i < toCopyLength; i++) {
+ char[] toElement = toCopy[i];
+ int toElementLength = toElement.length;
+ char[] resultElement = new char[toElementLength];
+ System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
+ result[i] = resultElement;
+ }
+ return result;
+ }
+
+ /**
+ * Return true if array ends with the sequence of characters contained in toBeFound,
+ * otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a', 'b', 'c', 'd' }
+ * toBeFound = { 'b', 'c' }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b', 'c' }
+ * toBeFound = { 'b', 'c' }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array the array to check
+ * @param toBeFound the array to find
+ * @exception NullPointerException if array is null or toBeFound is null
+ * @return true if array ends with the sequence of characters contained in toBeFound,
+ * otherwise false.
+ */
+ public static final boolean endsWith(char[] array, char[] toBeFound) {
+ int i = toBeFound.length;
+ int j = array.length - i;
+
+ if (j < 0)
+ return false;
+ while (--i >= 0)
+ if (toBeFound[i] != array[i + j])
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the two arrays are identical character by character, otherwise false.
+ * The equality is case sensitive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { } }
+ * second = null
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'a' } }
+ * second = { { 'a' } }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ * @param first the first array
+ * @param second the second array
+ * @return true if the two arrays are identical character by character, otherwise false
+ */
+ public static final boolean equals(char[][] first, char[][] second) {
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+
+ for (int i = first.length; --i >= 0;)
+ if (!equals(first[i], second[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * If isCaseSensite is true, answers true if the two arrays are identical character
+ * by character, otherwise false.
+ * If it is false, answers true if the two arrays are identical character by
+ * character without checking the case, otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { } }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array
+ * @param second the second array
+ * @param isCaseSensitive check whether or not the equality should be case sensitive
+ * @return true if the two arrays are identical character by character according to the value
+ * of isCaseSensitive, otherwise false
+ */
+ public static final boolean equals(
+ char[][] first,
+ char[][] second,
+ boolean isCaseSensitive) {
+
+ if (isCaseSensitive) {
+ return equals(first, second);
+ }
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+
+ for (int i = first.length; --i >= 0;)
+ if (!equals(first[i], second[i], false))
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the two arrays are identical character by character, otherwise false.
+ * The equality is case sensitive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { }
+ * second = null
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'a' }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'A' }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ * @param first the first array
+ * @param second the second array
+ * @return true if the two arrays are identical character by character, otherwise false
+ */
+ public static final boolean equals(char[] first, char[] second) {
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+
+ for (int i = first.length; --i >= 0;)
+ if (first[i] != second[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * If isCaseSensite is true, answers true if the two arrays are identical character
+ * by character, otherwise false.
+ * If it is false, answers true if the two arrays are identical character by
+ * character without checking the case, otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array
+ * @param second the second array
+ * @param isCaseSensitive check whether or not the equality should be case sensitive
+ * @return true if the two arrays are identical character by character according to the value
+ * of isCaseSensitive, otherwise false
+ */
+ public static final boolean equals(
+ char[] first,
+ char[] second,
+ boolean isCaseSensitive) {
+
+ if (isCaseSensitive) {
+ return equals(first, second);
+ }
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+
+ for (int i = first.length; --i >= 0;)
+ if (Character.toLowerCase(first[i])
+ != Character.toLowerCase(second[i]))
+ return false;
+ return true;
+ }
+ /**
+ * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
+ *
+ * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * startIndex = 1
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'C' , 'd' }
+ * startIndex = 1
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'C' , 'd' }
+ * startIndex = 0
+ * isCaseSensitive = false
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b'}
+ * startIndex = 0
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param fragment the fragment to check
+ * @param second the array to check
+ * @param startIndex the starting index
+ * @param isCaseSensitive check whether or not the equality should be case sensitive
+ * @return true if the name contains the fragment at the starting index startIndex according to the
+ * value of isCaseSensitive, otherwise false.
+ * @exception NullPointerException if fragment or name is null.
+ */
+ public static final boolean fragmentEquals(
+ char[] fragment,
+ char[] name,
+ int startIndex,
+ boolean isCaseSensitive) {
+
+ int max = fragment.length;
+ if (name.length < max + startIndex)
+ return false;
+ if (isCaseSensitive) {
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (fragment[i] != name[i + startIndex])
+ return false;
+ return true;
+ }
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (Character.toLowerCase(fragment[i])
+ != Character.toLowerCase(name[i + startIndex]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers a hashcode for the array
+ *
+ * @param array the array for which a hashcode is required
+ * @return the hashcode
+ * @exception NullPointerException if array is null
+ */
+ public static final int hashCode(char[] array) {
+ int hash = 0;
+ int offset = 0;
+ int length = array.length;
+ if (length < 16) {
+ for (int i = length; i > 0; i--)
+ hash = (hash * 37) + array[offset++];
+ } else {
+ // only sample some characters
+ int skip = length / 8;
+ for (int i = length; i > 0; i -= skip, offset += skip)
+ hash = (hash * 39) + array[offset];
+ }
+ return hash & 0x7FFFFFFF;
+ }
+ /**
+ * Answers true if c is a whitespace according to the JLS (\u000a, \u000c, \u000d, \u0009), otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * c = ' '
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * c = '\u3000'
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param c the character to check
+ * @return true if c is a whitespace according to the JLS, otherwise false.
+ */
+ public static boolean isWhitespace(char c) {
+ switch (c) {
+ case 10 : /* \ u000a: LINE FEED */
+ case 12 : /* \ u000c: FORM FEED */
+ case 13 : /* \ u000d: CARRIAGE RETURN */
+ case 32 : /* \ u0020: SPACE */
+ case 9 : /* \ u0009: HORIZONTAL TABULATION */
+ return true;
+ default :
+ return false;
+ }
+ }
+
+ /**
+ * Answers the first index in the array for which the corresponding character is
+ * equal to toBeFound. Answers -1 if no occurrence of this character is found.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the character to search
+ * @param array the array to be searched
+ * @return the first index in the array for which the corresponding character is
+ * equal to toBeFound, -1 otherwise
+ * @exception NullPointerException if array is null
+ */
+ public static final int indexOf(char toBeFound, char[] array) {
+ for (int i = 0; i < array.length; i++)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the first index in the array for which the corresponding character is
+ * equal to toBeFound starting the search at index start.
+ * Answers -1 if no occurrence of this character is found.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 1
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the character to search
+ * @param array the array to be searched
+ * @param start the starting index
+ * @return the first index in the array for which the corresponding character is
+ * equal to toBeFound, -1 otherwise
+ * @exception NullPointerException if array is null
+ * @exception ArrayIndexOutOfBoundsException if start is lower than 0
+ */
+ public static final int indexOf(char toBeFound, char[] array, int start) {
+ for (int i = start; i < array.length; i++)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character is
+ * equal to toBeFound starting from the end of the array.
+ * Answers -1 if no occurrence of this character is found.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
+ * result => 4
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the character to search
+ * @param array the array to be searched
+ * @return the last index in the array for which the corresponding character is
+ * equal to toBeFound starting from the end of the array, -1 otherwise
+ * @exception NullPointerException if array is null
+ */
+ public static final int lastIndexOf(char toBeFound, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character is
+ * equal to toBeFound stopping at the index startIndex.
+ * Answers -1 if no occurrence of this character is found.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd', 'e' }
+ * startIndex = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 0
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the character to search
+ * @param array the array to be searched
+ * @param startIndex the stopping index
+ * @return the last index in the array for which the corresponding character is
+ * equal to toBeFound stopping at the index startIndex, -1 otherwise
+ * @exception NullPointerException if array is null
+ * @exception ArrayIndexOutOfBoundsException if startIndex is lower than 0
+ */
+ public static final int lastIndexOf(
+ char toBeFound,
+ char[] array,
+ int startIndex) {
+ for (int i = array.length; --i >= startIndex;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character is
+ * equal to toBeFound starting from endIndex to startIndex.
+ * Answers -1 if no occurrence of this character is found.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 2
+ * endIndex = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd', 'e' }
+ * startIndex = 3
+ * endIndex = 4
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 0
+ * endIndex = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the character to search
+ * @param array the array to be searched
+ * @param startIndex the stopping index
+ * @param endIndex the starting index
+ * @return the last index in the array for which the corresponding character is
+ * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
+ * @exception NullPointerException if array is null
+ * @exception ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
+ */
+ public static final int lastIndexOf(
+ char toBeFound,
+ char[] array,
+ int startIndex,
+ int endIndex) {
+ for (int i = endIndex; --i >= startIndex;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last portion of a name given a separator.
+ * <br>
+ * <br>
+ * For example,
+ * <pre>
+ * lastSegment("java.lang.Object".toCharArray(),'.') --> Object
+ * </pre>
+ *
+ * @param array the array
+ * @param separator the given separator
+ * @return the last portion of a name given a separator
+ * @exception NullPointerException if array is null
+ */
+ final static public char[] lastSegment(char[] array, char separator) {
+ int pos = lastIndexOf(separator, array);
+ if (pos < 0)
+ return array;
+ return subarray(array, pos + 1, array.length);
+ }
+
+ /**
+ * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
+ * accepts wild-cards '*' and '?'.
+ *
+ * When not case sensitive, the pattern is assumed to already be lowercased, the
+ * name will be lowercased character per character as comparing.
+ * If name is null, the answer is false.
+ * If pattern is null, the answer is true if name is not null.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { '?', 'b', '?' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { 'b', '*' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
+ * @return true if the pattern matches the given name, false otherwise
+ */
+ public static final boolean match(
+ char[] pattern,
+ char[] name,
+ boolean isCaseSensitive) {
+
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+
+ return match(
+ pattern,
+ 0,
+ pattern.length,
+ name,
+ 0,
+ name.length,
+ isCaseSensitive);
+ }
+
+ /**
+ * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
+ * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
+ * end positions are non-inclusive.
+ * The subpattern is defined by the patternStart and pattternEnd positions.
+ * When not case sensitive, the pattern is assumed to already be lowercased, the
+ * name will be lowercased character per character as comparing.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * patternStart = 1
+ * patternEnd = 3
+ * name = { 'a', 'b', 'c' , 'd' }
+ * nameStart = 1
+ * nameEnd = 4
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * patternStart = 1
+ * patternEnd = 2
+ * name = { 'a', 'b', 'c' , 'd' }
+ * nameStart = 1
+ * nameEnd = 2
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param pattern the given pattern
+ * @param patternStart the given pattern start
+ * @param patternEnd the given pattern end
+ * @param name the given name
+ * @param nameStart the given name start
+ * @param nameEnd the given name end
+ * @param isCaseSensitive flag to know if the matching should be case sensitive
+ * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
+ */
+ public static final boolean match(
+ char[] pattern,
+ int patternStart,
+ int patternEnd,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ boolean isCaseSensitive) {
+
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ int iPattern = patternStart;
+ int iName = nameStart;
+
+ if (patternEnd < 0)
+ patternEnd = pattern.length;
+ if (nameEnd < 0)
+ nameEnd = name.length;
+
+ /* check first segment */
+ char patternChar = 0;
+ while ((iPattern < patternEnd)
+ && (patternChar = pattern[iPattern]) != '*') {
+ if (iName == nameEnd)
+ return false;
+ if (patternChar
+ != (isCaseSensitive
+ ? name[iName]
+ : Character.toLowerCase(name[iName]))
+ && patternChar != '?') {
+ return false;
+ }
+ iName++;
+ iPattern++;
+ }
+ /* check sequence of star+segment */
+ int segmentStart;
+ if (patternChar == '*') {
+ segmentStart = ++iPattern; // skip star
+ } else {
+ segmentStart = 0; // force iName check
+ }
+ int prefixStart = iName;
+ checkSegment : while (iName < nameEnd) {
+ if (iPattern == patternEnd) {
+ iPattern = segmentStart; // mismatch - restart current segment
+ iName = ++prefixStart;
+ continue checkSegment;
+ }
+ /* segment is ending */
+ if ((patternChar = pattern[iPattern]) == '*') {
+ segmentStart = ++iPattern; // skip start
+ if (segmentStart == patternEnd) {
+ return true;
+ }
+ prefixStart = iName;
+ continue checkSegment;
+ }
+ /* check current name character */
+ if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
+ != patternChar
+ && patternChar != '?') {
+ iPattern = segmentStart; // mismatch - restart current segment
+ iName = ++prefixStart;
+ continue checkSegment;
+ }
+ iName++;
+ iPattern++;
+ }
+
+ return (segmentStart == patternEnd)
+ || (iName == nameEnd && iPattern == patternEnd)
+ || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
+ }
+
+ /**
+ * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
+ *
+ * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
+ * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
+ * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
+ * any folder combination.
+ * Special rules:
+ * - foo\ is equivalent to foo\**
+ * - *.php is equivalent to **\*.php
+ * When not case sensitive, the pattern is assumed to already be lowercased, the
+ * name will be lowercased character per character as comparing.
+ *
+ * @param pattern the given pattern
+ * @param filepath the given path
+ * @param isCaseSensitive to find out whether or not the matching should be case sensitive
+ * @param pathSeparator the given path separator
+ * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
+ */
+ public static final boolean pathMatch(
+ char[] pattern,
+ char[] filepath,
+ boolean isCaseSensitive,
+ char pathSeparator) {
+
+ if (filepath == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+
+ // special case: pattern foo is equivalent to **\foo (not absolute)
+ boolean freeLeadingDoubleStar;
+
+ // offsets inside pattern
+ int pSegmentStart, pLength = pattern.length;
+
+ if (freeLeadingDoubleStar = pattern[0] != pathSeparator){
+ pSegmentStart = 0;
+ } else {
+ pSegmentStart = 1;
+ }
+ int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
+ if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+ // special case: pattern foo\ is equivalent to foo\**
+ boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
+
+ // offsets inside filepath
+ int fSegmentStart, fLength = filepath.length;
+ if (filepath[0] != pathSeparator){
+ fSegmentStart = 0;
+ } else {
+ fSegmentStart = 1;
+ }
+ if (fSegmentStart != pSegmentStart) {
+ return false; // both must start with a separator or none.
+ }
+ int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
+ if (fSegmentEnd < 0) fSegmentEnd = fLength;
+
+ // first segments
+ while (pSegmentStart < pLength
+ && !freeLeadingDoubleStar
+ && !(pSegmentEnd == pLength && freeTrailingDoubleStar
+ || (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*'
+ && pattern[pSegmentStart + 1] == '*'))) {
+
+ if (fSegmentStart >= fLength)
+ return false;
+ if (!CharOperation
+ .match(
+ pattern,
+ pSegmentStart,
+ pSegmentEnd,
+ filepath,
+ fSegmentStart,
+ fSegmentEnd,
+ isCaseSensitive)) {
+ return false;
+ }
+
+ // jump to next segment
+ pSegmentEnd =
+ CharOperation.indexOf(
+ pathSeparator,
+ pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+
+ fSegmentEnd =
+ CharOperation.indexOf(
+ pathSeparator,
+ filepath,
+ fSegmentStart = fSegmentEnd + 1);
+ // skip separator
+ if (fSegmentEnd < 0) fSegmentEnd = fLength;
+ }
+
+ /* check sequence of doubleStar+segment */
+ int pSegmentRestart;
+ if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
+ || (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*'
+ && pattern[pSegmentStart + 1] == '*')) {
+ pSegmentEnd =
+ CharOperation.indexOf(
+ pathSeparator,
+ pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0) pSegmentEnd = pLength;
+ pSegmentRestart = pSegmentStart;
+ } else {
+ pSegmentRestart = 0; // force fSegmentStart check
+ }
+ int fSegmentRestart = fSegmentStart;
+ checkSegment : while (fSegmentStart < fLength) {
+
+ if (pSegmentStart >= pLength) {
+ if (freeTrailingDoubleStar) return true;
+ // mismatch - restart current path segment
+ pSegmentEnd =
+ CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+ if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+ fSegmentRestart =
+ CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+ // skip separator
+ if (fSegmentRestart < 0) {
+ fSegmentRestart = fLength;
+ } else {
+ fSegmentRestart++;
+ }
+ fSegmentEnd =
+ CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+ if (fSegmentEnd < 0) fSegmentEnd = fLength;
+ continue checkSegment;
+ }
+
+ /* path segment is ending */
+ if (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*'
+ && pattern[pSegmentStart + 1] == '*') {
+ pSegmentEnd =
+ CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0) pSegmentEnd = pLength;
+ pSegmentRestart = pSegmentStart;
+ fSegmentRestart = fSegmentStart;
+ if (pSegmentStart >= pLength) return true;
+ continue checkSegment;
+ }
+ /* chech current path segment */
+ if (!CharOperation.match(
+ pattern,
+ pSegmentStart,
+ pSegmentEnd,
+ filepath,
+ fSegmentStart,
+ fSegmentEnd,
+ isCaseSensitive)) {
+ // mismatch - restart current path segment
+ pSegmentEnd =
+ CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+ if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+ fSegmentRestart =
+ CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+ // skip separator
+ if (fSegmentRestart < 0) {
+ fSegmentRestart = fLength;
+ } else {
+ fSegmentRestart++;
+ }
+ fSegmentEnd =
+ CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+ if (fSegmentEnd < 0) fSegmentEnd = fLength;
+ continue checkSegment;
+ }
+ // jump to next segment
+ pSegmentEnd =
+ CharOperation.indexOf(
+ pathSeparator,
+ pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+
+ fSegmentEnd =
+ CharOperation.indexOf(
+ pathSeparator,
+ filepath,
+ fSegmentStart = fSegmentEnd + 1);
+ // skip separator
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ }
+
+ return (pSegmentRestart >= pSegmentEnd)
+ || (fSegmentStart >= fLength && pSegmentStart >= pLength)
+ || (pSegmentStart == pLength - 2
+ && pattern[pSegmentStart] == '*'
+ && pattern[pSegmentStart + 1] == '*')
+ || (pSegmentStart == pLength && freeTrailingDoubleStar);
+ }
+
+ /**
+ * Answers the number of occurrences of the given character in the given array, 0 if any.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => 3
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => 0
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the given character
+ * @param array the given array
+ * @return the number of occurrences of the given character in the given array, 0 if any
+ * @exception NullPointerException if array is null
+ */
+ public static final int occurencesOf(char toBeFound, char[] array) {
+ int count = 0;
+ for (int i = 0; i < array.length; i++)
+ if (toBeFound == array[i])
+ count++;
+ return count;
+ }
+
+ /**
+ * Answers the number of occurrences of the given character in the given array starting
+ * at the given index, 0 if any.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 0
+ * result => 0
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param toBeFound the given character
+ * @param array the given array
+ * @return the number of occurrences of the given character in the given array, 0 if any
+ * @exception NullPointerException if array is null
+ * @exception ArrayIndexOutOfBoundsException if start is lower than 0
+ */
+ public static final int occurencesOf(
+ char toBeFound,
+ char[] array,
+ int start) {
+ int count = 0;
+ for (int i = start; i < array.length; i++)
+ if (toBeFound == array[i])
+ count++;
+ return count;
+ }
+
+ /**
+ * Answers true if the given name starts with the given prefix, false otherwise.
+ * The comparison is case sensitive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * prefix = { 'a' , 'b' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = { 'a' , 'c' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param prefix the given prefix
+ * @param name the given name
+ * @return true if the given name starts with the given prefix, false otherwise
+ * @exception NullPointerException if the given name is null or if the given prefix is null
+ */
+ public static final boolean prefixEquals(char[] prefix, char[] name) {
+
+ int max = prefix.length;
+ if (name.length < max)
+ return false;
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (prefix[i] != name[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the given name starts with the given prefix, false otherwise.
+ * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * prefix = { 'a' , 'B' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = { 'a' , 'B' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param prefix the given prefix
+ * @param name the given name
+ * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
+ * @return true if the given name starts with the given prefix, false otherwise
+ * @exception NullPointerException if the given name is null or if the given prefix is null
+ */
+ public static final boolean prefixEquals(
+ char[] prefix,
+ char[] name,
+ boolean isCaseSensitive) {
+
+ int max = prefix.length;
+ if (name.length < max)
+ return false;
+ if (isCaseSensitive) {
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (prefix[i] != name[i])
+ return false;
+ return true;
+ }
+
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (Character.toLowerCase(prefix[i])
+ != Character.toLowerCase(name[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Replace all occurrence of the character to be replaced with the remplacement character in the
+ * given array.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'b'
+ * replacementChar = 'a'
+ * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'c'
+ * replacementChar = 'a'
+ * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param toBeReplaced the character to be replaced
+ * @param replacementChar the replacement character
+ * @exception NullPointerException if the given array is null
+ */
+ public static final void replace(
+ char[] array,
+ char toBeReplaced,
+ char replacementChar) {
+ if (toBeReplaced != replacementChar) {
+ for (int i = 0, max = array.length; i < max; i++) {
+ if (array[i] == toBeReplaced)
+ array[i] = replacementChar;
+ }
+ }
+ }
+
+ /**
+ * Answers a new array of characters with substitutions. No side-effect is operated on the original
+ * array, in case no substitution happened, then the result is the same as the
+ * original one.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = { 'b' }
+ * replacementChar = { 'a', 'a' }
+ * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = { 'c' }
+ * replacementChar = { 'a' }
+ * result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param the given array
+ * @param toBeReplaced characters to be replaced
+ * @param the replacement characters
+ * @return a new array of characters with substitutions or the given array if none
+ * @exception NullPointerException if the given array is null
+ */
+ public static final char[] replace(
+ char[] array,
+ char[] toBeReplaced,
+ char[] replacementChars) {
+
+ int max = array.length;
+ int replacedLength = toBeReplaced.length;
+ int replacementLength = replacementChars.length;
+
+ int[] starts = new int[5];
+ int occurrenceCount = 0;
+
+ if (!equals(toBeReplaced, replacementChars)) {
+
+ next : for (int i = 0; i < max; i++) {
+ int j = 0;
+ while (j < replacedLength) {
+ if (i + j == max)
+ continue next;
+ if (array[i + j] != toBeReplaced[j++])
+ continue next;
+ }
+ if (occurrenceCount == starts.length) {
+ System.arraycopy(
+ starts,
+ 0,
+ starts = new int[occurrenceCount * 2],
+ 0,
+ occurrenceCount);
+ }
+ starts[occurrenceCount++] = i;
+ }
+ }
+ if (occurrenceCount == 0)
+ return array;
+ char[] result =
+ new char[max
+ + occurrenceCount * (replacementLength - replacedLength)];
+ int inStart = 0, outStart = 0;
+ for (int i = 0; i < occurrenceCount; i++) {
+ int offset = starts[i] - inStart;
+ System.arraycopy(array, inStart, result, outStart, offset);
+ inStart += offset;
+ outStart += offset;
+ System.arraycopy(
+ replacementChars,
+ 0,
+ result,
+ outStart,
+ replacementLength);
+ inStart += replacedLength;
+ outStart += replacementLength;
+ }
+ System.arraycopy(array, inStart, result, outStart, max - inStart);
+ return result;
+ }
+
+ /**
+ * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
+ * whitespaces equals to ' '.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param divider the given divider
+ * @param array the given array
+ * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
+ * whitespaces equals to ' '
+ */
+ public static final char[][] splitAndTrimOn(char divider, char[] array) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return NO_CHAR_CHAR;
+
+ int wordCount = 1;
+ for (int i = 0; i < length; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (array[i] == divider) {
+ int start = last, end = i - 1;
+ while (start < i && array[start] == ' ')
+ start++;
+ while (end > start && array[end] == ' ')
+ end--;
+ split[currentWord] = new char[end - start + 1];
+ System.arraycopy(
+ array,
+ start,
+ split[currentWord++],
+ 0,
+ end - start + 1);
+ last = i + 1;
+ }
+ }
+ int start = last, end = length - 1;
+ while (start < length && array[start] == ' ')
+ start++;
+ while (end > start && array[end] == ' ')
+ end--;
+ split[currentWord] = new char[end - start + 1];
+ System.arraycopy(
+ array,
+ start,
+ split[currentWord++],
+ 0,
+ end - start + 1);
+ return split;
+ }
+
+ /**
+ * Return a new array which is the split of the given array using the given divider.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+ * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param divider the given divider
+ * @param array the given array
+ * @return a new array which is the split of the given array using the given divider
+ */
+ public static final char[][] splitOn(char divider, char[] array) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return NO_CHAR_CHAR;
+
+ int wordCount = 1;
+ for (int i = 0; i < length; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (array[i] == divider) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(
+ array,
+ last,
+ split[currentWord++],
+ 0,
+ i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[length - last];
+ System.arraycopy(array, last, split[currentWord], 0, length - last);
+ return split;
+ }
+
+ /**
+ * Return a new array which is the split of the given array using the given divider. The given end
+ * is exclusive and the given start is inclusive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 2
+ * end = 5
+ * result => { { }, { }, { 'a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param divider the given divider
+ * @param array the given array
+ * @param start the given starting index
+ * @param end the given ending index
+ * @return a new array which is the split of the given array using the given divider
+ * @exception ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
+ */
+ public static final char[][] splitOn(
+ char divider,
+ char[] array,
+ int start,
+ int end) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0 || start > end)
+ return NO_CHAR_CHAR;
+
+ int wordCount = 1;
+ for (int i = start; i < end; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = start, currentWord = 0;
+ for (int i = start; i < end; i++) {
+ if (array[i] == divider) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(
+ array,
+ last,
+ split[currentWord++],
+ 0,
+ i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[end - last];
+ System.arraycopy(array, last, split[currentWord], 0, end - last);
+ return split;
+ }
+
+ /**
+ * Answers true if the given array starts with the given characters, false otherwise.
+ * The comparison is case sensitive.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = { 'a' , 'b' }
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = { 'a' , 'c' }
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param toBeFound the given character to search
+ * @return true if the given array starts with the given characters, false otherwise
+ * @exception NullPointerException if the given array is null or if the given characters array to be found is null
+ */
+ public static final boolean startsWith(char[] array, char[] toBeFound) {
+ int i = toBeFound.length;
+ if (i > array.length)
+ return false;
+ while (--i >= 0)
+ if (toBeFound[i] != array[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers a new array which is a copy of the given array starting at the given start and
+ * ending at the given end. The given start is inclusive and the given end is exclusive.
+ * Answers null if start is greater than end, if start is lower than 0 or if end is greater
+ * than the length of the given array. If end equals -1, it is converted to the array length.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * start = 0
+ * end = 1
+ * result => { { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * start = 0
+ * end = -1
+ * result => { { 'a' }, { 'b' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param start the given starting index
+ * @param end the given ending index
+ * @return a new array which is a copy of the given array starting at the given start and
+ * ending at the given end
+ * @exception NullPointerException if the given array is null
+ */
+ public static final char[][] subarray(char[][] array, int start, int end) {
+ if (end == -1)
+ end = array.length;
+ if (start > end)
+ return null;
+ if (start < 0)
+ return null;
+ if (end > array.length)
+ return null;
+
+ char[][] result = new char[end - start][];
+ System.arraycopy(array, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Answers a new array which is a copy of the given array starting at the given start and
+ * ending at the given end. The given start is inclusive and the given end is exclusive.
+ * Answers null if start is greater than end, if start is lower than 0 or if end is greater
+ * than the length of the given array. If end equals -1, it is converted to the array length.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a' , 'b' }
+ * start = 0
+ * end = 1
+ * result => { 'a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b' }
+ * start = 0
+ * end = -1
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array the given array
+ * @param start the given starting index
+ * @param end the given ending index
+ * @return a new array which is a copy of the given array starting at the given start and
+ * ending at the given end
+ * @exception NullPointerException if the given array is null
+ */
+ public static final char[] subarray(char[] array, int start, int end) {
+ if (end == -1)
+ end = array.length;
+ if (start > end)
+ return null;
+ if (start < 0)
+ return null;
+ if (end > array.length)
+ return null;
+
+ char[] result = new char[end - start];
+ System.arraycopy(array, start, result, 0, end - start);
+ return result;
+ }
+ /**
+ * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
+ * <br>
+ * NOTE: if no conversion was necessary, then answers back the argument one.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * chars = { 'a' , 'b' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'A', 'b' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param chars the chars to convert
+ * @return the result of a char[] conversion to lowercase
+ */
+ final static public char[] toLowerCase(char[] chars) {
+ if (chars == null)
+ return null;
+ int length = chars.length;
+ char[] lowerChars = null;
+ for (int i = 0; i < length; i++) {
+ char c = chars[i];
+ char lc = Character.toLowerCase(c);
+ if ((c != lc) || (lowerChars != null)) {
+ if (lowerChars == null) {
+ System.arraycopy(
+ chars,
+ 0,
+ lowerChars = new char[length],
+ 0,
+ i);
+ }
+ lowerChars[i] = lc;
+ }
+ }
+ return lowerChars == null ? chars : lowerChars;
+ }
+
+ /**
+ * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
+ * space characters to remove.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * chars = { ' ', 'a' , 'b', ' ', ' ' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'A', 'b' }
+ * result => { 'A' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param chars the given array
+ * @return a new array removing leading and trailing spaces (' ')
+ */
+ final static public char[] trim(char[] chars) {
+
+ if (chars == null)
+ return null;
+
+ int start = 0, length = chars.length, end = length - 1;
+ while (start < length && chars[start] == ' ') {
+ start++;
+ }
+ while (end > start && chars[end] == ' ') {
+ end--;
+ }
+ if (start != 0 || end != length - 1) {
+ return subarray(chars, start, end + 1);
+ }
+ return chars;
+ }
+
+ /**
+ * Answers a string which is the concatenation of the given array using the '.' as a separator.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * result => "a.b"
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { { ' ', 'a' } , { 'b' } }
+ * result => " a.b"
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param chars the given array
+ * @return a string which is the concatenation of the given array using the '.' as a separator
+ */
+ final static public String toString(char[][] array) {
+ char[] result = concatWith(array, '.');
+ return new String(result);
+ }
+}
public final static int TokenNameWHITESPACE = 900,
TokenNameCOMMENT_LINE = 901,
TokenNameCOMMENT_BLOCK = 902,
- TokenNameCOMMENT_PHPDOC = 903;
+ TokenNameCOMMENT_PHPDOC = 903,
+ TokenNameHTML = 904;
final static int TokenNameEOF = 0;
final static int TokenNameERROR = 1;
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+/**
+ * Generic option description, which can be modified independently from the
+ * component it belongs to.
+ *
+ * @deprecated backport 1.0 internal functionality
+ */
+
+import java.util.*;
+
+public class ConfigurableOption {
+ private String componentName;
+ private String optionName;
+ private int id;
+
+ private String category;
+ private String name;
+ private String description;
+ private int currentValueIndex;
+ private int defaultValueIndex;
+ private String[] possibleValues;
+
+ // special value for <possibleValues> indicating that
+ // the <currentValueIndex> is the actual value
+ public final static String[] NoDiscreteValue = {};
+/**
+ * INTERNAL USE ONLY
+ *
+ * Initialize an instance of this class according to a specific locale
+ *
+ * @param loc java.util.Locale
+ */
+public ConfigurableOption(
+ String componentName,
+ String optionName,
+ Locale loc,
+ int currentValueIndex) {
+
+ this.componentName = componentName;
+ this.optionName = optionName;
+ this.currentValueIndex = currentValueIndex;
+
+ ResourceBundle resource = null;
+ try {
+ String location = componentName.substring(0, componentName.lastIndexOf('.'));
+ resource = ResourceBundle.getBundle(location + ".Options", loc); //$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ description = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ possibleValues = new String[0];
+ id = -1;
+ }
+ if (resource == null) return;
+ try {
+ id = Integer.parseInt(resource.getString(optionName + ".number")); //$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ id = -1;
+ } catch (NumberFormatException e) {
+ id = -1;
+ }
+ try {
+ category = resource.getString(optionName + ".category"); //$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ try {
+ name = resource.getString(optionName + ".name"); //$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ try {
+ StringTokenizer tokenizer = new StringTokenizer(resource.getString(optionName + ".possibleValues"), "|"); //$NON-NLS-1$ //$NON-NLS-2$
+ int numberOfValues = Integer.parseInt(tokenizer.nextToken());
+ if(numberOfValues == -1){
+ possibleValues = NoDiscreteValue;
+ } else {
+ possibleValues = new String[numberOfValues];
+ int index = 0;
+ while (tokenizer.hasMoreTokens()) {
+ possibleValues[index] = tokenizer.nextToken();
+ index++;
+ }
+ }
+ } catch (MissingResourceException e) {
+ possibleValues = new String[0];
+ } catch (NoSuchElementException e) {
+ possibleValues = new String[0];
+ } catch (NumberFormatException e) {
+ possibleValues = new String[0];
+ }
+ try {
+ description = resource.getString(optionName + ".description"); //$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ description = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
+/**
+ * Return a String that represents the localized category of the receiver.
+ * @return java.lang.String
+ */
+public String getCategory() {
+ return category;
+}
+/**
+ * Return a String that identifies the component owner (typically the qualified
+ * type name of the class which it corresponds to).
+ *
+ * e.g. "org.phpeclipse.phpdt.internal.compiler.api.Compiler"
+ *
+ * @return java.lang.String
+ */
+public String getComponentName() {
+ return componentName;
+}
+/**
+ * Answer the index (in possibleValues array) of the current setting for this
+ * particular option.
+ *
+ * In case the set of possibleValues is NoDiscreteValue, then this index is the
+ * actual value (e.g. max line lenght set to 80).
+ *
+ * @return int
+ */
+public int getCurrentValueIndex() {
+ return currentValueIndex;
+}
+/**
+ * Answer the index (in possibleValues array) of the default setting for this
+ * particular option.
+ *
+ * In case the set of possibleValues is NoDiscreteValue, then this index is the
+ * actual value (e.g. max line lenght set to 80).
+ *
+ * @return int
+ */
+public int getDefaultValueIndex() {
+ return defaultValueIndex;
+}
+/**
+ * Return an String that represents the localized description of the receiver.
+ *
+ * @return java.lang.String
+ */
+public String getDescription() {
+ return description;
+}
+/**
+ * Internal ID which allows the configurable component to identify this particular option.
+ *
+ * @return int
+ */
+public int getID() {
+ return id;
+}
+/**
+ * Return a String that represents the localized name of the receiver.
+ * @return java.lang.String
+ */
+public String getName() {
+ return name;
+}
+/**
+ * Return an array of String that represents the localized possible values of the receiver.
+ * @return java.lang.String[]
+ */
+public String[] getPossibleValues() {
+ return possibleValues;
+}
+/**
+ * Change the index (in possibleValues array) of the current setting for this
+ * particular option.
+ *
+ * In case the set of possibleValues is NoDiscreteValue, then this index is the
+ * actual value (e.g. max line lenght set to 80).
+ *
+ * @return int
+ */
+public void setValueIndex(int newIndex) {
+ currentValueIndex = newIndex;
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Configurable option for "); //$NON-NLS-1$
+ buffer.append(this.componentName).append("\n"); //$NON-NLS-1$
+ buffer.append("- category: ").append(this.category).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append("- name: ").append(this.name).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ /* display current value */
+ buffer.append("- current value: "); //$NON-NLS-1$
+ if (possibleValues == NoDiscreteValue){
+ buffer.append(this.currentValueIndex);
+ } else {
+ buffer.append(this.possibleValues[this.currentValueIndex]);
+ }
+ buffer.append("\n"); //$NON-NLS-1$
+
+ /* display possible values */
+ if (possibleValues != NoDiscreteValue){
+ buffer.append("- possible values: ["); //$NON-NLS-1$
+ for (int i = 0, max = possibleValues.length; i < max; i++) {
+ if (i != 0)
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(possibleValues[i]);
+ }
+ buffer.append("]\n"); //$NON-NLS-1$
+ buffer.append("- curr. val. index: ").append(currentValueIndex).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ buffer.append("- description: ").append(description).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ return buffer.toString();
+}
+ /**
+ * Gets the optionName.
+ * @return Returns a String
+ */
+ public String getOptionName() {
+ return optionName;
+ }
+}
}
public int getNextToken() throws InvalidInputException {
+
try {
+ int htmlPosition = currentPosition;
while (!phpMode) {
- startPosition = currentPosition;
currentCharacter = source[currentPosition++];
if (currentCharacter == '<') {
if (getNextChar('?')) {
// <?
startPosition = currentPosition;
phpMode = true;
+ if (tokenizeWhiteSpace) {
+ // && (whiteStart != currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ startPosition = htmlPosition;
+ return TokenNameHTML;
+ }
} else {
boolean phpStart =
(currentCharacter == 'P') || (currentCharacter == 'p');
// <?PHP <?php
startPosition = currentPosition;
phpMode = true;
+
+ if (tokenizeWhiteSpace) {
+ // && (whiteStart != currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ startPosition = htmlPosition;
+ return TokenNameHTML;
+ }
}
}
}
--- /dev/null
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.corext.codemanipulation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+//import org.phpeclipse.phpdt.core.Flags;
+//import org.phpeclipse.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.ICodeFormatter;
+//import org.phpeclipse.phpdt.core.ICompilationUnit;
+//import org.phpeclipse.phpdt.core.IJavaElement;
+//import org.phpeclipse.phpdt.core.IJavaProject;
+//import org.phpeclipse.phpdt.core.IMethod;
+//import org.phpeclipse.phpdt.core.IParent;
+//import org.phpeclipse.phpdt.core.ISourceReference;
+//import org.phpeclipse.phpdt.core.IType;
+//import org.phpeclipse.phpdt.core.ITypeHierarchy;
+import net.sourceforge.phpeclipse.PHPCore;
+//import org.phpeclipse.phpdt.core.JavaModelException;
+//import org.phpeclipse.phpdt.core.Signature;
+import net.sourceforge.phpdt.core.ToolFactory;
+
+//import net.sourceforge.phpdt.internal.corext.util.CodeFormatterUtil;
+//import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+
+public class StubUtility {
+
+
+// public static class GenStubSettings extends CodeGenerationSettings {
+//
+// public boolean callSuper;
+// public boolean methodOverwrites;
+// public boolean noBody;
+//
+// public GenStubSettings(CodeGenerationSettings settings) {
+// settings.setSettings(this);
+// }
+//
+// public GenStubSettings() {
+// }
+//
+// }
+//
+//
+// /**
+// * Generates a stub. Given a template method, a stub with the same signature
+// * will be constructed so it can be added to a type.
+// * @param destTypeName The name of the type to which the method will be added to (Used for the constructor)
+// * @param method A method template (method belongs to different type than the parent)
+// * @param options Options as defined above (<code>GenStubSettings</code>)
+// * @param imports Imports required by the stub are added to the imports structure. If imports structure is <code>null</code>
+// * all type names are qualified.
+// * @throws JavaModelException
+// */
+// public static String genStub(String destTypeName, IMethod method, GenStubSettings settings, IImportsStructure imports) throws JavaModelException {
+// IType declaringtype= method.getDeclaringType();
+// StringBuffer buf= new StringBuffer();
+// String methodName= method.getElementName();
+// String[] paramTypes= method.getParameterTypes();
+// String[] paramNames= method.getParameterNames();
+// String[] excTypes= method.getExceptionTypes();
+// String retTypeSig= method.getReturnType();
+// int flags= method.getFlags();
+// boolean isConstructor= method.isConstructor();
+//
+// int lastParam= paramTypes.length -1;
+//
+//
+// if (settings.createComments) {
+// if (isConstructor) {
+// String desc= "Constructor for " + destTypeName; //$NON-NLS-1$
+// genJavaDocStub(desc, paramNames, Signature.SIG_VOID, excTypes, buf);
+// } else {
+// // php doc
+// if (settings.methodOverwrites) {
+// boolean isDeprecated= Flags.isDeprecated(flags);
+// genJavaDocSeeTag(declaringtype, methodName, paramTypes, settings.createNonJavadocComments, isDeprecated, buf);
+// } else {
+// // generate a default php doc comment
+// String desc= "Method " + methodName; //$NON-NLS-1$
+// genJavaDocStub(desc, paramNames, retTypeSig, excTypes, buf);
+// }
+// }
+// buf.append('\n');
+// }
+//
+// if (Flags.isPublic(flags) || isConstructor || (declaringtype.isInterface() && !settings.noBody)) {
+// buf.append("public "); //$NON-NLS-1$
+// } else if (Flags.isProtected(flags)) {
+// buf.append("protected "); //$NON-NLS-1$
+// } else if (Flags.isPrivate(flags)) {
+// buf.append("private "); //$NON-NLS-1$
+// }
+// if (Flags.isSynchronized(flags)) {
+// buf.append("synchronized "); //$NON-NLS-1$
+// }
+// if (Flags.isVolatile(flags)) {
+// buf.append("volatile "); //$NON-NLS-1$
+// }
+// if (Flags.isStrictfp(flags)) {
+// buf.append("strictfp "); //$NON-NLS-1$
+// }
+// if (Flags.isStatic(flags)) {
+// buf.append("static "); //$NON-NLS-1$
+// }
+//
+// if (isConstructor) {
+// buf.append(destTypeName);
+// } else {
+// String retTypeFrm;
+// if (!isPrimitiveType(retTypeSig)) {
+// retTypeFrm= resolveAndAdd(retTypeSig, declaringtype, imports);
+// } else {
+// retTypeFrm= Signature.toString(retTypeSig);
+// }
+// buf.append(retTypeFrm);
+// buf.append(' ');
+// buf.append(methodName);
+// }
+// buf.append('(');
+// for (int i= 0; i <= lastParam; i++) {
+// String paramTypeSig= paramTypes[i];
+// String paramTypeFrm;
+//
+// if (!isPrimitiveType(paramTypeSig)) {
+// paramTypeFrm= resolveAndAdd(paramTypeSig, declaringtype, imports);
+// } else {
+// paramTypeFrm= Signature.toString(paramTypeSig);
+// }
+// buf.append(paramTypeFrm);
+// buf.append(' ');
+// buf.append(paramNames[i]);
+// if (i < lastParam) {
+// buf.append(", "); //$NON-NLS-1$
+// }
+// }
+// buf.append(')');
+//
+// int lastExc= excTypes.length - 1;
+// if (lastExc >= 0) {
+// buf.append(" throws "); //$NON-NLS-1$
+// for (int i= 0; i <= lastExc; i++) {
+// String excTypeSig= excTypes[i];
+// String excTypeFrm= resolveAndAdd(excTypeSig, declaringtype, imports);
+// buf.append(excTypeFrm);
+// if (i < lastExc) {
+// buf.append(", "); //$NON-NLS-1$
+// }
+// }
+// }
+// if (settings.noBody) {
+// buf.append(";\n\n"); //$NON-NLS-1$
+// } else {
+// buf.append(" {\n\t"); //$NON-NLS-1$
+// if (!settings.callSuper) {
+// if (retTypeSig != null && !retTypeSig.equals(Signature.SIG_VOID)) {
+// buf.append('\t');
+// if (!isPrimitiveType(retTypeSig) || Signature.getArrayCount(retTypeSig) > 0) {
+// buf.append("return null;\n\t"); //$NON-NLS-1$
+// } else if (retTypeSig.equals(Signature.SIG_BOOLEAN)) {
+// buf.append("return false;\n\t"); //$NON-NLS-1$
+// } else {
+// buf.append("return 0;\n\t"); //$NON-NLS-1$
+// }
+// }
+// } else {
+// buf.append('\t');
+// if (!isConstructor) {
+// if (!Signature.SIG_VOID.equals(retTypeSig)) {
+// buf.append("return "); //$NON-NLS-1$
+// }
+// buf.append("super."); //$NON-NLS-1$
+// buf.append(methodName);
+// } else {
+// buf.append("super"); //$NON-NLS-1$
+// }
+// buf.append('(');
+// for (int i= 0; i <= lastParam; i++) {
+// buf.append(paramNames[i]);
+// if (i < lastParam) {
+// buf.append(", "); //$NON-NLS-1$
+// }
+// }
+// buf.append(");\n\t"); //$NON-NLS-1$
+// }
+// buf.append("}\n"); //$NON-NLS-1$
+// }
+// return buf.toString();
+// }
+//
+// private static boolean isSet(int options, int flag) {
+// return (options & flag) != 0;
+// }
+//
+// private static boolean isPrimitiveType(String typeName) {
+// char first= Signature.getElementType(typeName).charAt(0);
+// return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED);
+// }
+//
+// private static String resolveAndAdd(String refTypeSig, IType declaringType, IImportsStructure imports) throws JavaModelException {
+// String resolvedTypeName= JavaModelUtil.getResolvedTypeName(refTypeSig, declaringType);
+// if (resolvedTypeName != null) {
+// StringBuffer buf= new StringBuffer();
+// if (imports != null) {
+// buf.append(imports.addImport(resolvedTypeName));
+// } else {
+// buf.append(resolvedTypeName);
+// }
+// int arrayCount= Signature.getArrayCount(refTypeSig);
+// for (int i= 0; i < arrayCount; i++) {
+// buf.append("[]"); //$NON-NLS-1$
+// }
+// return buf.toString();
+// }
+// return Signature.toString(refTypeSig);
+// }
+//
+// /**
+// * Generates a default JavaDoc comment stub for a method.
+// */
+// public static void genJavaDocStub(String descr, String[] paramNames, String retTypeSig, String[] excTypeSigs, StringBuffer buf) {
+// buf.append("/**\n"); //$NON-NLS-1$
+// buf.append(" * "); buf.append(descr); buf.append(".\n"); //$NON-NLS-2$ //$NON-NLS-1$
+// for (int i= 0; i < paramNames.length; i++) {
+// buf.append(" * @param "); buf.append(paramNames[i]); buf.append('\n'); //$NON-NLS-1$
+// }
+// if (retTypeSig != null && !retTypeSig.equals(Signature.SIG_VOID)) {
+// String simpleName= Signature.getSimpleName(Signature.toString(retTypeSig));
+// buf.append(" * @return "); buf.append(simpleName); buf.append('\n'); //$NON-NLS-1$
+// }
+// if (excTypeSigs != null) {
+// for (int i= 0; i < excTypeSigs.length; i++) {
+// String simpleName= Signature.getSimpleName(Signature.toString(excTypeSigs[i]));
+// buf.append(" * @throws "); buf.append(simpleName); buf.append('\n'); //$NON-NLS-1$
+// }
+// }
+// buf.append(" */"); //$NON-NLS-1$
+// }
+//
+// /**
+// * Generates a '@see' tag to the defined method.
+// */
+// public static void genJavaDocSeeTag(IType declaringType, String methodName, String[] paramTypes, boolean nonJavaDocComment, boolean isDeprecated, StringBuffer buf) throws JavaModelException {
+// String[] fullParamNames= new String[paramTypes.length];
+// for (int i= 0; i < paramTypes.length; i++) {
+// fullParamNames[i]= JavaModelUtil.getResolvedTypeName(paramTypes[i], declaringType);
+// }
+// String fullTypeName= JavaModelUtil.getFullyQualifiedName(declaringType);
+//
+// genJavaDocSeeTag(fullTypeName, methodName, fullParamNames, nonJavaDocComment, isDeprecated, buf);
+// }
+//
+// /**
+// * Generates a '@see' tag to the defined method.
+// */
+// public static void genJavaDocSeeTag(String fullyQualifiedTypeName, String methodName, String[] fullParamTypeNames, boolean nonJavaDocComment, boolean isDeprecated, StringBuffer buf) throws JavaModelException {
+// // create a @see link
+// buf.append("/*"); //$NON-NLS-1$
+// if (!nonJavaDocComment) {
+// buf.append('*');
+// } else {
+// buf.append(" (non-Javadoc)"); //$NON-NLS-1$
+// }
+// buf.append("\n * @see "); //$NON-NLS-1$
+// buf.append(fullyQualifiedTypeName);
+// buf.append('#');
+// buf.append(methodName);
+// buf.append('(');
+// for (int i= 0; i < fullParamTypeNames.length; i++) {
+// if (i > 0) {
+// buf.append(", "); //$NON-NLS-1$
+// }
+// buf.append(fullParamTypeNames[i]);
+// }
+// buf.append(")\n"); //$NON-NLS-1$
+// if (isDeprecated) {
+// buf.append(" * @deprecated\n"); //$NON-NLS-1$
+// }
+// buf.append(" */"); //$NON-NLS-1$
+// }
+//
+//
+//
+// /**
+// * Finds a method in a list of methods.
+// * @return The found method or null, if nothing found
+// */
+// private static IMethod findMethod(IMethod method, List allMethods) throws JavaModelException {
+// String name= method.getElementName();
+// String[] paramTypes= method.getParameterTypes();
+// boolean isConstructor= method.isConstructor();
+//
+// for (int i= allMethods.size() - 1; i >= 0; i--) {
+// IMethod curr= (IMethod) allMethods.get(i);
+// if (JavaModelUtil.isSameMethodSignature(name, paramTypes, isConstructor, curr)) {
+// return curr;
+// }
+// }
+// return null;
+// }
+
+
+ /**
+ * Creates needed constructors for a type.
+ * @param type The type to create constructors for
+ * @param supertype The type's super type
+ * @param settings Options for comment generation
+ * @param imports Required imports are added to the import structure. Structure can be <code>null</code>, types are qualified then.
+ * @return Returns the generated stubs or <code>null</code> if the creation has been canceled
+ */
+// public static String[] evalConstructors(IType type, IType supertype, CodeGenerationSettings settings, IImportsStructure imports) throws JavaModelException {
+// IMethod[] superMethods= supertype.getMethods();
+// String typeName= type.getElementName();
+// IMethod[] methods= type.getMethods();
+// GenStubSettings genStubSettings= new GenStubSettings(settings);
+// genStubSettings.callSuper= true;
+// ArrayList newMethods= new ArrayList(superMethods.length);
+// for (int i= 0; i < superMethods.length; i++) {
+// IMethod curr= superMethods[i];
+// if (curr.isConstructor() && (JavaModelUtil.isVisible(curr, type.getPackageFragment()) || Flags.isProtected(curr.getFlags()))) {
+// if (JavaModelUtil.findMethod(typeName, curr.getParameterTypes(), true, methods) == null) {
+// String newStub= genStub(typeName, superMethods[i], genStubSettings, imports);
+// newMethods.add(newStub);
+// }
+// }
+// }
+// return (String[]) newMethods.toArray(new String[newMethods.size()]);
+// }
+//
+// /**
+// * Searches for unimplemented methods of a type.
+// * @param isSubType If set, the evaluation is for a subtype of the given type. If not set, the
+// * evaluation is for the type itself.
+// * @param settings Options for comment generation
+// * @param selectionQuery If not null will select the methods to implement.
+// * @param imports Required imports are added to the import structure. Structure can be <code>null</code>, types are qualified then.
+// * @return Returns the generated stubs or <code>null</code> if the creation has been canceled
+// */
+// public static String[] evalUnimplementedMethods(IType type, ITypeHierarchy hierarchy, boolean isSubType, CodeGenerationSettings settings,
+// IOverrideMethodQuery selectionQuery, IImportsStructure imports) throws JavaModelException {
+// List allMethods= new ArrayList();
+// List toImplement= new ArrayList();
+//
+// IMethod[] typeMethods= type.getMethods();
+// for (int i= 0; i < typeMethods.length; i++) {
+// IMethod curr= typeMethods[i];
+// if (!curr.isConstructor() && !Flags.isStatic(curr.getFlags()) && !Flags.isPrivate(curr.getFlags())) {
+// allMethods.add(curr);
+// }
+// }
+//
+// IType[] superTypes= hierarchy.getAllSuperclasses(type);
+// for (int i= 0; i < superTypes.length; i++) {
+// IMethod[] methods= superTypes[i].getMethods();
+// for (int k= 0; k < methods.length; k++) {
+// IMethod curr= methods[k];
+// if (!curr.isConstructor() && !Flags.isStatic(curr.getFlags()) && !Flags.isPrivate(curr.getFlags())) {
+// if (findMethod(curr, allMethods) == null) {
+// allMethods.add(curr);
+// }
+// }
+// }
+// }
+//
+// // do not call super
+// for (int i= 0; i < allMethods.size(); i++) {
+// IMethod curr= (IMethod) allMethods.get(i);
+// if ((Flags.isAbstract(curr.getFlags()) || curr.getDeclaringType().isInterface()) && (isSubType || !type.equals(curr.getDeclaringType()))) {
+// // implement all abstract methods
+// toImplement.add(curr);
+// }
+// }
+//
+// IType[] superInterfaces= hierarchy.getAllSuperInterfaces(type);
+// for (int i= 0; i < superInterfaces.length; i++) {
+// IMethod[] methods= superInterfaces[i].getMethods();
+// for (int k= 0; k < methods.length; k++) {
+// IMethod curr= methods[k];
+//
+// // binary interfaces can contain static initializers (variable intializations)
+// // 1G4CKUS
+// if (!Flags.isStatic(curr.getFlags())) {
+// IMethod impl= findMethod(curr, allMethods);
+// if (impl == null || ((curr.getExceptionTypes().length < impl.getExceptionTypes().length) && !Flags.isFinal(impl.getFlags()))) {
+// if (impl != null) {
+// allMethods.remove(impl);
+// }
+// // implement an interface method when it does not exist in the hierarchy
+// // or when it throws less exceptions that the implemented
+// toImplement.add(curr);
+// allMethods.add(curr);
+// }
+// }
+// }
+// }
+// IMethod[] toImplementArray= (IMethod[]) toImplement.toArray(new IMethod[toImplement.size()]);
+// if (selectionQuery != null) {
+// if (!isSubType) {
+// allMethods.removeAll(Arrays.asList(typeMethods));
+// }
+// // remove finals
+// for (int i= allMethods.size() - 1; i >= 0; i--) {
+// IMethod curr= (IMethod) allMethods.get(i);
+// if (Flags.isFinal(curr.getFlags())) {
+// allMethods.remove(i);
+// }
+// }
+// IMethod[] choice= (IMethod[]) allMethods.toArray(new IMethod[allMethods.size()]);
+// toImplementArray= selectionQuery.select(choice, toImplementArray, hierarchy);
+// if (toImplementArray == null) {
+// //cancel pressed
+// return null;
+// }
+// }
+// GenStubSettings genStubSettings= new GenStubSettings(settings);
+// genStubSettings.methodOverwrites= true;
+// String[] result= new String[toImplementArray.length];
+// for (int i= 0; i < toImplementArray.length; i++) {
+// IMethod curr= toImplementArray[i];
+// IMethod overrides= JavaModelUtil.findMethodImplementationInHierarchy(hierarchy, type, curr.getElementName(), curr.getParameterTypes(), curr.isConstructor());
+// genStubSettings.callSuper= (overrides != null);
+//
+// IMethod desc= JavaModelUtil.findMethodDeclarationInHierarchy(hierarchy, type, curr.getElementName(), curr.getParameterTypes(), curr.isConstructor());
+// if (desc != null) {
+// curr= desc;
+// }
+// result[i]= genStub(type.getElementName(), curr, genStubSettings, imports);
+// }
+// return result;
+// }
+
+ /**
+ * Examines a string and returns the first line delimiter found.
+ */
+// public static String getLineDelimiterUsed(IJavaElement elem) throws JavaModelException {
+// ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
+// if (cu != null && cu.exists()) {
+// IBuffer buf= cu.getBuffer();
+// int length= buf.getLength();
+// for (int i= 0; i < length; i++) {
+// char ch= buf.getChar(i);
+// if (ch == SWT.CR) {
+// if (i + 1 < length) {
+// if (buf.getChar(i + 1) == SWT.LF) {
+// return "\r\n"; //$NON-NLS-1$
+// }
+// }
+// return "\r"; //$NON-NLS-1$
+// } else if (ch == SWT.LF) {
+// return "\n"; //$NON-NLS-1$
+// }
+// }
+// }
+// return System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+
+ /**
+ * Embodies the policy which line delimiter to use when inserting into
+ * a document.
+ */
+ public static String getLineDelimiterFor(IDocument doc) {
+ // new for: 1GF5UU0: ITPJUI:WIN2000 - "Organize Imports" in php editor inserts lines in wrong format
+ String lineDelim= null;
+ try {
+ lineDelim= doc.getLineDelimiter(0);
+ } catch (BadLocationException e) {
+ }
+ if (lineDelim == null) {
+ String systemDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ String[] lineDelims= doc.getLegalLineDelimiters();
+ for (int i= 0; i < lineDelims.length; i++) {
+ if (lineDelims[i].equals(systemDelimiter)) {
+ lineDelim= systemDelimiter;
+ break;
+ }
+ }
+ if (lineDelim == null) {
+ lineDelim= lineDelims.length > 0 ? lineDelims[0] : systemDelimiter;
+ }
+ }
+ return lineDelim;
+ }
+
+
+ /**
+ * Evaluates the indention used by a Java element. (in tabulators)
+ */
+// public static int getIndentUsed(IJavaElement elem) throws JavaModelException {
+// if (elem instanceof ISourceReference) {
+// ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
+// if (cu != null) {
+// IBuffer buf= cu.getBuffer();
+// int offset= ((ISourceReference)elem).getSourceRange().getOffset();
+// int i= offset;
+// // find beginning of line
+// while (i > 0 && !Strings.isLineDelimiterChar(buf.getChar(i - 1)) ){
+// i--;
+// }
+// return Strings.computeIndent(buf.getText(i, offset - i), CodeFormatterUtil.getTabWidth());
+// }
+// }
+// return 0;
+// }
+
+ public static String codeFormat(String sourceString, int initialIndentationLevel, String lineDelim) {
+ ICodeFormatter formatter= ToolFactory.createDefaultCodeFormatter(null);
+ return formatter.format(sourceString, initialIndentationLevel, null, lineDelim);
+ }
+
+ /**
+ * Returns the element after the give element.
+ */
+// public static IJavaElement findNextSibling(IJavaElement member) throws JavaModelException {
+// IJavaElement parent= member.getParent();
+// if (parent instanceof IParent) {
+// IJavaElement[] elements= ((IParent)parent).getChildren();
+// for (int i= elements.length - 2; i >= 0 ; i--) {
+// if (member.equals(elements[i])) {
+// return elements[i+1];
+// }
+// }
+// }
+// return null;
+// }
+//
+// public static String getTodoTaskTag(IJavaProject project) {
+// String markers= null;
+// if (project == null) {
+// markers= JavaCore.getOption(JavaCore.COMPILER_TASK_TAGS);
+// } else {
+// markers= project.getOption(JavaCore.COMPILER_TASK_TAGS, true);
+// }
+//
+// if (markers != null && markers.length() > 0) {
+// int idx= markers.indexOf(',');
+// if (idx == -1) {
+// return markers;
+// } else {
+// return markers.substring(0, idx);
+// }
+// }
+// return null;
+// }
+
+}
--- /dev/null
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.dialog;
+
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.jface.dialogs.DialogPage;
+
+/**
+ * A utility class to work with IStatus.
+ */
+public class StatusUtil {
+
+ /**
+ * Compares two instances of <code>IStatus</code>. The more severe is returned:
+ * An error is more severe than a warning, and a warning is more severe
+ * than ok. If the two stati have the same severity, the second is returned.
+ */
+ public static IStatus getMoreSevere(IStatus s1, IStatus s2) {
+ if (s1.getSeverity() > s2.getSeverity()) {
+ return s1;
+ } else {
+ return s2;
+ }
+ }
+
+ /**
+ * Finds the most severe status from a array of stati.
+ * An error is more severe than a warning, and a warning is more severe
+ * than ok.
+ */
+ public static IStatus getMostSevere(IStatus[] status) {
+ IStatus max= null;
+ for (int i= 0; i < status.length; i++) {
+ IStatus curr= status[i];
+ if (curr.matches(IStatus.ERROR)) {
+ return curr;
+ }
+ if (max == null || curr.getSeverity() > max.getSeverity()) {
+ max= curr;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Applies the status to the status line of a dialog page.
+ */
+ public static void applyToStatusLine(DialogPage page, IStatus status) {
+ String message= status.getMessage();
+ switch (status.getSeverity()) {
+ case IStatus.OK:
+ page.setMessage(message, DialogPage.NONE);
+ page.setErrorMessage(null);
+ break;
+ case IStatus.WARNING:
+ page.setMessage(message, DialogPage.WARNING);
+ page.setErrorMessage(null);
+ break;
+ case IStatus.INFO:
+ page.setMessage(message, DialogPage.INFORMATION);
+ page.setErrorMessage(null);
+ break;
+ default:
+ if (message.length() == 0) {
+ message= null;
+ }
+ page.setMessage(null);
+ page.setErrorMessage(message);
+ break;
+ }
+ }
+}
--- /dev/null
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import net.sourceforge.phpdt.core.ICodeFormatter;
+import net.sourceforge.phpdt.core.ToolFactory;
+import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
+import net.sourceforge.phpdt.internal.ui.dialog.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialog.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.util.TabFolderLayout;
+import net.sourceforge.phpeclipse.PHPCore;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/*
+ * The page for setting code formatter options
+ */
+public class CodeFormatterPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ // Preference store keys, see PHPCore.getOptions
+ private static final String PREF_NEWLINE_OPENING_BRACES= PHPCore.FORMATTER_NEWLINE_OPENING_BRACE;
+ private static final String PREF_NEWLINE_CONTROL_STATEMENT= PHPCore.FORMATTER_NEWLINE_CONTROL;
+ private static final String PREF_NEWLINE_CLEAR_ALL= PHPCore.FORMATTER_CLEAR_BLANK_LINES;
+ private static final String PREF_NEWLINE_ELSE_IF= PHPCore.FORMATTER_NEWLINE_ELSE_IF;
+ private static final String PREF_NEWLINE_EMPTY_BLOCK= PHPCore.FORMATTER_NEWLINE_EMPTY_BLOCK;
+ private static final String PREF_LINE_SPLIT= PHPCore.FORMATTER_LINE_SPLIT;
+ private static final String PREF_STYLE_COMPACT_ASSIGNEMENT= PHPCore.FORMATTER_COMPACT_ASSIGNMENT;
+ private static final String PREF_TAB_CHAR= PHPCore.FORMATTER_TAB_CHAR;
+ private static final String PREF_TAB_SIZE= PHPCore.FORMATTER_TAB_SIZE;
+
+ // values
+ private static final String INSERT= PHPCore.INSERT;
+ private static final String DO_NOT_INSERT= PHPCore.DO_NOT_INSERT;
+
+ private static final String COMPACT= PHPCore.COMPACT;
+ private static final String NORMAL= PHPCore.NORMAL;
+
+ private static final String TAB= PHPCore.TAB;
+ private static final String SPACE= PHPCore.SPACE;
+
+ private static final String CLEAR_ALL= PHPCore.CLEAR_ALL;
+ private static final String PRESERVE_ONE= PHPCore.PRESERVE_ONE;
+
+
+ private static String[] getAllKeys() {
+ return new String[] {
+ PREF_NEWLINE_OPENING_BRACES, PREF_NEWLINE_CONTROL_STATEMENT, PREF_NEWLINE_CLEAR_ALL,
+ PREF_NEWLINE_ELSE_IF, PREF_NEWLINE_EMPTY_BLOCK, PREF_LINE_SPLIT,
+ PREF_STYLE_COMPACT_ASSIGNEMENT, PREF_TAB_CHAR, PREF_TAB_SIZE
+ };
+ }
+
+ /**
+ * Gets the currently configured tab size
+ * @deprecated Inline to avoid reference to preference page
+ */
+ public static int getTabSize() {
+ String string= (String) PHPCore.getOptions().get(PREF_TAB_SIZE);
+ return getPositiveIntValue(string, 4);
+ }
+
+ /**
+ * Gets the current compating assignement configuration
+ * @deprecated Inline to avoid reference to preference page
+ */
+ public static boolean isCompactingAssignment() {
+ return COMPACT.equals(PHPCore.getOptions().get(PREF_STYLE_COMPACT_ASSIGNEMENT));
+ }
+
+ /**
+ * Gets the current compating assignement configuration
+ * @deprecated Inline to avoid reference to preference page
+ */
+ public static boolean useSpaces() {
+ return SPACE.equals(PHPCore.getOptions().get(PREF_TAB_CHAR));
+ }
+
+
+ private static int getPositiveIntValue(String string, int dflt) {
+ try {
+ int i= Integer.parseInt(string);
+ if (i >= 0) {
+ return i;
+ }
+ } catch (NumberFormatException e) {
+ }
+ return dflt;
+ }
+
+ private static class ControlData {
+ private String fKey;
+ private String[] fValues;
+
+ public ControlData(String key, String[] values) {
+ fKey= key;
+ fValues= values;
+ }
+
+ public String getKey() {
+ return fKey;
+ }
+
+ public String getValue(boolean selection) {
+ int index= selection ? 0 : 1;
+ return fValues[index];
+ }
+
+ public String getValue(int index) {
+ return fValues[index];
+ }
+
+ public int getSelection(String value) {
+ for (int i= 0; i < fValues.length; i++) {
+ if (value.equals(fValues[i])) {
+ return i;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private Hashtable fWorkingValues;
+
+ private ArrayList fCheckBoxes;
+ private ArrayList fTextBoxes;
+
+ private SelectionListener fButtonSelectionListener;
+ private ModifyListener fTextModifyListener;
+
+ private String fPreviewText;
+ private IDocument fPreviewDocument;
+
+ private Text fTabSizeTextBox;
+ // private SourceViewer fSourceViewer;
+
+
+ public CodeFormatterPreferencePage() {
+ setPreferenceStore(PHPeclipsePlugin.getDefault().getPreferenceStore());
+ setDescription(PHPUIMessages.getString("CodeFormatterPreferencePage.description")); //$NON-NLS-1$
+
+ fWorkingValues= PHPCore.getOptions();
+ fCheckBoxes= new ArrayList();
+ fTextBoxes= new ArrayList();
+
+ fButtonSelectionListener= new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {}
+
+ public void widgetSelected(SelectionEvent e) {
+ if (!e.widget.isDisposed()) {
+ controlChanged((Button) e.widget);
+ }
+ }
+ };
+
+ fTextModifyListener= new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (!e.widget.isDisposed()) {
+ textChanged((Text) e.widget);
+ }
+ }
+ };
+
+ fPreviewDocument= new Document();
+ fPreviewText= loadPreviewFile("CodeFormatterPreviewCode.txt"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see IWorkbenchPreferencePage#init()
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * @see PreferencePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+// WorkbenchHelp.setHelp(getControl(), IJavaHelpContextIds.CODEFORMATTER_PREFERENCE_PAGE);
+ }
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+
+ Composite composite= new Composite(parent, SWT.NONE);
+ composite.setLayout(layout);
+
+
+ TabFolder folder= new TabFolder(composite, SWT.NONE);
+ folder.setLayout(new TabFolderLayout());
+ folder.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ String[] insertNotInsert= new String[] { INSERT, DO_NOT_INSERT };
+
+ layout= new GridLayout();
+ layout.numColumns= 2;
+
+ Composite newlineComposite= new Composite(folder, SWT.NULL);
+ newlineComposite.setLayout(layout);
+
+ String label= PHPUIMessages.getString("CodeFormatterPreferencePage.newline_opening_braces.label"); //$NON-NLS-1$
+ addCheckBox(newlineComposite, label, PREF_NEWLINE_OPENING_BRACES, insertNotInsert);
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.newline_control_statement.label"); //$NON-NLS-1$
+ addCheckBox(newlineComposite, label, PREF_NEWLINE_CONTROL_STATEMENT, insertNotInsert);
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.newline_clear_lines"); //$NON-NLS-1$
+ addCheckBox(newlineComposite, label, PREF_NEWLINE_CLEAR_ALL, new String[] { CLEAR_ALL, PRESERVE_ONE } );
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.newline_else_if.label"); //$NON-NLS-1$
+ addCheckBox(newlineComposite, label, PREF_NEWLINE_ELSE_IF, insertNotInsert);
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.newline_empty_block.label"); //$NON-NLS-1$
+ addCheckBox(newlineComposite, label, PREF_NEWLINE_EMPTY_BLOCK, insertNotInsert);
+
+ layout= new GridLayout();
+ layout.numColumns= 2;
+
+ Composite lineSplittingComposite= new Composite(folder, SWT.NULL);
+ lineSplittingComposite.setLayout(layout);
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.split_line.label"); //$NON-NLS-1$
+ addTextField(lineSplittingComposite, label, PREF_LINE_SPLIT);
+
+ layout= new GridLayout();
+ layout.numColumns= 2;
+
+ Composite styleComposite= new Composite(folder, SWT.NULL);
+ styleComposite.setLayout(layout);
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.style_compact_assignement.label"); //$NON-NLS-1$
+ addCheckBox(styleComposite, label, PREF_STYLE_COMPACT_ASSIGNEMENT, new String[] { COMPACT, NORMAL } );
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.tab_char.label"); //$NON-NLS-1$
+ addCheckBox(styleComposite, label, PREF_TAB_CHAR, new String[] { TAB, SPACE } );
+
+ label= PHPUIMessages.getString("CodeFormatterPreferencePage.tab_size.label"); //$NON-NLS-1$
+ fTabSizeTextBox= addTextField(styleComposite, label, PREF_TAB_SIZE);
+
+ TabItem item= new TabItem(folder, SWT.NONE);
+ item.setText(PHPUIMessages.getString("CodeFormatterPreferencePage.tab.newline.tabtitle")); //$NON-NLS-1$
+ item.setControl(newlineComposite);
+
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(PHPUIMessages.getString("CodeFormatterPreferencePage.tab.linesplit.tabtitle")); //$NON-NLS-1$
+ item.setControl(lineSplittingComposite);
+
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(PHPUIMessages.getString("CodeFormatterPreferencePage.tab.style.tabtitle")); //$NON-NLS-1$
+ item.setControl(styleComposite);
+
+ // fSourceViewer= createPreview(parent);
+
+ updatePreview();
+
+ return composite;
+ }
+
+// private SourceViewer createPreview(Composite parent) {
+// SourceViewer previewViewer= new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+// JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
+// previewViewer.configure(new PHPSourceViewerConfiguration(tools, null));
+// previewViewer.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
+// previewViewer.getTextWidget().setTabs(getPositiveIntValue((String) fWorkingValues.get(PREF_TAB_SIZE), 0));
+// previewViewer.setEditable(false);
+// previewViewer.setDocument(fPreviewDocument);
+// Control control= previewViewer.getControl();
+// GridData gdata= new GridData(GridData.FILL_BOTH);
+// gdata.widthHint= convertWidthInCharsToPixels(30);
+// gdata.heightHint= convertHeightInCharsToPixels(5);
+// control.setLayoutData(gdata);
+// return previewViewer;
+// }
+
+
+ private Button addCheckBox(Composite parent, String label, String key, String[] values) {
+ ControlData data= new ControlData(key, values);
+
+ GridData gd= new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan= 2;
+
+ Button checkBox= new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+ checkBox.setData(data);
+ checkBox.setLayoutData(gd);
+
+ String currValue= (String)fWorkingValues.get(key);
+ checkBox.setSelection(data.getSelection(currValue) == 0);
+ checkBox.addSelectionListener(fButtonSelectionListener);
+
+ fCheckBoxes.add(checkBox);
+ return checkBox;
+ }
+
+ private Text addTextField(Composite parent, String label, String key) {
+ Label labelControl= new Label(parent, SWT.NONE);
+ labelControl.setText(label);
+ labelControl.setLayoutData(new GridData());
+
+ Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
+ textBox.setData(key);
+ textBox.setLayoutData(new GridData());
+
+ String currValue= (String)fWorkingValues.get(key);
+ textBox.setText(String.valueOf(getPositiveIntValue(currValue, 1)));
+ textBox.setTextLimit(3);
+ textBox.addModifyListener(fTextModifyListener);
+
+ GridData gd= new GridData();
+ gd.widthHint= convertWidthInCharsToPixels(5);
+ textBox.setLayoutData(gd);
+
+ fTextBoxes.add(textBox);
+ return textBox;
+ }
+
+ private void controlChanged(Button button) {
+ ControlData data= (ControlData) button.getData();
+ boolean selection= button.getSelection();
+ String newValue= data.getValue(selection);
+ fWorkingValues.put(data.getKey(), newValue);
+ updatePreview();
+
+ if (PREF_TAB_CHAR.equals(data.getKey())) {
+ updateStatus(new StatusInfo());
+ if (selection) {
+ fTabSizeTextBox.setText((String)fWorkingValues.get(PREF_TAB_SIZE));
+ }
+ }
+ }
+
+ private void textChanged(Text textControl) {
+ String key= (String) textControl.getData();
+ String number= textControl.getText();
+ IStatus status= validatePositiveNumber(number);
+ if (!status.matches(IStatus.ERROR)) {
+ fWorkingValues.put(key, number);
+ }
+// if (PREF_TAB_SIZE.equals(key)) {
+// fSourceViewer.getTextWidget().setTabs(getPositiveIntValue(number, 0));
+// }
+ updateStatus(status);
+ updatePreview();
+ }
+
+
+ /*
+ * @see IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ String[] allKeys= getAllKeys();
+ // preserve other options
+ // store in JCore
+ Hashtable actualOptions= PHPCore.getOptions();
+ for (int i= 0; i < allKeys.length; i++) {
+ String key= allKeys[i];
+ String val= (String) fWorkingValues.get(key);
+ actualOptions.put(key, val);
+ }
+ PHPCore.setOptions(actualOptions);
+ PHPeclipsePlugin.getDefault().savePluginPreferences();
+ return super.performOk();
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ fWorkingValues= PHPCore.getDefaultOptions();
+ updateControls();
+ super.performDefaults();
+ }
+
+ private String loadPreviewFile(String filename) {
+ String separator= System.getProperty("line.separator"); //$NON-NLS-1$
+ StringBuffer btxt= new StringBuffer(512);
+ BufferedReader rin= null;
+ try {
+ rin= new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename)));
+ String line;
+ while ((line= rin.readLine()) != null) {
+ btxt.append(line);
+ btxt.append(separator);
+ }
+ } catch (IOException io) {
+ PHPeclipsePlugin.log(io);
+ } finally {
+ if (rin != null) {
+ try { rin.close(); } catch (IOException e) {}
+ }
+ }
+ return btxt.toString();
+ }
+
+
+ private void updatePreview() {
+ ICodeFormatter formatter= ToolFactory.createDefaultCodeFormatter(fWorkingValues);
+ fPreviewDocument.set(formatter.format(fPreviewText, 0, null, "\n")); //$NON-NLS-1$
+ }
+
+ private void updateControls() {
+ // update the UI
+ for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
+ Button curr= (Button) fCheckBoxes.get(i);
+ ControlData data= (ControlData) curr.getData();
+
+ String currValue= (String) fWorkingValues.get(data.getKey());
+ curr.setSelection(data.getSelection(currValue) == 0);
+ }
+ for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
+ Text curr= (Text) fTextBoxes.get(i);
+ String key= (String) curr.getData();
+ String currValue= (String) fWorkingValues.get(key);
+ curr.setText(currValue);
+ }
+ }
+
+ private IStatus validatePositiveNumber(String number) {
+ StatusInfo status= new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PHPUIMessages.getString("CodeFormatterPreferencePage.empty_input")); //$NON-NLS-1$
+ } else {
+ try {
+ int value= Integer.parseInt(number);
+ if (value < 0) {
+ status.setError(PHPUIMessages.getFormattedString("CodeFormatterPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ }
+ } catch (NumberFormatException e) {
+ status.setError(PHPUIMessages.getFormattedString("CodeFormatterPreferencePage.invalid_input", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+
+ private void updateStatus(IStatus status) {
+ if (!status.matches(IStatus.ERROR)) {
+ // look if there are more severe errors
+ for (int i= 0; i < fTextBoxes.size(); i++) {
+ Text curr= (Text) fTextBoxes.get(i);
+ if (!(curr == fTabSizeTextBox && usesTabs())) {
+ IStatus currStatus= validatePositiveNumber(curr.getText());
+ status= StatusUtil.getMoreSevere(currStatus, status);
+ }
+ }
+ }
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+ }
+
+ private boolean usesTabs() {
+ return TAB.equals(fWorkingValues.get(PREF_TAB_CHAR));
+ }
+
+
+}
+
+
--- /dev/null
+{
+
+if (size < currentSize) {
+try {
+size = inStream.available();
+} catch (IOException e) {
+}
+}
+else if (size == currentSize) {
+++size;
+}
+else {
+--size;
+}
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.formatter.IFormattingStrategy;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+import net.sourceforge.phpdt.core.ICodeFormatter;
+import net.sourceforge.phpdt.core.ToolFactory;
+
+import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+import net.sourceforge.phpdt.internal.ui.preferences.CodeFormatterPreferencePage;
+
+public class JavaFormattingStrategy implements IFormattingStrategy {
+
+ private String fInitialIndentation;
+ private ISourceViewer fViewer;
+
+ public JavaFormattingStrategy(ISourceViewer viewer) {
+ fViewer = viewer;
+ }
+
+ /**
+ * @see IFormattingStrategy#formatterStarts(String)
+ */
+ public void formatterStarts(String initialIndentation) {
+ fInitialIndentation= initialIndentation;
+ }
+
+ /**
+ * @see IFormattingStrategy#formatterStops()
+ */
+ public void formatterStops() {
+ }
+
+ /**
+ * @see IFormattingStrategy#format(String, boolean, String, int[])
+ */
+ public String format(String content, boolean isLineStart, String indentation, int[] positions) {
+ ICodeFormatter formatter= ToolFactory.createCodeFormatter();
+
+ IDocument doc= fViewer.getDocument();
+ String lineDelimiter= StubUtility.getLineDelimiterFor(doc);
+
+ int indent= 0;
+ if (fInitialIndentation != null) {
+ indent= Strings.computeIndent(fInitialIndentation, CodeFormatterPreferencePage.getTabSize());
+ }
+ return formatter.format(content, indent, positions, lineDelimiter);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved
+ */
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+
+public class TabFolderLayout extends Layout {
+
+ protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+ if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT)
+ return new Point(wHint, hHint);
+
+ Control [] children = composite.getChildren ();
+ int count = children.length;
+ int maxWidth = 0, maxHeight = 0;
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ Point pt = child.computeSize (SWT.DEFAULT, SWT.DEFAULT, flushCache);
+ maxWidth = Math.max (maxWidth, pt.x);
+ maxHeight = Math.max (maxHeight, pt.y);
+ }
+
+ if (wHint != SWT.DEFAULT)
+ maxWidth= wHint;
+ if (hHint != SWT.DEFAULT)
+ maxHeight= hHint;
+
+ return new Point(maxWidth, maxHeight);
+
+ }
+
+ protected void layout (Composite composite, boolean flushCache) {
+ Rectangle rect= composite.getClientArea();
+
+ Control[] children = composite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ children[i].setBounds(rect);
+ }
+ }
+}
package net.sourceforge.phpeclipse;
import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
import java.util.List;
import net.sourceforge.phpeclipse.resourcesview.PHPFile;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences;
public class PHPCore {
+ public static HashSet OptionNames = new HashSet(20);
+ /**
+ * The plug-in identifier of the Java core support
+ * (value <code>"org.phpeclipse.phpdt.core"</code>).
+ */
+ public static final String PLUGIN_ID = "net.sourceforge.phpeclipse.core"; //$NON-NLS-1$
+
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$
+
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_NEWLINE_OPENING_BRACE = PLUGIN_ID + ".formatter.newline.openingBrace"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_NEWLINE_CONTROL = PLUGIN_ID + ".formatter.newline.controlStatement"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_NEWLINE_ELSE_IF = PLUGIN_ID + ".formatter.newline.elseIf"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_NEWLINE_EMPTY_BLOCK = PLUGIN_ID + ".formatter.newline.emptyBlock"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_CLEAR_BLANK_LINES = PLUGIN_ID + ".formatter.newline.clearAll"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_LINE_SPLIT = PLUGIN_ID + ".formatter.lineSplit"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_COMPACT_ASSIGNMENT = PLUGIN_ID + ".formatter.style.assignment"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_TAB_CHAR = PLUGIN_ID + ".formatter.tabulation.char"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String FORMATTER_TAB_SIZE = PLUGIN_ID + ".formatter.tabulation.size"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String INSERT = "insert"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$
+
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String PRESERVE_ONE = "preserve one"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String CLEAR_ALL = "clear all"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String NORMAL = "normal"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String COMPACT = "compact"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String TAB = "tab"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String SPACE = "space"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String ENABLED = "enabled"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.0
+ */
+ public static final String DISABLED = "disabled"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions
+ * @since 2.1
+ */
+ public static final String CLEAN = "clean"; //$NON-NLS-1$
+
+ /**
+ * Returns a table of all known configurable options with their default values.
+ * These options allow to configure the behaviour of the underlying components.
+ * The client may safely use the result as a template that they can modify and
+ * then pass to <code>setOptions</code>.
+ *
+ * Helper constants have been defined on JavaCore for each of the option ID and
+ * their possible constant values.
+ *
+ * Note: more options might be added in further releases.
+ * <pre>
+ * RECOGNIZED OPTIONS:
+ * COMPILER / Generating Local Variable Debug Attribute
+ * When generated, this attribute will enable local variable names
+ * to be displayed in debugger, only in place where variables are
+ * definitely assigned (.class file is then bigger)
+ * - option id: "org.phpeclipse.phpdt.core.compiler.debug.localVariable"
+ * - possible values: { "generate", "do not generate" }
+ * - default: "generate"
+ *
+ * COMPILER / Generating Line Number Debug Attribute
+ * When generated, this attribute will enable source code highlighting in debugger
+ * (.class file is then bigger).
+ * - option id: "org.phpeclipse.phpdt.core.compiler.debug.lineNumber"
+ * - possible values: { "generate", "do not generate" }
+ * - default: "generate"
+ *
+ * COMPILER / Generating Source Debug Attribute
+ * When generated, this attribute will enable the debugger to present the
+ * corresponding source code.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.debug.sourceFile"
+ * - possible values: { "generate", "do not generate" }
+ * - default: "generate"
+ *
+ * COMPILER / Preserving Unused Local Variables
+ * Unless requested to preserve unused local variables (i.e. never read), the
+ * compiler will optimize them out, potentially altering debugging
+ * - option id: "org.phpeclipse.phpdt.core.compiler.codegen.unusedLocal"
+ * - possible values: { "preserve", "optimize out" }
+ * - default: "preserve"
+ *
+ * COMPILER / Defining Target Java Platform
+ * For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
+ * Note that "1.4" target require to toggle compliance mode to "1.4" too.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.codegen.targetPlatform"
+ * - possible values: { "1.1", "1.2", "1.3", "1.4" }
+ * - default: "1.1"
+ *
+ * COMPILER / Reporting Unreachable Code
+ * Unreachable code can optionally be reported as an error, warning or simply
+ * ignored. The bytecode generation will always optimized it out.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.unreachableCode"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "error"
+ *
+ * COMPILER / Reporting Invalid Import
+ * An import statement that cannot be resolved might optionally be reported
+ * as an error, as a warning or ignored.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.invalidImport"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "error"
+ *
+ * COMPILER / Reporting Attempt to Override Package-Default Method
+ * A package default method is not visible in a different package, and thus
+ * cannot be overridden. When enabling this option, the compiler will signal
+ * such scenarii either as an error or a warning.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.overridingPackageDefaultMethod"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Method With Constructor Name
+ * Naming a method with a constructor name is generally considered poor
+ * style programming. When enabling this option, the compiler will signal such
+ * scenarii either as an error or a warning.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.methodWithConstructorName"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Deprecation
+ * When enabled, the compiler will signal use of deprecated API either as an
+ * error or a warning.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.deprecation"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Deprecation Inside Deprecated Code
+ * When enabled, the compiler will signal use of deprecated API inside deprecated code.
+ * The severity of the problem is controlled with option "org.phpeclipse.phpdt.core.compiler.problem.deprecation".
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.deprecationInDeprecatedCode"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * COMPILER / Reporting Hidden Catch Block
+ * Locally to a try statement, some catch blocks may hide others , e.g.
+ * try { throw new java.io.CharConversionException();
+ * } catch (java.io.CharConversionException e) {
+ * } catch (java.io.IOException e) {}.
+ * When enabling this option, the compiler will issue an error or a warning for hidden
+ * catch blocks corresponding to checked exceptions
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.hiddenCatchBlock"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Unused Local
+ * When enabled, the compiler will issue an error or a warning for unused local
+ * variables (i.e. variables never read from)
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.unusedLocal"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Unused Parameter
+ * When enabled, the compiler will issue an error or a warning for unused method
+ * parameters (i.e. parameters never read from)
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.unusedParameter"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Unused Import
+ * When enabled, the compiler will issue an error or a warning for unused import
+ * reference
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.unusedImport"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Synthetic Access Emulation
+ * When enabled, the compiler will issue an error or a warning whenever it emulates
+ * access to a non-accessible member of an enclosing type. Such access can have
+ * performance implications.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.syntheticAccessEmulation"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Non-Externalized String Literal
+ * When enabled, the compiler will issue an error or a warning for non externalized
+ * String literal (i.e. non tagged with //$NON-NLS-<n>$).
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.nonExternalizedStringLiteral"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Usage of 'assert' Identifier
+ * When enabled, the compiler will issue an error or a warning whenever 'assert' is
+ * used as an identifier (reserved keyword in 1.4)
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.assertIdentifier"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Usage of expression receiver on static invocation/field access
+ * When enabled, the compiler will issue an error or a warning whenever a static field
+ * or method is accessed with an expression receiver.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.staticAccessReceiver"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Assignment with no effect
+ * When enabled, the compiler will issue an error or a warning whenever an assignment
+ * has no effect (e.g 'x = x').
+ * - option id: "org.phpeclipse.phpdt.core.compiler.problem.noEffectAssignment"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Setting Source Compatibility Mode
+ * Specify whether source is 1.3 or 1.4 compatible. From 1.4 on, 'assert' is a keyword
+ * reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
+ * level should be set to "1.4" and the compliance mode should be "1.4".
+ * - option id: "org.phpeclipse.phpdt.core.compiler.source"
+ * - possible values: { "1.3", "1.4" }
+ * - default: "1.3"
+ *
+ * COMPILER / Setting Compliance Level
+ * Select the compliance level for the compiler. In "1.3" mode, source and target settings
+ * should not go beyond "1.3" level.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.compliance"
+ * - possible values: { "1.3", "1.4" }
+ * - default: "1.3"
+ *
+ * COMPILER / Maximum number of problems reported per compilation unit
+ * Specify the maximum number of problems reported on each compilation unit.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.maxProblemPerUnit"
+ * - possible values: "<n>" where <n> is zero or a positive integer (if zero then all problems are reported).
+ * - default: "100"
+ *
+ * COMPILER / Define the Automatic Task Tags
+ * When the tag is non empty, the compiler will issue a task marker whenever it encounters
+ * one of the corresponding tag inside any comment in Java source code.
+ * Generated task messages will include the tag, and range until the next line separator or comment ending, and will be trimmed.
+ * - option id: "org.phpeclipse.phpdt.core.compiler.taskTags"
+ * - possible values: { "<tag>[,<tag>]*" } where <tag> is a String without any wild-card
+ * - default: ""
+ *
+ * COMPILER / Define the Automatic Task Priorities
+ * In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
+ * of the task markers issued by the compiler.
+ * If the default is specified, the priority of each task marker is "NORMAL".
+ * - option id: "org.phpeclipse.phpdt.core.compiler.taskPriorities"
+ * - possible values: { "<priority>[,<priority>]*" } where <priority> is one of "HIGH", "NORMAL" or "LOW"
+ * - default: ""
+ *
+ * BUILDER / Specifying Filters for Resource Copying Control
+ * Allow to specify some filters to control the resource copy process.
+ * - option id: "org.phpeclipse.phpdt.core.builder.resourceCopyExclusionFilter"
+ * - possible values: { "<name>[,<name>]* } where <name> is a file name pattern (* and ? wild-cards allowed)
+ * or the name of a folder which ends with '/'
+ * - default: ""
+ *
+ * BUILDER / Abort if Invalid Classpath
+ * Allow to toggle the builder to abort if the classpath is invalid
+ * - option id: "org.phpeclipse.phpdt.core.builder.invalidClasspath"
+ * - possible values: { "abort", "ignore" }
+ * - default: "ignore"
+ *
+ * BUILDER / Cleaning Output Folder(s)
+ * Indicate whether the JavaBuilder is allowed to clean the output folders
+ * when performing full build operations.
+ * - option id: "org.phpeclipse.phpdt.core.builder.cleanOutputFolder"
+ * - possible values: { "clean", "ignore" }
+ * - default: "clean"
+ *
+ * JAVACORE / Computing Project Build Order
+ * Indicate whether JavaCore should enforce the project build order to be based on
+ * the classpath prerequisite chain. When requesting to compute, this takes over
+ * the platform default order (based on project references).
+ * - option id: "org.phpeclipse.phpdt.core.computeJavaBuildOrder"
+ * - possible values: { "compute", "ignore" }
+ * - default: "ignore"
+ *
+ * JAVACORE / Specify Default Source Encoding Format
+ * Get the encoding format for compiled sources. This setting is read-only, it is equivalent
+ * to 'ResourcesPlugin.getEncoding()'.
+ * - option id: "org.phpeclipse.phpdt.core.encoding"
+ * - possible values: { any of the supported encoding name}.
+ * - default: <platform default>
+ *
+ * JAVACORE / Reporting Incomplete Classpath
+ * An entry on the classpath doesn't exist or is not visible (e.g. a referenced project is closed).
+ * - option id: "org.phpeclipse.phpdt.core.incompleteClasspath"
+ * - possible values: { "error", "warning"}
+ * - default: "error"
+ *
+ * JAVACORE / Reporting Classpath Cycle
+ * A project is involved in a cycle.
+ * - option id: "org.phpeclipse.phpdt.core.circularClasspath"
+ * - possible values: { "error", "warning" }
+ * - default: "error"
+ *
+ * FORMATTER / Inserting New Line Before Opening Brace
+ * When Insert, a new line is inserted before an opening brace, otherwise nothing
+ * is inserted
+ * - option id: "org.phpeclipse.phpdt.core.formatter.newline.openingBrace"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * FORMATTER / Inserting New Line Inside Control Statement
+ * When Insert, a new line is inserted between } and following else, catch, finally
+ * - option id: "org.phpeclipse.phpdt.core.formatter.newline.controlStatement"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * FORMATTER / Clearing Blank Lines
+ * When Clear all, all blank lines are removed. When Preserve one, only one is kept
+ * and all others removed.
+ * - option id: "org.phpeclipse.phpdt.core.formatter.newline.clearAll"
+ * - possible values: { "clear all", "preserve one" }
+ * - default: "preserve one"
+ *
+ * FORMATTER / Inserting New Line Between Else/If
+ * When Insert, a blank line is inserted between an else and an if when they are
+ * contiguous. When choosing to not insert, else-if will be kept on the same
+ * line when possible.
+ * - option id: "org.phpeclipse.phpdt.core.formatter.newline.elseIf"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * FORMATTER / Inserting New Line In Empty Block
+ * When insert, a line break is inserted between contiguous { and }, if } is not followed
+ * by a keyword.
+ * - option id: "org.phpeclipse.phpdt.core.formatter.newline.emptyBlock"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "insert"
+ *
+ * FORMATTER / Splitting Lines Exceeding Length
+ * Enable splitting of long lines (exceeding the configurable length). Length of 0 will
+ * disable line splitting
+ * - option id: "org.phpeclipse.phpdt.core.formatter.lineSplit"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "80"
+ *
+ * FORMATTER / Compacting Assignment
+ * Assignments can be formatted asymmetrically, e.g. 'int x= 2;', when Normal, a space
+ * is inserted before the assignment operator
+ * - option id: "org.phpeclipse.phpdt.core.formatter.style.assignment"
+ * - possible values: { "compact", "normal" }
+ * - default: "normal"
+ *
+ * FORMATTER / Defining Indentation Character
+ * Either choose to indent with tab characters or spaces
+ * - option id: "org.phpeclipse.phpdt.core.formatter.tabulation.char"
+ * - possible values: { "tab", "space" }
+ * - default: "tab"
+ *
+ * FORMATTER / Defining Space Indentation Length
+ * When using spaces, set the amount of space characters to use for each
+ * indentation mark.
+ * - option id: "org.phpeclipse.phpdt.core.formatter.tabulation.size"
+ * - possible values: "<n>", where n is a positive integer
+ * - default: "4"
+ *
+ * CODEASSIST / Activate Visibility Sensitive Completion
+ * When active, completion doesn't show that you can not see
+ * (e.g. you can not see private methods of a super class).
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.visibilityCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Automatic Qualification of Implicit Members
+ * When active, completion automatically qualifies completion on implicit
+ * field references and message expressions.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.forceImplicitQualification"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Define the Prefixes for Field Name
+ * When the prefixes is non empty, completion for field name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.fieldPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Static Field Name
+ * When the prefixes is non empty, completion for static field name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.staticFieldPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Local Variable Name
+ * When the prefixes is non empty, completion for local variable name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.localPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Argument Name
+ * When the prefixes is non empty, completion for argument name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.argumentPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Field Name
+ * When the suffixes is non empty, completion for field name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.fieldSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Static Field Name
+ * When the suffixes is non empty, completion for static field name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.staticFieldSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Local Variable Name
+ * When the suffixes is non empty, completion for local variable name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.localSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Argument Name
+ * When the suffixes is non empty, completion for argument name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.phpeclipse.phpdt.core.codeComplete.argumentSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ * </pre>
+ *
+ * @return a mutable table containing the default settings of all known options
+ * (key type: <code>String</code>; value type: <code>String</code>)
+ * @see #setOptions
+ */
+ public static Hashtable getDefaultOptions() {
+
+ Hashtable defaultOptions = new Hashtable(10);
+
+ // see #initializeDefaultPluginPreferences() for changing default settings
+ Preferences preferences = getPlugin().getPluginPreferences();
+ HashSet optionNames = OptionNames;
+
+ // get preferences set to their default
+ String[] defaultPropertyNames = preferences.defaultPropertyNames();
+ for (int i = 0; i < defaultPropertyNames.length; i++) {
+ String propertyName = defaultPropertyNames[i];
+ if (optionNames.contains(propertyName)) {
+ defaultOptions.put(
+ propertyName,
+ preferences.getDefaultString(propertyName));
+ }
+ }
+ // get preferences not set to their default
+ String[] propertyNames = preferences.propertyNames();
+ for (int i = 0; i < propertyNames.length; i++) {
+ String propertyName = propertyNames[i];
+ if (optionNames.contains(propertyName)) {
+ defaultOptions.put(
+ propertyName,
+ preferences.getDefaultString(propertyName));
+ }
+ }
+ // get encoding through resource plugin
+ defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding());
+
+ return defaultOptions;
+ }
+ /**
+ * Helper method for returning one option value only. Equivalent to <code>(String)JavaCore.getOptions().get(optionName)</code>
+ * Note that it may answer <code>null</code> if this option does not exist.
+ * <p>
+ * For a complete description of the configurable options, see <code>getDefaultOptions</code>.
+ * </p>
+ *
+ * @param optionName the name of an option
+ * @return the String value of a given option
+ * @see JavaCore#getDefaultOptions
+ * @since 2.0
+ */
+ public static String getOption(String optionName) {
+
+ if (CORE_ENCODING.equals(optionName)) {
+ return ResourcesPlugin.getEncoding();
+ }
+ if (OptionNames.contains(optionName)) {
+ Preferences preferences = getPlugin().getPluginPreferences();
+ return preferences.getString(optionName).trim();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the table of the current options. Initially, all options have their default values,
+ * and this method returns a table that includes all known options.
+ * <p>
+ * For a complete description of the configurable options, see <code>getDefaultOptions</code>.
+ * </p>
+ *
+ * @return table of current settings of all options
+ * (key type: <code>String</code>; value type: <code>String</code>)
+ * @see JavaCore#getDefaultOptions
+ */
+ public static Hashtable getOptions() {
+
+ Hashtable options = new Hashtable(10);
+
+ // see #initializeDefaultPluginPreferences() for changing default settings
+ Plugin plugin = getPlugin();
+ if (plugin != null) {
+ Preferences preferences = getPlugin().getPluginPreferences();
+ HashSet optionNames = OptionNames;
+
+ // get preferences set to their default
+ String[] defaultPropertyNames = preferences.defaultPropertyNames();
+ for (int i = 0; i < defaultPropertyNames.length; i++) {
+ String propertyName = defaultPropertyNames[i];
+ if (optionNames.contains(propertyName)) {
+ options.put(propertyName, preferences.getDefaultString(propertyName));
+ }
+ }
+ // get preferences not set to their default
+ String[] propertyNames = preferences.propertyNames();
+ for (int i = 0; i < propertyNames.length; i++) {
+ String propertyName = propertyNames[i];
+ if (optionNames.contains(propertyName)) {
+ options.put(propertyName, preferences.getString(propertyName).trim());
+ }
+ }
+ // get encoding through resource plugin
+ options.put(CORE_ENCODING, ResourcesPlugin.getEncoding());
+ }
+ return options;
+ }
+ /**
+ * Sets the current table of options. All and only the options explicitly included in the given table
+ * are remembered; all previous option settings are forgotten, including ones not explicitly
+ * mentioned.
+ * <p>
+ * For a complete description of the configurable options, see <code>getDefaultOptions</code>.
+ * </p>
+ *
+ * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
+ * or <code>null</code> to reset all options to their default values
+ * @see JavaCore#getDefaultOptions
+ */
+ public static void setOptions(Hashtable newOptions) {
+
+ // see #initializeDefaultPluginPreferences() for changing default settings
+ Preferences preferences = getPlugin().getPluginPreferences();
+
+ if (newOptions == null) {
+ newOptions = getDefaultOptions();
+ }
+ Enumeration keys = newOptions.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (!OptionNames.contains(key))
+ continue; // unrecognized option
+ if (key.equals(CORE_ENCODING))
+ continue; // skipped, contributed by resource prefs
+ String value = (String) newOptions.get(key);
+ preferences.setValue(key, value);
+ }
+
+ // persist options
+ getPlugin().savePluginPreferences();
+ }
public static IProject[] getPHPProjects() {
List phpProjectsList = new ArrayList();
- IProject[] workspaceProjects = PHPeclipsePlugin.getWorkspace().getRoot().getProjects();
+ IProject[] workspaceProjects =
+ PHPeclipsePlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; i < workspaceProjects.length; i++) {
IProject iProject = workspaceProjects[i];
}
public static PHPProject getPHPProject(String name) {
- IProject aProject = PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
+ IProject aProject =
+ PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
if (isPHPProject(aProject)) {
PHPProject thePHPProject = new PHPProject();
thePHPProject.setProject(aProject);
return project;
}
} catch (CoreException e) {
- System.err.println("Exception occurred in PHPCore#create(IProject): " + e.toString());
+ System.err.println(
+ "Exception occurred in PHPCore#create(IProject): " + e.toString());
}
return null;
}
- public static void addPHPNature(IProject project, IProgressMonitor monitor) throws CoreException {
+ public static void addPHPNature(IProject project, IProgressMonitor monitor)
+ throws CoreException {
if (!project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
IProjectDescription description = project.getDescription();
String[] prevNatures = description.getNatureIds();
project.setDescription(description, monitor);
}
}
+
+ /**
+ * Returns the single instance of the PHP core plug-in runtime class.
+ *
+ * @return the single instance of the PHP core plug-in runtime class
+ */
+ public static Plugin getPlugin() {
+ return PHPeclipsePlugin.getDefault();
+ }
+
+/**
+ * Initializes the default preferences settings for this plug-in.
+ */
+ protected static void initializeDefaultPluginPreferences() {
+
+ Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
+ HashSet optionNames = OptionNames;
+
+// // Compiler settings
+// preferences.setDefault(COMPILER_LOCAL_VARIABLE_ATTR, GENERATE);
+// optionNames.add(COMPILER_LOCAL_VARIABLE_ATTR);
+//
+// preferences.setDefault(COMPILER_LINE_NUMBER_ATTR, GENERATE);
+// optionNames.add(COMPILER_LINE_NUMBER_ATTR);
+//
+// preferences.setDefault(COMPILER_SOURCE_FILE_ATTR, GENERATE);
+// optionNames.add(COMPILER_SOURCE_FILE_ATTR);
+//
+// preferences.setDefault(COMPILER_CODEGEN_UNUSED_LOCAL, PRESERVE);
+// optionNames.add(COMPILER_CODEGEN_UNUSED_LOCAL);
+//
+// preferences.setDefault(COMPILER_CODEGEN_TARGET_PLATFORM, VERSION_1_1);
+// optionNames.add(COMPILER_CODEGEN_TARGET_PLATFORM);
+//
+// preferences.setDefault(COMPILER_PB_UNREACHABLE_CODE, ERROR);
+// optionNames.add(COMPILER_PB_UNREACHABLE_CODE);
+//
+// preferences.setDefault(COMPILER_PB_INVALID_IMPORT, ERROR);
+// optionNames.add(COMPILER_PB_INVALID_IMPORT);
+//
+// preferences.setDefault(COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD, WARNING);
+// optionNames.add(COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD);
+//
+// preferences.setDefault(COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME, WARNING);
+// optionNames.add(COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME);
+//
+// preferences.setDefault(COMPILER_PB_DEPRECATION, WARNING);
+// optionNames.add(COMPILER_PB_DEPRECATION);
+//
+// preferences.setDefault(COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE, DISABLED);
+// optionNames.add(COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE);
+//
+// preferences.setDefault(COMPILER_PB_HIDDEN_CATCH_BLOCK, WARNING);
+// optionNames.add(COMPILER_PB_HIDDEN_CATCH_BLOCK);
+//
+// preferences.setDefault(COMPILER_PB_UNUSED_LOCAL, IGNORE);
+// optionNames.add(COMPILER_PB_UNUSED_LOCAL);
+//
+// preferences.setDefault(COMPILER_PB_UNUSED_PARAMETER, IGNORE);
+// optionNames.add(COMPILER_PB_UNUSED_PARAMETER);
+//
+// preferences.setDefault(COMPILER_PB_UNUSED_IMPORT, WARNING);
+// optionNames.add(COMPILER_PB_UNUSED_IMPORT);
+//
+// preferences.setDefault(COMPILER_PB_SYNTHETIC_ACCESS_EMULATION, IGNORE);
+// optionNames.add(COMPILER_PB_SYNTHETIC_ACCESS_EMULATION);
+//
+// preferences.setDefault(COMPILER_PB_NON_NLS_STRING_LITERAL, IGNORE);
+// optionNames.add(COMPILER_PB_NON_NLS_STRING_LITERAL);
+//
+// preferences.setDefault(COMPILER_PB_ASSERT_IDENTIFIER, IGNORE);
+// optionNames.add(COMPILER_PB_ASSERT_IDENTIFIER);
+//
+// preferences.setDefault(COMPILER_PB_STATIC_ACCESS_RECEIVER, WARNING);
+// optionNames.add(COMPILER_PB_STATIC_ACCESS_RECEIVER);
+//
+// preferences.setDefault(COMPILER_PB_NO_EFFECT_ASSIGNMENT, WARNING);
+// optionNames.add(COMPILER_PB_NO_EFFECT_ASSIGNMENT);
+//
+// preferences.setDefault(COMPILER_TASK_TAGS, ""); //$NON-NLS-1$
+// optionNames.add(COMPILER_TASK_TAGS);
+//
+// preferences.setDefault(COMPILER_TASK_PRIORITIES, ""); //$NON-NLS-1$
+// optionNames.add(COMPILER_TASK_PRIORITIES);
+//
+// preferences.setDefault(COMPILER_SOURCE, VERSION_1_3);
+// optionNames.add(COMPILER_SOURCE);
+//
+// preferences.setDefault(COMPILER_COMPLIANCE, VERSION_1_3);
+// optionNames.add(COMPILER_COMPLIANCE);
+//
+// preferences.setDefault(COMPILER_PB_MAX_PER_UNIT, "100"); //$NON-NLS-1$
+// optionNames.add(COMPILER_PB_MAX_PER_UNIT);
+//
+// // Builder settings
+// preferences.setDefault(CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
+// optionNames.add(CORE_JAVA_BUILD_RESOURCE_COPY_FILTER);
+//
+// preferences.setDefault(CORE_JAVA_BUILD_INVALID_CLASSPATH, ABORT);
+// optionNames.add(CORE_JAVA_BUILD_INVALID_CLASSPATH);
+//
+// preferences.setDefault(CORE_JAVA_BUILD_DUPLICATE_RESOURCE, WARNING);
+// optionNames.add(CORE_JAVA_BUILD_DUPLICATE_RESOURCE);
+//
+// preferences.setDefault(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, CLEAN);
+// optionNames.add(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER);
+//
+// // JavaCore settings
+// preferences.setDefault(CORE_JAVA_BUILD_ORDER, IGNORE);
+// optionNames.add(CORE_JAVA_BUILD_ORDER);
+//
+// preferences.setDefault(CORE_CIRCULAR_CLASSPATH, ERROR);
+// optionNames.add(CORE_CIRCULAR_CLASSPATH);
+//
+// preferences.setDefault(CORE_INCOMPLETE_CLASSPATH, ERROR);
+// optionNames.add(CORE_INCOMPLETE_CLASSPATH);
+
+ // encoding setting comes from resource plug-in
+ optionNames.add(CORE_ENCODING);
+
+ // Formatter settings
+ preferences.setDefault(FORMATTER_NEWLINE_OPENING_BRACE, DO_NOT_INSERT);
+ optionNames.add(FORMATTER_NEWLINE_OPENING_BRACE);
+
+ preferences.setDefault(FORMATTER_NEWLINE_CONTROL, DO_NOT_INSERT);
+ optionNames.add(FORMATTER_NEWLINE_CONTROL);
+
+ preferences.setDefault(FORMATTER_CLEAR_BLANK_LINES, PRESERVE_ONE);
+ optionNames.add(FORMATTER_CLEAR_BLANK_LINES);
+
+ preferences.setDefault(FORMATTER_NEWLINE_ELSE_IF, DO_NOT_INSERT);
+ optionNames.add(FORMATTER_NEWLINE_ELSE_IF);
+
+ preferences.setDefault(FORMATTER_NEWLINE_EMPTY_BLOCK, INSERT);
+ optionNames.add(FORMATTER_NEWLINE_EMPTY_BLOCK);
+
+ preferences.setDefault(FORMATTER_LINE_SPLIT, "80"); //$NON-NLS-1$
+ optionNames.add(FORMATTER_LINE_SPLIT);
+
+ preferences.setDefault(FORMATTER_COMPACT_ASSIGNMENT, NORMAL);
+ optionNames.add(FORMATTER_COMPACT_ASSIGNMENT);
+
+ preferences.setDefault(FORMATTER_TAB_CHAR, TAB);
+ optionNames.add(FORMATTER_TAB_CHAR);
+
+ preferences.setDefault(FORMATTER_TAB_SIZE, "4"); //$NON-NLS-1$
+ optionNames.add(FORMATTER_TAB_SIZE);
+
+ // CodeAssist settings
+// preferences.setDefault(CODEASSIST_VISIBILITY_CHECK, DISABLED); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_VISIBILITY_CHECK);
+//
+// preferences.setDefault(CODEASSIST_IMPLICIT_QUALIFICATION, DISABLED); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_IMPLICIT_QUALIFICATION);
+//
+// preferences.setDefault(CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_FIELD_PREFIXES);
+//
+// preferences.setDefault(CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_STATIC_FIELD_PREFIXES);
+//
+// preferences.setDefault(CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_LOCAL_PREFIXES);
+//
+// preferences.setDefault(CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_ARGUMENT_PREFIXES);
+//
+// preferences.setDefault(CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_FIELD_SUFFIXES);
+//
+// preferences.setDefault(CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_STATIC_FIELD_SUFFIXES);
+//
+// preferences.setDefault(CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_LOCAL_SUFFIXES);
+//
+// preferences.setDefault(CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
+// optionNames.add(CODEASSIST_ARGUMENT_SUFFIXES);
+
+ }
}
\ No newline at end of file
store.setDefault(PHP_OUTLINE_VAR, "true"); //$NON-NLS-1$
TemplatePreferencePage.initDefaults(store);
- new PHPSyntaxRdr();
//this will initialize the static fields in the syntaxrdr class
+ new PHPSyntaxRdr();
+
+ PHPCore.initializeDefaultPluginPreferences();
}
public void startup() throws CoreException {
import java.util.Vector;
+import net.sourceforge.phpdt.internal.ui.text.java.JavaFormattingStrategy;
import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.phpeditor.html.HTMLFormattingStrategy;
import net.sourceforge.phpeclipse.phpeditor.php.HTMLCompletionProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.formatter.ContentFormatter;
import org.eclipse.jface.text.formatter.IContentFormatter;
+import org.eclipse.jface.text.formatter.IFormattingStrategy;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
* @see SourceViewerConfiguration#getContentFormatter(ISourceViewer)
*/
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
+// if (fFormatter == null) {
+// fFormatter = new ContentFormatter();
+// fFormattingStrategy = new HTMLFormattingStrategy(this, sourceViewer);
+// fFormatter.setFormattingStrategy(fFormattingStrategy, HTML_DEFAULT);
+// fFormatter.enablePartitionAwareFormatting(false);
+// fFormatter.setPartitionManagingPositionCategories(getConfiguredContentTypes(null));
+// }
+// return fFormatter;
+
if (fFormatter == null) {
- fFormatter = new ContentFormatter();
- fFormattingStrategy = new HTMLFormattingStrategy(this, sourceViewer);
- fFormatter.setFormattingStrategy(fFormattingStrategy, HTML_DEFAULT);
- fFormatter.enablePartitionAwareFormatting(false);
- fFormatter.setPartitionManagingPositionCategories(getConfiguredContentTypes(null));
+ //ContentFormatter
+ fFormatter= new ContentFormatter();
+ IFormattingStrategy strategy= new JavaFormattingStrategy(sourceViewer);
+
+ fFormatter.setFormattingStrategy(strategy, IDocument.DEFAULT_CONTENT_TYPE);
+ fFormatter.enablePartitionAwareFormatting(false);
+ fFormatter.setPartitionManagingPositionCategories(getPartitionManagingPositionCategories());
}
return fFormatter;
}
+ /**
+ * Returns the names of the document position categories used by the document
+ * partitioners created by this object to manage their partition information.
+ * If the partitioners don't use document position categories, the returned
+ * result is <code>null</code>.
+ *
+ * @return the partition managing position categories or <code>null</code>
+ * if there is none
+ */
+ public String[] getPartitionManagingPositionCategories() {
+ return new String[] { DefaultPartitioner.CONTENT_TYPES_CATEGORY };
+ }
// /**
// * Returns the names of the document position categories used by the document
// * partitioners created by this object to manage their partition information.
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.phpeclipse.phpdt.internal.formatter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.ICodeFormatter;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.ConfigurableOption;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+import org.phpeclipse.phpdt.internal.formatter.impl.FormatterOptions;
+import org.phpeclipse.phpdt.internal.formatter.impl.SplitLine;
+
+/** <h2>How to format a piece of code ?</h2>
+ * <ul><li>Create an instance of <code>CodeFormatter</code>
+ * <li>Use the method <code>void format(aString)</code>
+ * on this instance to format <code>aString</code>.
+ * It will return the formatted string.</ul>
+*/
+public class CodeFormatter implements ITerminalSymbols, ICodeFormatter {
+
+ public FormatterOptions options;
+
+ /**
+ * Represents a block in the <code>constructions</code> stack.
+ */
+ public static final int BLOCK = ITerminalSymbols.TokenNameLBRACE;
+
+ /**
+ * Represents a block following a control statement in the <code>constructions</code> stack.
+ */
+ public static final int NONINDENT_BLOCK = -100;
+
+ /**
+ * Contains the formatted output.
+ */
+ StringBuffer formattedSource;
+
+ /**
+ * Contains the current line.<br>
+ * Will be dumped at the next "newline"
+ */
+ StringBuffer currentLineBuffer;
+
+ /**
+ * Used during the formatting to get each token.
+ */
+ Scanner scanner;
+
+ /**
+ * Contains the tokens responsible for the current indentation level
+ * and the blocks not closed yet.
+ */
+ private int[] constructions;
+
+ /**
+ * Index in the <code>constructions</code> array.
+ */
+ private int constructionsCount;
+
+ /**
+ * Level of indentation of the current token (number of tab char put in front of it).
+ */
+ private int indentationLevel;
+
+ /**
+ * Regular level of indentation of all the lines
+ */
+ private int initialIndentationLevel;
+
+ /**
+ * Used to split a line.
+ */
+ Scanner splitScanner;
+
+ /**
+ * To remember the offset between the beginning of the line and the
+ * beginning of the comment.
+ */
+ int currentCommentOffset;
+ int currentLineIndentationLevel;
+ int maxLineSize = 30;
+ private boolean containsOpenCloseBraces;
+ private int indentationLevelForOpenCloseBraces;
+
+ /**
+ * Collections of positions to map
+ */
+ private int[] positionsToMap;
+
+ /**
+ * Collections of mapped positions
+ */
+ private int[] mappedPositions;
+
+ private int indexToMap;
+
+ private int indexInMap;
+
+ private int globalDelta;
+
+ private int lineDelta;
+
+ private int splitDelta;
+
+ private int beginningOfLineIndex;
+
+ private int multipleLineCommentCounter;
+
+ /**
+ * Creates a new instance of Code Formatter using the given settings.
+ *
+ * @deprecated backport 1.0 internal functionality
+ */
+ public CodeFormatter(ConfigurableOption[] settings) {
+ this(convertConfigurableOptions(settings));
+ }
+
+ /**
+ * Creates a new instance of Code Formatter using the FormattingOptions object
+ * given as argument
+ * @deprecated Use CodeFormatter(ConfigurableOption[]) instead
+ */
+ public CodeFormatter() {
+ this((Map)null);
+ }
+ /**
+ * Creates a new instance of Code Formatter using the given settings.
+ */
+ public CodeFormatter(Map settings) {
+
+ // initialize internal state
+ constructionsCount = 0;
+ constructions = new int[10];
+ currentLineIndentationLevel = indentationLevel = initialIndentationLevel;
+ currentCommentOffset = -1;
+
+ // initialize primary and secondary scanners
+ scanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/); // regular scanner for forming lines
+ scanner.recordLineSeparator = true;
+
+ // to remind of the position of the beginning of the line.
+ splitScanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/);
+ // secondary scanner to split long lines formed by primary scanning
+
+ // initialize current line buffer
+ currentLineBuffer = new StringBuffer();
+ this.options = new FormatterOptions(settings);
+ }
+
+ /**
+ * Returns true if a lineSeparator has to be inserted before <code>operator</code>
+ * false otherwise.
+ */
+ private static boolean breakLineBeforeOperator(int operator) {
+ switch (operator) {
+ case TokenNameCOMMA :
+ case TokenNameSEMICOLON :
+ case TokenNameEQUAL :
+ return false;
+ default :
+ return true;
+ }
+ }
+
+ /**
+ * @deprecated backport 1.0 internal functionality
+ */
+ private static Map convertConfigurableOptions(ConfigurableOption[] settings) {
+ Hashtable options = new Hashtable(10);
+
+ for (int i = 0; i < settings.length; i++) {
+ if(settings[i].getComponentName().equals(CodeFormatter.class.getName())){
+ String optionName = settings[i].getOptionName();
+ int valueIndex = settings[i].getCurrentValueIndex();
+
+ if(optionName.equals("newline.openingBrace")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.newline.openingBrace", valueIndex == 0 ? "insert" : "do not insert"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("newline.controlStatement")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.newline.controlStatement", valueIndex == 0 ? "insert" : "do not insert"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("newline.clearAll")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.newline.clearAll", valueIndex == 0 ? "clear all" : "preserve one"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("newline.elseIf")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.newline.elseIf", valueIndex == 0 ? "do not insert" : "insert" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("newline.emptyBlock")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.newline.emptyBlock", valueIndex == 0 ? "insert" : "do not insert"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("lineSplit")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.lineSplit", String.valueOf(valueIndex)); //$NON-NLS-1$ //$NON-NLS-2$
+
+ } else if(optionName.equals("style.assignment")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.style.assignment", valueIndex == 0 ? "compact" : "normal"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("tabulation.char")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.tabulation.char", valueIndex == 0 ? "tab" : "space"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ } else if(optionName.equals("tabulation.size")) { //$NON-NLS-1$
+ options.put("org.phpeclipse.phpdt.core.formatter.tabulation.size", String.valueOf(valueIndex)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+
+ return options;
+ }
+
+ /**
+ * Returns the end of the source code.
+ */
+ private final String copyRemainingSource() {
+ char str[] = scanner.source;
+ int startPosition = scanner.startPosition;
+ int length = str.length - startPosition;
+ StringBuffer bufr = new StringBuffer(length);
+ if (startPosition < str.length) {
+ bufr.append(str, startPosition, length);
+ }
+ return (bufr.toString());
+ }
+
+ /**
+ * Inserts <code>tabCount</code> tab character or their equivalent number of spaces.
+ */
+ private void dumpTab(int tabCount) {
+ if (options.indentWithTab) {
+ for (int j = 0; j < tabCount; j++) {
+ formattedSource.append('\t');
+ increaseSplitDelta(1);
+ }
+ } else {
+ for (int i = 0, max = options.tabSize * tabCount; i < max; i++) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ }
+ }
+
+ /**
+ * Dumps <code>currentLineBuffer</code> into the formatted string.
+ */
+ private void flushBuffer() {
+ String currentString = currentLineBuffer.toString();
+ splitDelta = 0;
+ beginningOfLineIndex = formattedSource.length();
+ if (containsOpenCloseBraces) {
+ containsOpenCloseBraces = false;
+ outputLine(
+ currentString,
+ false,
+ indentationLevelForOpenCloseBraces,
+ 0,
+ -1,
+ null,
+ 0);
+ indentationLevelForOpenCloseBraces = currentLineIndentationLevel;
+ } else {
+ outputLine(currentString, false, currentLineIndentationLevel, 0, -1, null, 0);
+ }
+ int scannerSourceLength = scanner.source.length;
+ if (scannerSourceLength > 2) {
+ if (scanner.source[scannerSourceLength - 1] == '\n' &&
+ scanner.source[scannerSourceLength - 2] == '\r') {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 2);
+ } else if (scanner.source[scannerSourceLength - 1] == '\n') {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ } else if (scanner.source[scannerSourceLength - 1] == '\r') {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ }
+ }
+ updateMappedPositions(scanner.startPosition);
+ }
+
+ /**
+ * Formats the input string.
+ */
+ private void format() {
+ int token = 0;
+ int previousToken = 0;
+ int previousCompilableToken = 0;
+ int indentationOffset = 0;
+ int newLinesInWhitespace = 0;
+
+ // number of new lines in the previous whitespace token
+ // (used to leave blank lines before comments)
+ int pendingNewLines = 0;
+ boolean expectingOpenBrace = false;
+ boolean clearNonBlockIndents = false;
+ // true if all indentations till the 1st { (usefull after } or ;)
+ boolean pendingSpace = true;
+ boolean pendingNewlineAfterParen = false;
+ // true when a cr is to be put after a ) (in conditional statements)
+ boolean inAssignment = false;
+ boolean inArrayAssignment = false;
+ boolean inThrowsClause = false;
+ boolean inClassOrInterfaceHeader = false;
+
+ // openBracketCount is used to count the number of open brackets not closed yet.
+ int openBracketCount = 0;
+ int unarySignModifier = 0;
+
+ // openParenthesis[0] is used to count the parenthesis not belonging to a condition
+ // (eg foo();). parenthesis in for (...) are count elsewhere in the array.
+ int openParenthesisCount = 1;
+ int[] openParenthesis = new int[10];
+
+ // tokenBeforeColon is used to know what token goes along with the current :
+ // it can be case or ?
+ int tokenBeforeColonCount = 0;
+ int[] tokenBeforeColon = new int[10];
+
+ constructionsCount = 0; // initializes the constructions count.
+
+ // contains DO if in a DO..WHILE statement, UNITIALIZED otherwise.
+ int nlicsToken = 0;
+
+ // fix for 1FF17XY: LFCOM:ALL - Format problem on not matching } and else
+ boolean specialElse = false;
+
+ // OPTION (IndentationLevel): initial indentation level may be non-zero.
+ currentLineIndentationLevel += constructionsCount;
+
+ // An InvalidInputException exception might cause the termination of this loop.
+ try {
+ while (true) {
+ // Get the next token. Catch invalid input and output it
+ // with minimal formatting, also catch end of input and
+ // exit the loop.
+ try {
+ token = scanner.getNextToken();
+
+ // Patch for line comment
+ // See PR http://dev.eclipse.org/bugs/show_bug.cgi?id=23096
+ if (token == ITerminalSymbols.TokenNameCOMMENT_LINE) {
+ int length = scanner.currentPosition;
+ loop: for (int index = length - 1; index >= 0; index--) {
+ switch(scanner.source[index]) {
+ case '\r' :
+ case '\n' :
+ scanner.currentPosition--;
+ break;
+ default:
+ break loop;
+ }
+ }
+ }
+ } catch (InvalidInputException e) {
+ if (!handleInvalidToken(e)) {
+ throw e;
+ }
+ token = 0;
+ }
+ if (token == Scanner.TokenNameEOF)
+ break;
+
+ /* ## MODIFYING the indentation level before generating new lines
+ and indentation in the output string
+ */
+
+ // Removes all the indentations made by statements not followed by a block
+ // except if the current token is ELSE, CATCH or if we are in a switch/case
+ if (clearNonBlockIndents && (token != Scanner.TokenNameWHITESPACE)) {
+ switch (token) {
+ case TokenNameelse :
+ if (constructionsCount > 0
+ && constructions[constructionsCount - 1] == TokenNameelse) {
+ pendingNewLines = 1;
+ specialElse = true;
+ }
+ indentationLevel += popInclusiveUntil(TokenNameif);
+ break;
+// case TokenNamecatch :
+// indentationLevel += popInclusiveUntil(TokenNamecatch);
+// break;
+// case TokenNamefinally :
+// indentationLevel += popInclusiveUntil(TokenNamecatch);
+// break;
+ case TokenNamewhile :
+ if (nlicsToken == TokenNamedo) {
+ indentationLevel += pop(TokenNamedo);
+ break;
+ }
+ default :
+ indentationLevel += popExclusiveUntilBlockOrCase();
+ // clear until a CASE, DEFAULT or BLOCK is encountered.
+ // Thus, the indentationLevel is correctly cleared either
+ // in a switch/case statement or in any other situation.
+ }
+ clearNonBlockIndents = false;
+ }
+ // returns to the indentation level created by the SWITCH keyword
+ // if the current token is a CASE or a DEFAULT
+ if (token == TokenNamecase || token == TokenNamedefault) {
+ indentationLevel += pop(TokenNamecase);
+ }
+// if (token == Scanner.TokenNamethrows) {
+// inThrowsClause = true;
+// }
+ if ((token == Scanner.TokenNameclass
+ // || token == Scanner.TokenNameinterface
+ ) && previousToken != Scanner.TokenNameDOT) {
+ inClassOrInterfaceHeader = true;
+ }
+
+ /* ## APPEND newlines and indentations to the output string
+ */
+ // Do not add a new line between ELSE and IF, if the option elseIfOnSameLine is true.
+ // Fix for 1ETLWPZ: IVJCOM:ALL - incorrect "else if" formatting
+ if (pendingNewlineAfterParen
+ && previousCompilableToken == TokenNameelse
+ && token == TokenNameif
+ && options.compactElseIfMode) {
+ pendingNewlineAfterParen = false;
+ pendingNewLines = 0;
+ indentationLevel += pop(TokenNameelse);
+ // because else if is now one single statement,
+ // the indentation level after it is increased by one and not by 2
+ // (else = 1 indent, if = 1 indent, but else if = 1 indent, not 2).
+ }
+ // Add a newline & indent to the formatted source string if
+ // a for/if-else/while statement was scanned and there is no block
+ // following it.
+ pendingNewlineAfterParen =
+ pendingNewlineAfterParen
+ || (previousCompilableToken == TokenNameRPAREN && token == TokenNameLBRACE);
+ if (pendingNewlineAfterParen && token != Scanner.TokenNameWHITESPACE) {
+ pendingNewlineAfterParen = false;
+
+ // Do to add a newline & indent sequence if the current token is an
+ // open brace or a period or if the current token is a semi-colon and the
+ // previous token is a close paren.
+ // add a new line if a parenthesis belonging to a for() statement
+ // has been closed and the current token is not an opening brace
+ if (token != TokenNameLBRACE
+ && !isComment(token) // to avoid adding new line between else and a comment
+ && token != TokenNameDOT
+ && !(previousCompilableToken == TokenNameRPAREN && token == TokenNameSEMICOLON)) {
+ newLine(1);
+ currentLineIndentationLevel = indentationLevel;
+ pendingNewLines = 0;
+ pendingSpace = false;
+ } else {
+ if (token == TokenNameLBRACE && options.newLineBeforeOpeningBraceMode) {
+ newLine(1);
+ if (constructionsCount > 0
+ && constructions[constructionsCount - 1] != BLOCK
+ && constructions[constructionsCount - 1] != NONINDENT_BLOCK) {
+ currentLineIndentationLevel = indentationLevel - 1;
+ } else {
+ currentLineIndentationLevel = indentationLevel;
+ }
+ pendingNewLines = 0;
+ pendingSpace = false;
+ }
+ }
+ }
+ if (token == TokenNameLBRACE
+ && options.newLineBeforeOpeningBraceMode
+ && constructionsCount > 0
+ && constructions[constructionsCount - 1] == TokenNamedo) {
+ newLine(1);
+ currentLineIndentationLevel = indentationLevel - 1;
+ pendingNewLines = 0;
+ pendingSpace = false;
+ }
+ // see PR 1G5G8EC
+ if (token == TokenNameLBRACE && inThrowsClause) {
+ inThrowsClause = false;
+ if (options.newLineBeforeOpeningBraceMode) {
+ newLine(1);
+ currentLineIndentationLevel = indentationLevel;
+ pendingNewLines = 0;
+ pendingSpace = false;
+ }
+ }
+ // see PR 1G5G82G
+ if (token == TokenNameLBRACE && inClassOrInterfaceHeader) {
+ inClassOrInterfaceHeader = false;
+ if (options.newLineBeforeOpeningBraceMode) {
+ newLine(1);
+ currentLineIndentationLevel = indentationLevel;
+ pendingNewLines = 0;
+ pendingSpace = false;
+ }
+ }
+ // Add pending new lines to the formatted source string.
+ // Note: pending new lines are not added if the current token
+ // is a single line comment or whitespace.
+ // if the comment is between parenthesis, there is no blank line preservation
+ // (if it's a one-line comment, a blank line is added after it).
+ if (((pendingNewLines > 0 && (!isComment(token)))
+ || (newLinesInWhitespace > 0 && (openParenthesisCount <= 1 && isComment(token)))
+ || (previousCompilableToken == TokenNameLBRACE && token == TokenNameRBRACE))
+ && token != Scanner.TokenNameWHITESPACE) {
+
+ // Do not add newline & indent between an adjoining close brace and
+ // close paren. Anonymous inner classes may use this form.
+ boolean closeBraceAndCloseParen =
+ previousToken == TokenNameRBRACE && token == TokenNameRPAREN;
+
+ // OPTION (NewLineInCompoundStatement): do not add newline & indent
+ // between close brace and else, (do) while, catch, and finally if
+ // newlineInCompoundStatement is true.
+ boolean nlicsOption =
+ previousToken == TokenNameRBRACE
+ && !options.newlineInControlStatementMode
+ && (token == TokenNameelse
+ || (token == TokenNamewhile && nlicsToken == TokenNamedo));
+// || token == TokenNamecatch
+// || token == TokenNamefinally);
+
+ // Do not add a newline & indent between a close brace and semi-colon.
+ boolean semiColonAndCloseBrace =
+ previousToken == TokenNameRBRACE && token == TokenNameSEMICOLON;
+
+ // Do not add a new line & indent between a multiline comment and a opening brace
+ boolean commentAndOpenBrace =
+ previousToken == Scanner.TokenNameCOMMENT_BLOCK && token == TokenNameLBRACE;
+
+ // Do not add a newline & indent between a close brace and a colon (in array assignments, for example).
+ boolean commaAndCloseBrace =
+ previousToken == TokenNameRBRACE && token == TokenNameCOMMA;
+
+ // Add a newline and indent, if appropriate.
+ if (specialElse
+ || (!commentAndOpenBrace
+ && !closeBraceAndCloseParen
+ && !nlicsOption
+ && !semiColonAndCloseBrace
+ && !commaAndCloseBrace)) {
+
+ // if clearAllBlankLinesMode=false, leaves the blank lines
+ // inserted by the user
+ // if clearAllBlankLinesMode=true, removes all of then
+ // and insert only blank lines required by the formatting.
+ if (!options.clearAllBlankLinesMode) {
+ // (isComment(token))
+ pendingNewLines =
+ (pendingNewLines < newLinesInWhitespace)
+ ? newLinesInWhitespace
+ : pendingNewLines;
+ pendingNewLines = (pendingNewLines > 2) ? 2 : pendingNewLines;
+ }
+ if (previousCompilableToken == TokenNameLBRACE && token == TokenNameRBRACE) {
+ containsOpenCloseBraces = true;
+ indentationLevelForOpenCloseBraces = currentLineIndentationLevel;
+ if (isComment(previousToken)) {
+ newLine(pendingNewLines);
+ } else {
+ /* if (!(constructionsCount > 1
+ && constructions[constructionsCount-1] == NONINDENT_BLOCK
+ && (constructions[constructionsCount-2] == TokenNamefor
+ || constructions[constructionsCount-2] == TokenNamewhile))) {*/
+ if (options.newLineInEmptyBlockMode) {
+ if (inArrayAssignment) {
+ newLine(1); // array assigment with an empty block
+ } else {
+ newLine(pendingNewLines);
+ }
+ }
+ // }
+ }
+ } else {
+ // see PR 1FKKC3U: LFCOM:WINNT - Format problem with a comment before the ';'
+ if (!((previousToken == Scanner.TokenNameCOMMENT_BLOCK
+ || previousToken == Scanner.TokenNameCOMMENT_PHPDOC)
+ && token == TokenNameSEMICOLON)) {
+ newLine(pendingNewLines);
+ }
+ }
+ if (((previousCompilableToken == TokenNameSEMICOLON)
+ || (previousCompilableToken == TokenNameLBRACE)
+ || (previousCompilableToken == TokenNameRBRACE)
+ || (isComment(previousToken)))
+ && (token == TokenNameRBRACE)) {
+ indentationOffset = -1;
+ indentationLevel += popExclusiveUntilBlock();
+ }
+ if (previousToken == Scanner.TokenNameCOMMENT_LINE && inAssignment) {
+ // PR 1FI5IPO
+ currentLineIndentationLevel++;
+ } else {
+ currentLineIndentationLevel = indentationLevel + indentationOffset;
+ }
+ pendingSpace = false;
+ indentationOffset = 0;
+ }
+ pendingNewLines = 0;
+ newLinesInWhitespace = 0;
+ specialElse = false;
+
+ if (nlicsToken == TokenNamedo && token == TokenNamewhile) {
+ nlicsToken = 0;
+ }
+ }
+ switch (token) {
+ case TokenNameelse :
+ // case TokenNamefinally :
+ expectingOpenBrace = true;
+ pendingNewlineAfterParen = true;
+ indentationLevel += pushControlStatement(token);
+ break;
+ case TokenNamecase :
+ case TokenNamedefault :
+ if (tokenBeforeColonCount == tokenBeforeColon.length) {
+ System.arraycopy(
+ tokenBeforeColon,
+ 0,
+ (tokenBeforeColon = new int[tokenBeforeColonCount * 2]),
+ 0,
+ tokenBeforeColonCount);
+ }
+ tokenBeforeColon[tokenBeforeColonCount++] = TokenNamecase;
+ indentationLevel += pushControlStatement(TokenNamecase);
+ break;
+ case TokenNameQUESTION :
+ if (tokenBeforeColonCount == tokenBeforeColon.length) {
+ System.arraycopy(
+ tokenBeforeColon,
+ 0,
+ (tokenBeforeColon = new int[tokenBeforeColonCount * 2]),
+ 0,
+ tokenBeforeColonCount);
+ }
+ tokenBeforeColon[tokenBeforeColonCount++] = token;
+ break;
+ case TokenNameswitch :
+ case TokenNamefor :
+ case TokenNameif :
+ case TokenNamewhile :
+ if (openParenthesisCount == openParenthesis.length) {
+ System.arraycopy(
+ openParenthesis,
+ 0,
+ (openParenthesis = new int[openParenthesisCount * 2]),
+ 0,
+ openParenthesisCount);
+ }
+ openParenthesis[openParenthesisCount++] = 0;
+ expectingOpenBrace = true;
+
+ indentationLevel += pushControlStatement(token);
+ break;
+// case TokenNametry :
+// pendingNewlineAfterParen = true;
+// case TokenNamecatch :
+// // several CATCH statements can be contiguous.
+// // a CATCH is encountered pop until first CATCH (if a CATCH follows a TRY it works the same way,
+// // as CATCH and TRY are the same token in the stack).
+// expectingOpenBrace = true;
+// indentationLevel += pushControlStatement(TokenNamecatch);
+// break;
+
+ case TokenNamedo :
+ expectingOpenBrace = true;
+ indentationLevel += pushControlStatement(token);
+ nlicsToken = token;
+ break;
+ case TokenNamenew :
+ break;
+ case TokenNameLPAREN :
+// if (previousToken == TokenNamesynchronized) {
+// indentationLevel += pushControlStatement(previousToken);
+// } else {
+ // Put a space between the previous and current token if the
+ // previous token was not a keyword, open paren, logical
+ // compliment (eg: !), semi-colon, open brace, close brace,
+ // super, or this.
+ if (previousCompilableToken != TokenNameLBRACKET
+ && previousToken != TokenNameIdentifier
+ && previousToken != 0
+ && previousToken != TokenNameNOT
+ && previousToken != TokenNameLPAREN
+ && previousToken != TokenNameTWIDDLE
+ && previousToken != TokenNameSEMICOLON
+ && previousToken != TokenNameLBRACE
+ && previousToken != TokenNameRBRACE) {
+// && previousToken != TokenNamesuper
+// && previousToken != TokenNamethis) {
+ space();
+ }
+ // If in a for/if/while statement, increase the parenthesis count
+ // for the current openParenthesisCount
+ // else increase the count for stand alone parenthesis.
+ if (openParenthesisCount > 0)
+ openParenthesis[openParenthesisCount - 1]++;
+ else
+ openParenthesis[0]++;
+
+ pendingSpace = false;
+ //S }
+ break;
+ case TokenNameRPAREN :
+
+ // Decrease the parenthesis count
+ // if there is no more unclosed parenthesis,
+ // a new line and indent may be append (depending on the next token).
+ if ((openParenthesisCount > 1)
+ && (openParenthesis[openParenthesisCount - 1] > 0)) {
+ openParenthesis[openParenthesisCount - 1]--;
+ if (openParenthesis[openParenthesisCount - 1] <= 0) {
+ pendingNewlineAfterParen = true;
+ inAssignment = false;
+ openParenthesisCount--;
+ }
+ } else {
+ openParenthesis[0]--;
+ }
+ pendingSpace = false;
+ break;
+ case TokenNameLBRACE :
+ if ((previousCompilableToken == TokenNameRBRACKET)
+ || (previousCompilableToken == TokenNameEQUAL)) {
+ // if (previousCompilableToken == TokenNameRBRACKET) {
+ inArrayAssignment = true;
+ inAssignment = false;
+ }
+ if (inArrayAssignment) {
+ indentationLevel += pushBlock();
+ } else {
+ // Add new line and increase indentation level after open brace.
+ pendingNewLines = 1;
+ indentationLevel += pushBlock();
+ }
+ break;
+ case TokenNameRBRACE :
+ if (previousCompilableToken == TokenNameRPAREN) {
+ pendingSpace = false;
+ }
+ if (inArrayAssignment) {
+ inArrayAssignment = false;
+ pendingNewLines = 1;
+ indentationLevel += popInclusiveUntilBlock();
+ } else {
+ pendingNewLines = 1;
+ indentationLevel += popInclusiveUntilBlock();
+
+ if (previousCompilableToken == TokenNameRPAREN) {
+ // fix for 1FGDDV6: LFCOM:WIN98 - Weird splitting on message expression
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ increaseLineDelta(options.lineSeparatorSequence.length);
+ }
+ if (constructionsCount > 0) {
+ switch (constructions[constructionsCount - 1]) {
+ case TokenNamefor :
+ //indentationLevel += popExclusiveUntilBlock();
+ //break;
+ case TokenNameswitch :
+ case TokenNameif :
+ case TokenNameelse :
+// case TokenNametry :
+// case TokenNamecatch :
+// case TokenNamefinally :
+ case TokenNamewhile :
+ case TokenNamedo :
+// case TokenNamesynchronized :
+ clearNonBlockIndents = true;
+ default :
+ break;
+ }
+ }
+ }
+ break;
+ case TokenNameLBRACKET :
+ openBracketCount++;
+ pendingSpace = false;
+ break;
+ case TokenNameRBRACKET :
+ openBracketCount -= (openBracketCount > 0) ? 1 : 0;
+ // if there is no left bracket to close, the right bracket is ignored.
+ pendingSpace = false;
+ break;
+ case TokenNameCOMMA :
+ case TokenNameDOT :
+ pendingSpace = false;
+ break;
+ case TokenNameSEMICOLON :
+
+ // Do not generate line terminators in the definition of
+ // the for statement.
+ // if not in this case, jump a line and reduce indentation after the brace
+ // if the block it closes belongs to a conditional statement (if, while, do...).
+ if (openParenthesisCount <= 1) {
+ pendingNewLines = 1;
+ if (expectingOpenBrace) {
+ clearNonBlockIndents = true;
+ expectingOpenBrace = false;
+ }
+ }
+ inAssignment = false;
+ pendingSpace = false;
+ break;
+ case TokenNamePLUS_PLUS :
+ case TokenNameMINUS_MINUS :
+
+ // Do not put a space between a post-increment/decrement
+ // and the identifier being modified.
+ if (previousToken == TokenNameIdentifier
+ || previousToken == TokenNameRBRACKET) {
+ pendingSpace = false;
+ }
+ break;
+ case TokenNamePLUS : // previously ADDITION
+ case TokenNameMINUS :
+
+ // Handle the unary operators plus and minus via a flag
+ if (!isLiteralToken(previousToken)
+ && previousToken != TokenNameIdentifier
+ && previousToken != TokenNameRPAREN
+ && previousToken != TokenNameRBRACKET) {
+ unarySignModifier = 1;
+ }
+ break;
+ case TokenNameCOLON :
+ // In a switch/case statement, add a newline & indent
+ // when a colon is encountered.
+ if (tokenBeforeColonCount > 0) {
+ if (tokenBeforeColon[tokenBeforeColonCount - 1] == TokenNamecase) {
+ pendingNewLines = 1;
+ }
+ tokenBeforeColonCount--;
+ }
+ break;
+ case TokenNameEQUAL :
+ inAssignment = true;
+ break;
+ case Scanner.TokenNameCOMMENT_LINE :
+ pendingNewLines = 1;
+ if (inAssignment) {
+ currentLineIndentationLevel++;
+ }
+ break; // a line is always inserted after a one-line comment
+ case Scanner.TokenNameCOMMENT_PHPDOC :
+ case Scanner.TokenNameCOMMENT_BLOCK :
+ currentCommentOffset = getCurrentCommentOffset();
+ pendingNewLines = 1;
+ break;
+ case Scanner.TokenNameWHITESPACE :
+
+ // Count the number of line terminators in the whitespace so
+ // line spacing can be preserved near comments.
+ char[] source = scanner.source;
+ newLinesInWhitespace = 0;
+ for (int i = scanner.startPosition, max = scanner.currentPosition;
+ i < max;
+ i++) {
+ if (source[i] == '\r') {
+ if (i < max - 1) {
+ if (source[++i] == '\n') {
+ newLinesInWhitespace++;
+ } else {
+ newLinesInWhitespace++;
+ }
+ } else {
+ newLinesInWhitespace++;
+ }
+ } else if (source[i] == '\n') {
+ newLinesInWhitespace++;
+ }
+ }
+ increaseLineDelta(scanner.startPosition - scanner.currentPosition);
+ break;
+ default :
+ if ((token == TokenNameIdentifier)
+ || isLiteralToken(token)) {
+// || token == TokenNamesuper
+// || token == TokenNamethis) {
+
+ // Do not put a space between a unary operator
+ // (eg: ++, --, +, -) and the identifier being modified.
+ if (previousToken == TokenNamePLUS_PLUS
+ || previousToken == TokenNameMINUS_MINUS
+ || (previousToken == TokenNamePLUS && unarySignModifier > 0)
+ || (previousToken == TokenNameMINUS && unarySignModifier > 0)) {
+ pendingSpace = false;
+ }
+ unarySignModifier = 0;
+ }
+ break;
+ }
+ // Do not output whitespace tokens.
+ if (token != Scanner.TokenNameWHITESPACE) {
+
+ /* Add pending space to the formatted source string.
+ Do not output a space under the following circumstances:
+ 1) this is the first pass
+ 2) previous token is an open paren
+ 3) previous token is a period
+ 4) previous token is the logical compliment (eg: !)
+ 5) previous token is the bitwise compliment (eg: ~)
+ 6) previous token is the open bracket (eg: [)
+ 7) in an assignment statement, if the previous token is an
+ open brace or the current token is a close brace
+ 8) previous token is a single line comment
+ */
+ boolean openAndCloseBrace =
+ previousCompilableToken == TokenNameLBRACE && token == TokenNameRBRACE;
+
+ if (pendingSpace
+ && insertSpaceAfter(previousToken)
+ && !(inAssignment
+ && (previousToken == TokenNameLBRACE || token == TokenNameRBRACE))
+ && previousToken != Scanner.TokenNameCOMMENT_LINE) {
+ if ((!(options.compactAssignmentMode && token == TokenNameEQUAL))
+ && !openAndCloseBrace)
+ space();
+ }
+ // Add the next token to the formatted source string.
+ outputCurrentToken(token);
+ if (token == Scanner.TokenNameCOMMENT_LINE && openParenthesisCount > 1) {
+ pendingNewLines = 0;
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ increaseLineDelta(options.lineSeparatorSequence.length);
+ }
+ pendingSpace = true;
+ }
+ // Whitespace tokens do not need to be remembered.
+ if (token != Scanner.TokenNameWHITESPACE) {
+ previousToken = token;
+ if (token != Scanner.TokenNameCOMMENT_BLOCK
+ && token != Scanner.TokenNameCOMMENT_LINE
+ && token != Scanner.TokenNameCOMMENT_PHPDOC) {
+ previousCompilableToken = token;
+ }
+ }
+ }
+ output(copyRemainingSource());
+ flushBuffer(); // dump the last token of the source in the formatted output.
+ } catch (InvalidInputException e) {
+ output(copyRemainingSource());
+ flushBuffer(); // dump the last token of the source in the formatted output.
+ }
+ }
+
+ /**
+ * Formats the char array <code>sourceString</code>,
+ * and returns a string containing the formatted version.
+ * @return the formatted ouput.
+ */
+ public String formatSourceString(String sourceString) {
+ char[] sourceChars = sourceString.toCharArray();
+ formattedSource = new StringBuffer(sourceChars.length);
+ scanner.setSource(sourceChars);
+ format();
+ return formattedSource.toString();
+ }
+
+ /**
+ * Formats the char array <code>sourceString</code>,
+ * and returns a string containing the formatted version.
+ * @param string the string to format
+ * @param indentationLevel the initial indentation level
+ * @return the formatted ouput.
+ */
+ public String format(String string, int indentationLevel) {
+ return format(string, indentationLevel, (int[])null);
+ }
+
+ /**
+ * Formats the char array <code>sourceString</code>,
+ * and returns a string containing the formatted version.
+ * The positions array is modified to contain the mapped positions.
+ * @param string the string to format
+ * @param indentationLevel the initial indentation level
+ * @param positions the array of positions to map
+ * @return the formatted ouput.
+ */
+ public String format(String string, int indentationLevel, int[] positions) {
+ return this.format(string, indentationLevel, positions, null);
+ }
+
+ public String format(String string, int indentationLevel, int[] positions, String lineSeparator) {
+ if (lineSeparator != null){
+ this.options.setLineSeparator(lineSeparator);
+ }
+ if (positions != null) {
+ this.setPositionsToMap(positions);
+ this.setInitialIndentationLevel(indentationLevel);
+ String formattedString = this.formatSourceString(string);
+ int[] mappedPositions = this.getMappedPositions();
+ System.arraycopy(mappedPositions, 0, positions, 0, positions.length);
+ return formattedString;
+ } else {
+ this.setInitialIndentationLevel(indentationLevel);
+ return this.formatSourceString(string);
+ }
+ }
+ /**
+ * Formats the char array <code>sourceString</code>,
+ * and returns a string containing the formatted version. The initial indentation level is 0.
+ * @param string the string to format
+ * @return the formatted ouput.
+ */
+ public String format(String string) {
+ return this.format(string, 0, (int[])null);
+ }
+
+ /**
+ * Formats a given source string, starting indenting it at a particular
+ * depth and using the given options
+ *
+ * @deprecated backport 1.0 internal functionality
+ */
+ public static String format(String sourceString, int initialIndentationLevel, ConfigurableOption[] options) {
+ CodeFormatter formatter = new CodeFormatter(options);
+ formatter.setInitialIndentationLevel(initialIndentationLevel);
+ return formatter.formatSourceString(sourceString);
+ }
+
+ /**
+ * Returns the number of characters and tab char between the beginning of the line
+ * and the beginning of the comment.
+ */
+ private int getCurrentCommentOffset() {
+ int linePtr = scanner.linePtr;
+ // if there is no beginning of line, return 0.
+ if (linePtr < 0)
+ return 0;
+ int offset = 0;
+ int beginningOfLine = scanner.lineEnds[linePtr];
+ int currentStartPosition = scanner.startPosition;
+ char[] source = scanner.source;
+
+ // find the position of the beginning of the line containing the comment
+ while (beginningOfLine > currentStartPosition) {
+ if (linePtr > 0) {
+ beginningOfLine = scanner.lineEnds[--linePtr];
+ } else {
+ beginningOfLine = 0;
+ break;
+ }
+ }
+ for (int i = currentStartPosition - 1; i >= beginningOfLine ; i--) {
+ char currentCharacter = source[i];
+ switch (currentCharacter) {
+ case '\t' :
+ offset += options.tabSize;
+ break;
+ case ' ' :
+ offset++;
+ break;
+ case '\r' :
+ case '\n' :
+ break;
+ default:
+ return offset;
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Returns an array of descriptions for the configurable options.
+ * The descriptions may be changed and passed back to a different
+ * compiler.
+ *
+ * @deprecated backport 1.0 internal functionality
+ */
+ public static ConfigurableOption[] getDefaultOptions(Locale locale) {
+ String componentName = CodeFormatter.class.getName();
+ FormatterOptions options = new FormatterOptions();
+ return new ConfigurableOption[] {
+ new ConfigurableOption(componentName, "newline.openingBrace", locale, options.newLineBeforeOpeningBraceMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "newline.controlStatement", locale, options.newlineInControlStatementMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "newline.clearAll", locale, options.clearAllBlankLinesMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "newline.elseIf", locale, options.compactElseIfMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "newline.emptyBlock", locale, options.newLineInEmptyBlockMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "line.split", locale, options.maxLineLength),//$NON-NLS-1$
+ new ConfigurableOption(componentName, "style.compactAssignment", locale, options.compactAssignmentMode ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "tabulation.char", locale, options.indentWithTab ? 0 : 1), //$NON-NLS-1$
+ new ConfigurableOption(componentName, "tabulation.size", locale, options.tabSize) //$NON-NLS-1$
+ };
+ }
+
+ /**
+ * Returns the array of mapped positions.
+ * Returns null is no positions have been set.
+ * @return int[]
+ * @deprecated There is no need to retrieve the mapped positions anymore.
+ */
+ public int[] getMappedPositions() {
+ return mappedPositions;
+ }
+
+ /**
+ * Returns the priority of the token given as argument<br>
+ * The most prioritary the token is, the smallest the return value is.
+ * @return the priority of <code>token</code>
+ * @param token the token of which the priority is requested
+ */
+ private static int getTokenPriority(int token) {
+ switch (token) {
+ case TokenNameextends :
+// case TokenNameimplements :
+// case TokenNamethrows :
+ return 10;
+ case TokenNameSEMICOLON : // ;
+ return 20;
+ case TokenNameCOMMA : // ,
+ return 25;
+ case TokenNameEQUAL : // =
+ return 30;
+ case TokenNameAND_AND : // &&
+ case TokenNameOR_OR : // ||
+ return 40;
+ case TokenNameQUESTION : // ?
+ case TokenNameCOLON : // :
+ return 50; // it's better cutting on ?: than on ;
+ case TokenNameEQUAL_EQUAL : // ==
+ case TokenNameNOT_EQUAL : // !=
+ return 60;
+ case TokenNameLESS : // <
+ case TokenNameLESS_EQUAL : // <=
+ case TokenNameGREATER : // >
+ case TokenNameGREATER_EQUAL : // >=
+// case TokenNameinstanceof : // instanceof
+ return 70;
+ case TokenNamePLUS : // +
+ case TokenNameMINUS : // -
+ return 80;
+ case TokenNameMULTIPLY : // *
+ case TokenNameDIVIDE : // /
+ case TokenNameREMAINDER : // %
+ return 90;
+ case TokenNameLEFT_SHIFT : // <<
+ case TokenNameRIGHT_SHIFT : // >>
+// case TokenNameUNSIGNED_RIGHT_SHIFT : // >>>
+ return 100;
+ case TokenNameAND : // &
+ case TokenNameOR : // |
+ case TokenNameXOR : // ^
+ return 110;
+ case TokenNameMULTIPLY_EQUAL : // *=
+ case TokenNameDIVIDE_EQUAL : // /=
+ case TokenNameREMAINDER_EQUAL : // %=
+ case TokenNamePLUS_EQUAL : // +=
+ case TokenNameMINUS_EQUAL : // -=
+ case TokenNameLEFT_SHIFT_EQUAL : // <<=
+ case TokenNameRIGHT_SHIFT_EQUAL : // >>=
+// case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>=
+ case TokenNameAND_EQUAL : // &=
+ case TokenNameXOR_EQUAL : // ^=
+ case TokenNameOR_EQUAL : // |=
+ return 120;
+ case TokenNameDOT : // .
+ return 130;
+ default :
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ /**
+ * Handles the exception raised when an invalid token is encountered.
+ * Returns true if the exception has been handled, false otherwise.
+ */
+ private boolean handleInvalidToken(Exception e) {
+ if (e.getMessage().equals(Scanner.INVALID_CHARACTER_CONSTANT)
+ || e.getMessage().equals(Scanner.INVALID_CHAR_IN_STRING)
+ || e.getMessage().equals(Scanner.INVALID_ESCAPE)) {
+ return true;
+ }
+ return false;
+ }
+
+ private final void increaseGlobalDelta(int offset) {
+ globalDelta += offset;
+ }
+
+ private final void increaseLineDelta(int offset) {
+ lineDelta += offset;
+ }
+
+ private final void increaseSplitDelta(int offset) {
+ splitDelta += offset;
+ }
+
+ /**
+ * Returns true if a space has to be inserted after <code>operator</code>
+ * false otherwise.
+ */
+ private boolean insertSpaceAfter(int token) {
+ switch (token) {
+ case TokenNameLPAREN :
+ case TokenNameNOT :
+ case TokenNameTWIDDLE :
+ case TokenNameDOT :
+ case 0 : // no token
+ case TokenNameLBRACKET :
+ case Scanner.TokenNameCOMMENT_LINE :
+ return false;
+ default :
+ return true;
+ }
+ }
+
+ /**
+ * Returns true if a space has to be inserted before <code>operator</code>
+ * false otherwise.<br>
+ * Cannot be static as it uses the code formatter options
+ * (to know if the compact assignment mode is on).
+ */
+ private boolean insertSpaceBefore(int token) {
+ switch (token) {
+ case TokenNameEQUAL :
+ return (!options.compactAssignmentMode);
+ default :
+ return false;
+ }
+ }
+
+ private static boolean isComment(int token) {
+ boolean result =
+ token == Scanner.TokenNameCOMMENT_BLOCK
+ || token == Scanner.TokenNameCOMMENT_LINE
+ || token == Scanner.TokenNameCOMMENT_PHPDOC;
+ return result;
+ }
+
+ private static boolean isLiteralToken(int token) {
+ boolean result =
+ token == TokenNameIntegerLiteral
+ // || token == TokenNameLongLiteral
+ // || token == TokenNameFloatingPointLiteral
+ || token == TokenNameDoubleLiteral
+ // || token == TokenNameCharacterLiteral
+ || token == TokenNameStringLiteral;
+ return result;
+ }
+
+ /**
+ * If the length of <code>oneLineBuffer</code> exceeds <code>maxLineLength</code>,
+ * it is split and the result is dumped in <code>formattedSource</code>
+ * @param newLineCount the number of new lines to append
+ */
+ private void newLine(int newLineCount) {
+
+ // format current line
+ splitDelta = 0;
+ beginningOfLineIndex = formattedSource.length();
+ String currentLine = currentLineBuffer.toString();
+ if (containsOpenCloseBraces) {
+ containsOpenCloseBraces = false;
+ outputLine(
+ currentLine,
+ false,
+ indentationLevelForOpenCloseBraces,
+ 0,
+ -1,
+ null,
+ 0);
+ indentationLevelForOpenCloseBraces = currentLineIndentationLevel;
+ } else {
+ outputLine(currentLine, false, currentLineIndentationLevel, 0, -1, null, 0);
+ }
+ // dump line break(s)
+ for (int i = 0; i < newLineCount; i++) {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseSplitDelta(options.lineSeparatorSequence.length);
+ }
+ // reset formatter for next line
+ int currentLength = currentLine.length();
+ currentLineBuffer =
+ new StringBuffer(
+ currentLength > maxLineSize ? maxLineSize = currentLength : maxLineSize);
+
+ increaseGlobalDelta(splitDelta);
+ increaseGlobalDelta(lineDelta);
+ lineDelta = 0;
+ currentLineIndentationLevel = initialIndentationLevel;
+ }
+
+ private String operatorString(int operator) {
+ switch (operator) {
+ case TokenNameextends :
+ return "extends"; //$NON-NLS-1$
+
+// case TokenNameimplements :
+// return "implements"; //$NON-NLS-1$
+//
+// case TokenNamethrows :
+// return "throws"; //$NON-NLS-1$
+
+ case TokenNameSEMICOLON : // ;
+ return ";"; //$NON-NLS-1$
+
+ case TokenNameCOMMA : // ,
+ return ","; //$NON-NLS-1$
+
+ case TokenNameEQUAL : // =
+ return "="; //$NON-NLS-1$
+
+ case TokenNameAND_AND : // && (15.22)
+ return "&&"; //$NON-NLS-1$
+
+ case TokenNameOR_OR : // || (15.23)
+ return "||"; //$NON-NLS-1$
+
+ case TokenNameQUESTION : // ? (15.24)
+ return "?"; //$NON-NLS-1$
+
+ case TokenNameCOLON : // : (15.24)
+ return ":"; //$NON-NLS-1$
+
+ case TokenNameEQUAL_EQUAL : // == (15.20, 15.20.1, 15.20.2, 15.20.3)
+ return "=="; //$NON-NLS-1$
+
+ case TokenNameNOT_EQUAL : // != (15.20, 15.20.1, 15.20.2, 15.20.3)
+ return "!="; //$NON-NLS-1$
+
+ case TokenNameLESS : // < (15.19.1)
+ return "<"; //$NON-NLS-1$
+
+ case TokenNameLESS_EQUAL : // <= (15.19.1)
+ return "<="; //$NON-NLS-1$
+
+ case TokenNameGREATER : // > (15.19.1)
+ return ">"; //$NON-NLS-1$
+
+ case TokenNameGREATER_EQUAL : // >= (15.19.1)
+ return ">="; //$NON-NLS-1$
+
+// case TokenNameinstanceof : // instanceof
+// return "instanceof"; //$NON-NLS-1$
+
+ case TokenNamePLUS : // + (15.17, 15.17.2)
+ return "+"; //$NON-NLS-1$
+
+ case TokenNameMINUS : // - (15.17.2)
+ return "-"; //$NON-NLS-1$
+
+ case TokenNameMULTIPLY : // * (15.16.1)
+ return "*"; //$NON-NLS-1$
+
+ case TokenNameDIVIDE : // / (15.16.2)
+ return "/"; //$NON-NLS-1$
+
+ case TokenNameREMAINDER : // % (15.16.3)
+ return "%"; //$NON-NLS-1$
+
+ case TokenNameLEFT_SHIFT : // << (15.18)
+ return "<<"; //$NON-NLS-1$
+
+ case TokenNameRIGHT_SHIFT : // >> (15.18)
+ return ">>"; //$NON-NLS-1$
+
+// case TokenNameUNSIGNED_RIGHT_SHIFT : // >>> (15.18)
+// return ">>>"; //$NON-NLS-1$
+
+ case TokenNameAND : // & (15.21, 15.21.1, 15.21.2)
+ return "&"; //$NON-NLS-1$
+
+ case TokenNameOR : // | (15.21, 15.21.1, 15.21.2)
+ return "|"; //$NON-NLS-1$
+
+ case TokenNameXOR : // ^ (15.21, 15.21.1, 15.21.2)
+ return "^"; //$NON-NLS-1$
+
+ case TokenNameMULTIPLY_EQUAL : // *= (15.25.2)
+ return "*="; //$NON-NLS-1$
+
+ case TokenNameDIVIDE_EQUAL : // /= (15.25.2)
+ return "/="; //$NON-NLS-1$
+
+ case TokenNameREMAINDER_EQUAL : // %= (15.25.2)
+ return "%="; //$NON-NLS-1$
+
+ case TokenNamePLUS_EQUAL : // += (15.25.2)
+ return "+="; //$NON-NLS-1$
+
+ case TokenNameMINUS_EQUAL : // -= (15.25.2)
+ return "-="; //$NON-NLS-1$
+
+ case TokenNameLEFT_SHIFT_EQUAL : // <<= (15.25.2)
+ return "<<="; //$NON-NLS-1$
+
+ case TokenNameRIGHT_SHIFT_EQUAL : // >>= (15.25.2)
+ return ">>="; //$NON-NLS-1$
+
+// case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>= (15.25.2)
+// return ">>>="; //$NON-NLS-1$
+
+ case TokenNameAND_EQUAL : // &= (15.25.2)
+ return "&="; //$NON-NLS-1$
+
+ case TokenNameXOR_EQUAL : // ^= (15.25.2)
+ return "^="; //$NON-NLS-1$
+
+ case TokenNameOR_EQUAL : // |= (15.25.2)
+ return "|="; //$NON-NLS-1$
+
+ case TokenNameDOT : // .
+ return "."; //$NON-NLS-1$
+
+ default :
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Appends <code>stringToOutput</code> to the formatted output.<br>
+ * If it contains \n, append a LINE_SEPARATOR and indent after it.
+ */
+ private void output(String stringToOutput) {
+ char currentCharacter;
+ for (int i = 0, max = stringToOutput.length(); i < max; i++) {
+ currentCharacter = stringToOutput.charAt(i);
+ if (currentCharacter != '\t') {
+ currentLineBuffer.append(currentCharacter);
+ }
+ }
+ }
+
+ /**
+ * Appends <code>token</code> to the formatted output.<br>
+ * If it contains <code>\n</code>, append a LINE_SEPARATOR and indent after it.
+ */
+ private void outputCurrentToken(int token) {
+ char[] source = scanner.source;
+ int startPosition = scanner.startPosition;
+
+ switch (token) {
+ case Scanner.TokenNameCOMMENT_PHPDOC :
+ case Scanner.TokenNameCOMMENT_BLOCK :
+ case Scanner.TokenNameCOMMENT_LINE :
+ boolean endOfLine = false;
+ int currentCommentOffset = getCurrentCommentOffset();
+ int beginningOfLineSpaces = 0;
+ endOfLine = false;
+ currentCommentOffset = getCurrentCommentOffset();
+ beginningOfLineSpaces = 0;
+ boolean pendingCarriageReturn = false;
+ for (int i = startPosition, max = scanner.currentPosition; i < max; i++) {
+ char currentCharacter = source[i];
+ updateMappedPositions(i);
+ switch (currentCharacter) {
+ case '\r' :
+ pendingCarriageReturn = true;
+ endOfLine = true;
+ break;
+ case '\n' :
+ if (pendingCarriageReturn) {
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 2);
+ } else {
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ }
+ pendingCarriageReturn = false;
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ beginningOfLineSpaces = 0;
+ endOfLine = true;
+ break;
+ case '\t' :
+ if (pendingCarriageReturn) {
+ pendingCarriageReturn = false;
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ beginningOfLineSpaces = 0;
+ endOfLine = true;
+ }
+ if (endOfLine) {
+ // we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
+ beginningOfLineSpaces += options.tabSize;
+ if (beginningOfLineSpaces > currentCommentOffset) {
+ currentLineBuffer.append(currentCharacter);
+ } else {
+ increaseGlobalDelta(-1);
+ }
+ } else {
+ currentLineBuffer.append(currentCharacter);
+ }
+ break;
+ case ' ' :
+ if (pendingCarriageReturn) {
+ pendingCarriageReturn = false;
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ beginningOfLineSpaces = 0;
+ endOfLine = true;
+ }
+ if (endOfLine) {
+ // we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
+ beginningOfLineSpaces++;
+ if (beginningOfLineSpaces > currentCommentOffset) {
+ currentLineBuffer.append(currentCharacter);
+ } else {
+ increaseGlobalDelta(-1);
+ }
+ } else {
+ currentLineBuffer.append(currentCharacter);
+ }
+ break;
+ default :
+ if (pendingCarriageReturn) {
+ pendingCarriageReturn = false;
+ increaseGlobalDelta(options.lineSeparatorSequence.length - 1);
+ currentLineBuffer.append(options.lineSeparatorSequence);
+ beginningOfLineSpaces = 0;
+ endOfLine = true;
+ } else {
+ beginningOfLineSpaces = 0;
+ currentLineBuffer.append(currentCharacter);
+ endOfLine = false;
+ }
+ }
+ }
+ updateMappedPositions(scanner.currentPosition - 1);
+ multipleLineCommentCounter++;
+ break;
+ default :
+ for (int i = startPosition, max = scanner.currentPosition; i < max; i++) {
+ char currentCharacter = source[i];
+ updateMappedPositions(i);
+ currentLineBuffer.append(currentCharacter);
+ }
+ }
+ }
+
+ /**
+ * Outputs <code>currentString</code>:<br>
+ * <ul><li>If its length is < maxLineLength, output
+ * <li>Otherwise it is split.</ul>
+ * @param currentString string to output
+ * @param preIndented whether the string to output was pre-indented
+ * @param depth number of indentation to put in front of <code>currentString</code>
+ * @param operator value of the operator belonging to <code>currentString</code>.
+ */
+ private void outputLine(
+ String currentString,
+ boolean preIndented,
+ int depth,
+ int operator,
+ int substringIndex,
+ int[] startSubstringIndexes,
+ int offsetInGlobalLine) {
+
+ boolean emptyFirstSubString = false;
+ String operatorString = operatorString(operator);
+ boolean placeOperatorBehind = !breakLineBeforeOperator(operator);
+ boolean placeOperatorAhead = !placeOperatorBehind;
+
+ // dump prefix operator?
+ if (placeOperatorAhead) {
+ if (!preIndented) {
+ dumpTab(depth);
+ preIndented = true;
+ }
+ if (operator != 0) {
+ if (insertSpaceBefore(operator)) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ formattedSource.append(operatorString);
+ increaseSplitDelta(operatorString.length());
+
+ if (insertSpaceAfter(operator)
+ // && operator != TokenNameimplements
+ && operator != TokenNameextends) {
+ // && operator != TokenNamethrows) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ }
+ }
+ SplitLine splitLine = null;
+ if (options.maxLineLength == 0
+ || getLength(currentString, depth) < options.maxLineLength
+ || (splitLine = split(currentString, offsetInGlobalLine)) == null) {
+
+ // depending on the type of operator, outputs new line before of after dumping it
+ // indent before postfix operator
+ // indent also when the line cannot be split
+ if (operator == TokenNameextends) {
+// || operator == TokenNameimplements
+// || operator == TokenNamethrows) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ if (placeOperatorBehind) {
+ if (!preIndented) {
+ dumpTab(depth);
+ }
+ }
+ int max = currentString.length();
+ if (multipleLineCommentCounter != 0) {
+ try {
+ BufferedReader reader = new BufferedReader(new StringReader(currentString));
+ String line = reader.readLine();
+ while (line != null) {
+ updateMappedPositionsWhileSplitting(
+ beginningOfLineIndex,
+ beginningOfLineIndex + line.length() + options.lineSeparatorSequence.length);
+ formattedSource.append(line);
+ beginningOfLineIndex = beginningOfLineIndex + line.length();
+ if ((line = reader.readLine()) != null) {
+ formattedSource.append(options.lineSeparatorSequence);
+ beginningOfLineIndex += options.lineSeparatorSequence.length;
+ dumpTab(currentLineIndentationLevel);
+ }
+ }
+ reader.close();
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ updateMappedPositionsWhileSplitting(
+ beginningOfLineIndex,
+ beginningOfLineIndex + max);
+ for (int i = 0; i < max; i++) {
+ char currentChar = currentString.charAt(i);
+ switch (currentChar) {
+ case '\r' :
+ break;
+ case '\n' :
+ if (i != max - 1) {
+ // fix for 1FFYL5C: LFCOM:ALL - Incorrect indentation when split with a comment inside a condition
+ // a substring cannot end with a lineSeparatorSequence,
+ // except if it has been added by format() after a one-line comment
+ formattedSource.append(options.lineSeparatorSequence);
+
+ // 1FGDDV6: LFCOM:WIN98 - Weird splitting on message expression
+ dumpTab(depth - 1);
+ }
+ break;
+ default :
+ formattedSource.append(currentChar);
+ }
+ }
+ }
+ // update positions inside the mappedPositions table
+ if (substringIndex != -1) {
+ if (multipleLineCommentCounter == 0) {
+ int startPosition =
+ beginningOfLineIndex + startSubstringIndexes[substringIndex];
+ updateMappedPositionsWhileSplitting(startPosition, startPosition + max);
+ }
+
+ // compute the splitDelta resulting with the operator and blank removal
+ if (substringIndex + 1 != startSubstringIndexes.length) {
+ increaseSplitDelta(
+ startSubstringIndexes[substringIndex]
+ + max
+ - startSubstringIndexes[substringIndex + 1]);
+ }
+ }
+ // dump postfix operator?
+ if (placeOperatorBehind) {
+ if (insertSpaceBefore(operator)) {
+ formattedSource.append(' ');
+ if (operator != 0) {
+ increaseSplitDelta(1);
+ }
+ }
+ formattedSource.append(operatorString);
+ if (operator != 0) {
+ increaseSplitDelta(operatorString.length());
+ }
+ }
+ return;
+ }
+ // fix for 1FG0BA3: LFCOM:WIN98 - Weird splitting on interfaces
+ // extends has to stand alone on a line when currentString has been split.
+ if (options.maxLineLength != 0
+ && splitLine != null
+ && (operator == TokenNameextends)) {
+// || operator == TokenNameimplements
+// || operator == TokenNamethrows)) {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseSplitDelta(options.lineSeparatorSequence.length);
+ dumpTab(depth + 1);
+ } else {
+ if (operator == TokenNameextends) {
+// || operator == TokenNameimplements
+// || operator == TokenNamethrows) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ }
+ // perform actual splitting
+ String result[] = splitLine.substrings;
+ int[] splitOperators = splitLine.operators;
+
+ if (result[0].length() == 0) {
+ // when the substring 0 is null, the substring 1 is correctly indented.
+ depth--;
+ emptyFirstSubString = true;
+ }
+ // the operator going in front of the result[0] string is the operator parameter
+ for (int i = 0, max = result.length; i < max; i++) {
+ // the new depth is the current one if this is the first substring,
+ // the current one + 1 otherwise.
+ // if the substring is a comment, use the current indentation Level instead of the depth
+ // (-1 because the ouputline increases depth).
+ // (fix for 1FFC72R: LFCOM:ALL - Incorrect line split in presence of line comments)
+ String currentResult = result[i];
+
+ if (currentResult.length() != 0 || splitOperators[i] != 0) {
+ int newDepth =
+ (currentResult.startsWith("/*") //$NON-NLS-1$
+ || currentResult.startsWith("//")) //$NON-NLS-1$
+ ? indentationLevel - 1 : depth;
+ outputLine(
+ currentResult,
+ i == 0 || (i == 1 && emptyFirstSubString) ? preIndented : false,
+ i == 0 ? newDepth : newDepth + 1,
+ splitOperators[i],
+ i,
+ splitLine.startSubstringsIndexes,
+ currentString.indexOf(currentResult));
+ if (i != max - 1) {
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseSplitDelta(options.lineSeparatorSequence.length);
+ }
+ }
+ }
+ if (result.length == splitOperators.length - 1) {
+ int lastOperator = splitOperators[result.length];
+ String lastOperatorString = operatorString(lastOperator);
+ formattedSource.append(options.lineSeparatorSequence);
+ increaseSplitDelta(options.lineSeparatorSequence.length);
+
+ if (breakLineBeforeOperator(lastOperator)) {
+ dumpTab(depth + 1);
+ if (lastOperator != 0) {
+ if (insertSpaceBefore(lastOperator)) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ formattedSource.append(lastOperatorString);
+ increaseSplitDelta(lastOperatorString.length());
+
+ if (insertSpaceAfter(lastOperator)
+ // && lastOperator != TokenNameimplements
+ && lastOperator != TokenNameextends ) {
+ // && lastOperator != TokenNamethrows) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ }
+ }
+ }
+ if (placeOperatorBehind) {
+ if (insertSpaceBefore(operator)) {
+ formattedSource.append(' ');
+ increaseSplitDelta(1);
+ }
+ formattedSource.append(operatorString);
+ //increaseSplitDelta(operatorString.length());
+ }
+ }
+
+ /**
+ * Pops the top statement of the stack if it is <code>token</code>
+ */
+ private int pop(int token) {
+ int delta = 0;
+ if ((constructionsCount > 0)
+ && (constructions[constructionsCount - 1] == token)) {
+ delta--;
+ constructionsCount--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops the top statement of the stack if it is a <code>BLOCK</code> or a <code>NONINDENT_BLOCK</code>.
+ */
+ private int popBlock() {
+ int delta = 0;
+ if ((constructionsCount > 0)
+ && ((constructions[constructionsCount - 1] == BLOCK)
+ || (constructions[constructionsCount - 1] == NONINDENT_BLOCK))) {
+ if (constructions[constructionsCount - 1] == BLOCK)
+ delta--;
+ constructionsCount--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops elements until the stack is empty or the top element is <code>token</code>.<br>
+ * Does not remove <code>token</code> from the stack.
+ * @param token the token to be left as the top of the stack
+ */
+ private int popExclusiveUntil(int token) {
+ int delta = 0;
+ int startCount = constructionsCount;
+ for (int i = startCount - 1; i >= 0 && constructions[i] != token; i--) {
+ if (constructions[i] != NONINDENT_BLOCK)
+ delta--;
+ constructionsCount--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops elements until the stack is empty or the top element is
+ * a <code>BLOCK</code> or a <code>NONINDENT_BLOCK</code>.<br>
+ * Does not remove it from the stack.
+ */
+ private int popExclusiveUntilBlock() {
+ int startCount = constructionsCount;
+ int delta = 0;
+ for (int i = startCount - 1;
+ i >= 0 && constructions[i] != BLOCK && constructions[i] != NONINDENT_BLOCK;
+ i--) {
+ constructionsCount--;
+ delta--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops elements until the stack is empty or the top element is
+ * a <code>BLOCK</code>, a <code>NONINDENT_BLOCK</code> or a <code>CASE</code>.<br>
+ * Does not remove it from the stack.
+ */
+ private int popExclusiveUntilBlockOrCase() {
+ int startCount = constructionsCount;
+ int delta = 0;
+ for (int i = startCount - 1;
+ i >= 0
+ && constructions[i] != BLOCK
+ && constructions[i] != NONINDENT_BLOCK
+ && constructions[i] != TokenNamecase;
+ i--) {
+ constructionsCount--;
+ delta--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops elements until the stack is empty or the top element is <code>token</code>.<br>
+ * Removes <code>token</code> from the stack too.
+ * @param token the token to remove from the stack
+ */
+ private int popInclusiveUntil(int token) {
+ int startCount = constructionsCount;
+ int delta = 0;
+ for (int i = startCount - 1; i >= 0 && constructions[i] != token; i--) {
+ if (constructions[i] != NONINDENT_BLOCK)
+ delta--;
+ constructionsCount--;
+ }
+ if (constructionsCount > 0) {
+ if (constructions[constructionsCount - 1] != NONINDENT_BLOCK)
+ delta--;
+ constructionsCount--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pops elements until the stack is empty or the top element is
+ * a <code>BLOCK</code> or a <code>NONINDENT_BLOCK</code>.<br>
+ * Does not remove it from the stack.
+ */
+ private int popInclusiveUntilBlock() {
+ int startCount = constructionsCount;
+ int delta = 0;
+ for (int i = startCount - 1;
+ i >= 0 && (constructions[i] != BLOCK && constructions[i] != NONINDENT_BLOCK);
+ i--) {
+ delta--;
+ constructionsCount--;
+ }
+ if (constructionsCount > 0) {
+ if (constructions[constructionsCount - 1] == BLOCK)
+ delta--;
+ constructionsCount--;
+ }
+ return delta;
+ }
+
+ /**
+ * Pushes a block in the stack.<br>
+ * Pushes a <code>BLOCK</code> if the stack is empty or if the top element is a <code>BLOCK</code>,
+ * pushes <code>NONINDENT_BLOCK</code> otherwise.
+ * Creates a new bigger array if the current one is full.
+ */
+ private int pushBlock() {
+ int delta = 0;
+ if (constructionsCount == constructions.length)
+ System.arraycopy(
+ constructions,
+ 0,
+ (constructions = new int[constructionsCount * 2]),
+ 0,
+ constructionsCount);
+
+ if ((constructionsCount == 0)
+ || (constructions[constructionsCount - 1] == BLOCK)
+ || (constructions[constructionsCount - 1] == NONINDENT_BLOCK)
+ || (constructions[constructionsCount - 1] == TokenNamecase)) {
+ delta++;
+ constructions[constructionsCount++] = BLOCK;
+ } else {
+ constructions[constructionsCount++] = NONINDENT_BLOCK;
+ }
+ return delta;
+ }
+
+ /**
+ * Pushes <code>token</code>.<br>
+ * Creates a new bigger array if the current one is full.
+ */
+ private int pushControlStatement(int token) {
+ if (constructionsCount == constructions.length)
+ System.arraycopy(
+ constructions,
+ 0,
+ (constructions = new int[constructionsCount * 2]),
+ 0,
+ constructionsCount);
+ constructions[constructionsCount++] = token;
+ return 1;
+ }
+
+ private static boolean separateFirstArgumentOn(int currentToken) {
+ //return (currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON);
+ return currentToken != TokenNameif
+ && currentToken != TokenNameLPAREN
+ && currentToken != TokenNameNOT
+ && currentToken != TokenNamewhile
+ && currentToken != TokenNamefor
+ && currentToken != TokenNameswitch;
+ }
+
+ /**
+ * Set the positions to map. The mapped positions should be retrieved using the
+ * getMappedPositions() method.
+ * @param positions int[]
+ * @deprecated Set the positions to map using the format(String, int, int[]) method.
+ *
+ * @see #getMappedPositions()
+ */
+ public void setPositionsToMap(int[] positions) {
+ positionsToMap = positions;
+ lineDelta = 0;
+ globalDelta = 0;
+ mappedPositions = new int[positions.length];
+ }
+
+ /**
+ * Appends a space character to the current line buffer.
+ */
+ private void space() {
+ currentLineBuffer.append(' ');
+ increaseLineDelta(1);
+ }
+
+ /**
+ * Splits <code>stringToSplit</code> on the top level token<br>
+ * If there are several identical token at the same level,
+ * the string is cut into many pieces.
+ * @return an object containing the operator and all the substrings
+ * or null if the string cannot be split
+ */
+ public SplitLine split(String stringToSplit) {
+ return split(stringToSplit, 0);
+ }
+
+ /**
+ * Splits <code>stringToSplit</code> on the top level token<br>
+ * If there are several identical token at the same level,
+ * the string is cut into many pieces.
+ * @return an object containing the operator and all the substrings
+ * or null if the string cannot be split
+ */
+ public SplitLine split(String stringToSplit, int offsetInGlobalLine) {
+ /*
+ * See http://dev.eclipse.org/bugs/show_bug.cgi?id=12540 and
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=14387
+ */
+ if (stringToSplit.indexOf("//$NON-NLS") != -1) { //$NON-NLS-1$
+ return null;
+ }
+ // local variables
+ int currentToken = 0;
+ int splitTokenType = 0;
+ int splitTokenDepth = Integer.MAX_VALUE;
+ int splitTokenPriority = Integer.MAX_VALUE;
+
+ int[] substringsStartPositions = new int[10];
+ // contains the start position of substrings
+ int[] substringsEndPositions = new int[10];
+ // contains the start position of substrings
+ int substringsCount = 1; // index in the substringsStartPosition array
+ int[] splitOperators = new int[10];
+ // contains the start position of substrings
+ int splitOperatorsCount = 0; // index in the substringsStartPosition array
+ int[] openParenthesisPosition = new int[10];
+ int openParenthesisPositionCount = 0;
+ int position = 0;
+ int lastOpenParenthesisPosition = -1;
+ // used to remember the position of the 1st open parenthesis
+ // needed for a pattern like: A.B(C); we want formatted like A.B( split C);
+ // setup the scanner with a new source
+ int lastCommentStartPosition = -1;
+ // to remember the start position of the last comment
+ int firstTokenOnLine = -1;
+ // to remember the first token of the line
+ int previousToken = -1;
+ // to remember the previous token.
+ splitScanner.setSource(stringToSplit.toCharArray());
+
+ try {
+ // start the loop
+ while (true) {
+ // takes the next token
+ try {
+ if (currentToken != Scanner.TokenNameWHITESPACE)
+ previousToken = currentToken;
+ currentToken = splitScanner.getNextToken();
+ } catch (InvalidInputException e) {
+ if (!handleInvalidToken(e))
+ throw e;
+ currentToken = 0; // this value is not modify when an exception is raised.
+ }
+ if (currentToken == TokenNameEOF)
+ break;
+
+ if (firstTokenOnLine == -1) {
+ firstTokenOnLine = currentToken;
+ }
+ switch (currentToken) {
+ case TokenNameRBRACE :
+ case TokenNameRPAREN :
+ if (openParenthesisPositionCount > 0) {
+ if (openParenthesisPositionCount == 1
+ && lastOpenParenthesisPosition < openParenthesisPosition[0]) {
+ lastOpenParenthesisPosition = openParenthesisPosition[0];
+ } else if (
+ (splitTokenDepth == Integer.MAX_VALUE)
+ || (splitTokenDepth > openParenthesisPositionCount
+ && openParenthesisPositionCount == 1)) {
+ splitTokenType = 0;
+ splitTokenDepth = openParenthesisPositionCount;
+ splitTokenPriority = Integer.MAX_VALUE;
+ substringsStartPositions[0] = 0;
+ // better token means the whole line until now is the first substring
+ substringsCount = 1; // resets the count of substrings
+ substringsEndPositions[0] = openParenthesisPosition[0];
+ // substring ends on operator start
+ position = openParenthesisPosition[0];
+ // the string mustn't be cut before the closing parenthesis but after the opening one.
+ splitOperatorsCount = 1; // resets the count of split operators
+ splitOperators[0] = 0;
+ }
+ openParenthesisPositionCount--;
+ }
+ break;
+ case TokenNameLBRACE :
+ case TokenNameLPAREN :
+ if (openParenthesisPositionCount == openParenthesisPosition.length) {
+ System.arraycopy(
+ openParenthesisPosition,
+ 0,
+ (openParenthesisPosition = new int[openParenthesisPositionCount * 2]),
+ 0,
+ openParenthesisPositionCount);
+ }
+ openParenthesisPosition[openParenthesisPositionCount++] =
+ splitScanner.currentPosition;
+ if (currentToken == TokenNameLPAREN && previousToken == TokenNameRPAREN) {
+ openParenthesisPosition[openParenthesisPositionCount - 1] =
+ splitScanner.startPosition;
+ }
+ break;
+ case TokenNameSEMICOLON : // ;
+ case TokenNameCOMMA : // ,
+ case TokenNameEQUAL : // =
+ if (openParenthesisPositionCount < splitTokenDepth
+ || (openParenthesisPositionCount == splitTokenDepth
+ && splitTokenPriority > getTokenPriority(currentToken))) {
+ // the current token is better than the one we currently have
+ // (in level or in priority if same level)
+ // reset the substringsCount
+ splitTokenDepth = openParenthesisPositionCount;
+ splitTokenType = currentToken;
+ splitTokenPriority = getTokenPriority(currentToken);
+ substringsStartPositions[0] = 0;
+ // better token means the whole line until now is the first substring
+
+ if (separateFirstArgumentOn(firstTokenOnLine)
+ && openParenthesisPositionCount > 0) {
+ substringsCount = 2; // resets the count of substrings
+
+ substringsEndPositions[0] = openParenthesisPosition[splitTokenDepth - 1];
+ substringsStartPositions[1] = openParenthesisPosition[splitTokenDepth - 1];
+ substringsEndPositions[1] = splitScanner.startPosition;
+ splitOperatorsCount = 2; // resets the count of split operators
+ splitOperators[0] = 0;
+ splitOperators[1] = currentToken;
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ } else {
+ substringsCount = 1; // resets the count of substrings
+
+ substringsEndPositions[0] = splitScanner.startPosition;
+ // substring ends on operator start
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ splitOperatorsCount = 1; // resets the count of split operators
+ splitOperators[0] = currentToken;
+ }
+ } else {
+ if ((openParenthesisPositionCount == splitTokenDepth
+ && splitTokenPriority == getTokenPriority(currentToken))
+ && splitTokenType != TokenNameEQUAL
+ && currentToken != TokenNameEQUAL) {
+ // fix for 1FG0BCN: LFCOM:WIN98 - Missing one indentation after split
+ // take only the 1st = into account.
+ // if another token with the same priority is found,
+ // push the start position of the substring and
+ // push the token into the stack.
+ // create a new array object if the current one is full.
+ if (substringsCount == substringsStartPositions.length) {
+ System.arraycopy(
+ substringsStartPositions,
+ 0,
+ (substringsStartPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ substringsEndPositions,
+ 0,
+ (substringsEndPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ }
+ if (splitOperatorsCount == splitOperators.length) {
+ System.arraycopy(
+ splitOperators,
+ 0,
+ (splitOperators = new int[splitOperatorsCount * 2]),
+ 0,
+ splitOperatorsCount);
+ }
+ substringsStartPositions[substringsCount] = position;
+ substringsEndPositions[substringsCount++] = splitScanner.startPosition;
+ // substring ends on operator start
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ splitOperators[splitOperatorsCount++] = currentToken;
+ }
+ }
+ break;
+
+ case TokenNameCOLON : // : (15.24)
+ // see 1FK7C5R, we only split on a colon, when it is associated with a question-mark.
+ // indeed it might appear also behind a case statement, and we do not to break at this point.
+ if ((splitOperatorsCount == 0)
+ || splitOperators[splitOperatorsCount - 1] != TokenNameQUESTION) {
+ break;
+ }
+ case TokenNameextends :
+ // case TokenNameimplements :
+ // case TokenNamethrows :
+
+ case TokenNameDOT : // .
+ case TokenNameMULTIPLY : // * (15.16.1)
+ case TokenNameDIVIDE : // / (15.16.2)
+ case TokenNameREMAINDER : // % (15.16.3)
+ case TokenNamePLUS : // + (15.17, 15.17.2)
+ case TokenNameMINUS : // - (15.17.2)
+ case TokenNameLEFT_SHIFT : // << (15.18)
+ case TokenNameRIGHT_SHIFT : // >> (15.18)
+ // case TokenNameUNSIGNED_RIGHT_SHIFT : // >>> (15.18)
+ case TokenNameLESS : // < (15.19.1)
+ case TokenNameLESS_EQUAL : // <= (15.19.1)
+ case TokenNameGREATER : // > (15.19.1)
+ case TokenNameGREATER_EQUAL : // >= (15.19.1)
+ // case TokenNameinstanceof : // instanceof
+ case TokenNameEQUAL_EQUAL : // == (15.20, 15.20.1, 15.20.2, 15.20.3)
+ case TokenNameNOT_EQUAL : // != (15.20, 15.20.1, 15.20.2, 15.20.3)
+ case TokenNameAND : // & (15.21, 15.21.1, 15.21.2)
+ case TokenNameOR : // | (15.21, 15.21.1, 15.21.2)
+ case TokenNameXOR : // ^ (15.21, 15.21.1, 15.21.2)
+ case TokenNameAND_AND : // && (15.22)
+ case TokenNameOR_OR : // || (15.23)
+ case TokenNameQUESTION : // ? (15.24)
+ case TokenNameMULTIPLY_EQUAL : // *= (15.25.2)
+ case TokenNameDIVIDE_EQUAL : // /= (15.25.2)
+ case TokenNameREMAINDER_EQUAL : // %= (15.25.2)
+ case TokenNamePLUS_EQUAL : // += (15.25.2)
+ case TokenNameMINUS_EQUAL : // -= (15.25.2)
+ case TokenNameLEFT_SHIFT_EQUAL : // <<= (15.25.2)
+ case TokenNameRIGHT_SHIFT_EQUAL : // >>= (15.25.2)
+// case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>= (15.25.2)
+ case TokenNameAND_EQUAL : // &= (15.25.2)
+ case TokenNameXOR_EQUAL : // ^= (15.25.2)
+ case TokenNameOR_EQUAL : // |= (15.25.2)
+
+ if ((openParenthesisPositionCount < splitTokenDepth
+ || (openParenthesisPositionCount == splitTokenDepth
+ && splitTokenPriority > getTokenPriority(currentToken)))
+ && !((currentToken == TokenNamePLUS || currentToken == TokenNameMINUS)
+ && (previousToken == TokenNameLBRACE
+ || previousToken == TokenNameLBRACKET
+ || splitScanner.startPosition == 0))) {
+ // the current token is better than the one we currently have
+ // (in level or in priority if same level)
+ // reset the substringsCount
+ splitTokenDepth = openParenthesisPositionCount;
+ splitTokenType = currentToken;
+ splitTokenPriority = getTokenPriority(currentToken);
+ substringsStartPositions[0] = 0;
+ // better token means the whole line until now is the first substring
+
+ if (separateFirstArgumentOn(firstTokenOnLine)
+ && openParenthesisPositionCount > 0) {
+ substringsCount = 2; // resets the count of substrings
+
+ substringsEndPositions[0] = openParenthesisPosition[splitTokenDepth - 1];
+ substringsStartPositions[1] = openParenthesisPosition[splitTokenDepth - 1];
+ substringsEndPositions[1] = splitScanner.startPosition;
+ splitOperatorsCount = 3; // resets the count of split operators
+ splitOperators[0] = 0;
+ splitOperators[1] = 0;
+ splitOperators[2] = currentToken;
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ } else {
+ substringsCount = 1; // resets the count of substrings
+
+ substringsEndPositions[0] = splitScanner.startPosition;
+ // substring ends on operator start
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ splitOperatorsCount = 2; // resets the count of split operators
+ splitOperators[0] = 0;
+ // nothing for first operand since operator will be inserted in front of the second operand
+ splitOperators[1] = currentToken;
+
+ }
+ } else {
+ if (openParenthesisPositionCount == splitTokenDepth
+ && splitTokenPriority == getTokenPriority(currentToken)) {
+ // if another token with the same priority is found,
+ // push the start position of the substring and
+ // push the token into the stack.
+ // create a new array object if the current one is full.
+ if (substringsCount == substringsStartPositions.length) {
+ System.arraycopy(
+ substringsStartPositions,
+ 0,
+ (substringsStartPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ substringsEndPositions,
+ 0,
+ (substringsEndPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ }
+ if (splitOperatorsCount == splitOperators.length) {
+ System.arraycopy(
+ splitOperators,
+ 0,
+ (splitOperators = new int[splitOperatorsCount * 2]),
+ 0,
+ splitOperatorsCount);
+ }
+ substringsStartPositions[substringsCount] = position;
+ substringsEndPositions[substringsCount++] = splitScanner.startPosition;
+ // substring ends on operator start
+ position = splitScanner.currentPosition;
+ // next substring will start from operator end
+ splitOperators[splitOperatorsCount++] = currentToken;
+ }
+ }
+ default :
+ break;
+ }
+ if (isComment(currentToken)) {
+ lastCommentStartPosition = splitScanner.startPosition;
+ } else {
+ lastCommentStartPosition = -1;
+ }
+ }
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ // if the string cannot be split, return null.
+ if (splitOperatorsCount == 0)
+ return null;
+
+ // ## SPECIAL CASES BEGIN
+ if (((splitOperatorsCount == 2
+ && splitOperators[1] == TokenNameDOT
+ && splitTokenDepth == 0
+ && lastOpenParenthesisPosition > -1)
+ || (splitOperatorsCount > 2
+ && splitOperators[1] == TokenNameDOT
+ && splitTokenDepth == 0
+ && lastOpenParenthesisPosition > -1
+ && lastOpenParenthesisPosition <= options.maxLineLength)
+ || (separateFirstArgumentOn(firstTokenOnLine)
+ && splitTokenDepth > 0
+ && lastOpenParenthesisPosition > -1))
+ && (lastOpenParenthesisPosition < splitScanner.source.length
+ && splitScanner.source[lastOpenParenthesisPosition] != ')')) {
+ // fix for 1FH4J2H: LFCOM:WINNT - Formatter - Empty parenthesis should not be broken on two lines
+ // only one split on a top level .
+ // or more than one split on . and substring before open parenthesis fits one line.
+ // or split inside parenthesis and first token is not a for/while/if
+ SplitLine sl =
+ split(
+ stringToSplit.substring(lastOpenParenthesisPosition),
+ lastOpenParenthesisPosition);
+ if (sl == null || sl.operators[0] != TokenNameCOMMA) {
+ // trim() is used to remove the extra blanks at the end of the substring. See PR 1FGYPI1
+ return new SplitLine(
+ new int[] { 0, 0 },
+ new String[] {
+ stringToSplit.substring(0, lastOpenParenthesisPosition).trim(),
+ stringToSplit.substring(lastOpenParenthesisPosition)},
+ new int[] {
+ offsetInGlobalLine,
+ lastOpenParenthesisPosition + offsetInGlobalLine });
+ } else {
+ // right substring can be split and is split on comma
+ // copy substrings and operators
+ // except if the 1st string is empty.
+ int startIndex = (sl.substrings[0].length() == 0) ? 1 : 0;
+ int subStringsLength = sl.substrings.length + 1 - startIndex;
+ String[] result = new String[subStringsLength];
+ int[] startIndexes = new int[subStringsLength];
+ int operatorsLength = sl.operators.length + 1 - startIndex;
+ int[] operators = new int[operatorsLength];
+
+ result[0] = stringToSplit.substring(0, lastOpenParenthesisPosition);
+ operators[0] = 0;
+
+ System.arraycopy(
+ sl.startSubstringsIndexes,
+ startIndex,
+ startIndexes,
+ 1,
+ subStringsLength - 1);
+ for (int i = subStringsLength - 1; i >= 0; i--) {
+ startIndexes[i] += offsetInGlobalLine;
+ }
+ System.arraycopy(sl.substrings, startIndex, result, 1, subStringsLength - 1);
+ System.arraycopy(sl.operators, startIndex, operators, 1, operatorsLength - 1);
+
+ return new SplitLine(operators, result, startIndexes);
+ }
+ }
+ // if the last token is a comment and the substring before the comment fits on a line,
+ // split before the comment and return the result.
+ if (lastCommentStartPosition > -1
+ && lastCommentStartPosition < options.maxLineLength
+ && splitTokenPriority > 50) {
+ int end = lastCommentStartPosition;
+ int start = lastCommentStartPosition;
+ if (stringToSplit.charAt(end - 1) == ' ') {
+ end--;
+ }
+ if (start != end && stringToSplit.charAt(start) == ' ') {
+ start++;
+ }
+ return new SplitLine(
+ new int[] { 0, 0 },
+ new String[] { stringToSplit.substring(0, end), stringToSplit.substring(start)},
+ new int[] { 0, start });
+ }
+ if (position != stringToSplit.length()) {
+ if (substringsCount == substringsStartPositions.length) {
+ System.arraycopy(
+ substringsStartPositions,
+ 0,
+ (substringsStartPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ substringsEndPositions,
+ 0,
+ (substringsEndPositions = new int[substringsCount * 2]),
+ 0,
+ substringsCount);
+ }
+ // avoid empty extra substring, e.g. line terminated with a semi-colon
+ substringsStartPositions[substringsCount] = position;
+ substringsEndPositions[substringsCount++] = stringToSplit.length();
+ }
+ if (splitOperatorsCount == splitOperators.length) {
+ System.arraycopy(
+ splitOperators,
+ 0,
+ (splitOperators = new int[splitOperatorsCount * 2]),
+ 0,
+ splitOperatorsCount);
+ }
+ splitOperators[splitOperatorsCount] = 0;
+
+ // the last element of the stack is the position of the end of StringToSPlit
+ // +1 because the substring method excludes the last character
+ String[] result = new String[substringsCount];
+ for (int i = 0; i < substringsCount; i++) {
+ int start = substringsStartPositions[i];
+ int end = substringsEndPositions[i];
+ if (stringToSplit.charAt(start) == ' ') {
+ start++;
+ substringsStartPositions[i]++;
+ }
+ if (end != start && stringToSplit.charAt(end - 1) == ' ') {
+ end--;
+ }
+ result[i] = stringToSplit.substring(start, end);
+ substringsStartPositions[i] += offsetInGlobalLine;
+ }
+ if (splitOperatorsCount > substringsCount) {
+ System.arraycopy(
+ substringsStartPositions,
+ 0,
+ (substringsStartPositions = new int[splitOperatorsCount]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ substringsEndPositions,
+ 0,
+ (substringsEndPositions = new int[splitOperatorsCount]),
+ 0,
+ substringsCount);
+ for (int i = substringsCount; i < splitOperatorsCount; i++) {
+ substringsStartPositions[i] = position;
+ substringsEndPositions[i] = position;
+ }
+ System.arraycopy(
+ splitOperators,
+ 0,
+ (splitOperators = new int[splitOperatorsCount]),
+ 0,
+ splitOperatorsCount);
+ } else {
+ System.arraycopy(
+ substringsStartPositions,
+ 0,
+ (substringsStartPositions = new int[substringsCount]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ substringsEndPositions,
+ 0,
+ (substringsEndPositions = new int[substringsCount]),
+ 0,
+ substringsCount);
+ System.arraycopy(
+ splitOperators,
+ 0,
+ (splitOperators = new int[substringsCount]),
+ 0,
+ substringsCount);
+ }
+ SplitLine splitLine =
+ new SplitLine(splitOperators, result, substringsStartPositions);
+ return splitLine;
+ }
+
+ private void updateMappedPositions(int startPosition) {
+ if (positionsToMap == null) {
+ return;
+ }
+ char[] source = scanner.source;
+ int sourceLength = source.length;
+ while (indexToMap < positionsToMap.length
+ && positionsToMap[indexToMap] <= startPosition) {
+ int posToMap = positionsToMap[indexToMap];
+ if (posToMap < 0
+ || posToMap >= sourceLength) { // protection against out of bounds position
+ if (posToMap == sourceLength) {
+ mappedPositions[indexToMap] = formattedSource.length();
+ }
+ indexToMap = positionsToMap.length; // no more mapping
+ return;
+ }
+ if (CharOperation.isWhitespace(source[posToMap])) {
+ mappedPositions[indexToMap] = startPosition + globalDelta + lineDelta;
+ } else {
+ if (posToMap == sourceLength - 1) {
+ mappedPositions[indexToMap] = startPosition + globalDelta + lineDelta;
+ } else {
+ mappedPositions[indexToMap] = posToMap + globalDelta + lineDelta;
+ }
+ }
+ indexToMap++;
+ }
+ }
+
+ private void updateMappedPositionsWhileSplitting(
+ int startPosition,
+ int endPosition) {
+ if (mappedPositions == null || mappedPositions.length == indexInMap)
+ return;
+
+ while (indexInMap < mappedPositions.length
+ && startPosition <= mappedPositions[indexInMap]
+ && mappedPositions[indexInMap] < endPosition
+ && indexInMap < indexToMap) {
+ mappedPositions[indexInMap] += splitDelta;
+ indexInMap++;
+ }
+ }
+
+ private int getLength(String s, int tabDepth) {
+ int length = 0;
+ for (int i = 0; i < tabDepth; i++) {
+ length += options.tabSize;
+ }
+ for (int i = 0, max = s.length(); i < max; i++) {
+ char currentChar = s.charAt(i);
+ switch (currentChar) {
+ case '\t' :
+ length += options.tabSize;
+ break;
+ default :
+ length++;
+ }
+ }
+ return length;
+ }
+
+ /**
+ * Sets the initial indentation level
+ * @param indentationLevel new indentation level
+ *
+ * @deprecated
+ */
+ public void setInitialIndentationLevel(int newIndentationLevel) {
+ this.initialIndentationLevel =
+ currentLineIndentationLevel = indentationLevel = newIndentationLevel;
+ }
+}
\ No newline at end of file
--- /dev/null
+newline.openingBrace.number=1
+newline.openingBrace.category=Newline
+newline.openingBrace.name=I&nsert new line before opening brace
+newline.openingBrace.possibleValues=2|Insert|Do not insert
+newline.openingBrace.description=When Insert, a new line is inserted before an opening brace, otherwise nothing is inserted
+
+newline.controlStatement.number=2
+newline.controlStatement.category=Newline
+newline.controlStatement.name=Insert new &line in control statement
+newline.controlStatement.possibleValues=2|Insert|Do not insert
+newline.controlStatement.description=When Insert, a new line is inserted between } and else, catch, finally
+
+newline.clearAll.number=3
+newline.clearAll.category=Newline
+newline.clearAll.name=Clear all &blank lines
+newline.clearAll.possibleValues=2|Clear|Preserve one
+newline.clearAll.description=When Clear, all blank lines are removed. When Preserve one, only one is kept and all others removed.
+
+newline.elseIf.number=4
+newline.elseIf.category=Newline
+newline.elseIf.name=&Keep else if on the same line
+newline.elseIf.possibleValues=2|Yes|No
+newline.elseIf.description=When Yes, a blank line is inserted between a else and a if when they are contiguous
+
+newline.emptyBlock.number=5
+newline.emptyBlock.category=Newline
+newline.emptyBlock.name=In&sert a new line inside an empty block
+newline.emptyBlock.possibleValues=2|Insert|Do not insert
+newline.emptyBlock.description=When insert, a line break is inserted between contiguous { and }, if } is not followed by a keyword.
+
+line.split.number=6
+line.split.category=Line splitting
+line.split.name=Ma&ximum line length
+line.split.possibleValues=-1
+line.split.description=Enable splitting of long lines (exceeding the configurable length). Length of 0 will disable line splitting
+
+style.compactAssignment.number=7
+style.compactAssignment.category=Style
+style.compactAssignment.name=&Compact assignment
+style.compactAssignment.possibleValues=2|Compact|Normal
+style.compactAssignment.description=Assignments can be formatted asymmetrically, e.g. 'int x= 2;', when Normal, a space is inserted before the assignment operator
+
+style.reuseExistingLayout.number=8
+style.reuseExistingLayout.category=Style
+style.reuseExistingLayout.name=&Reuse existing layout
+style.reuseExistingLayout.possibleValues=2|Reuse|Do not reuse
+style.reuseExistingLayout.description=If the user has formatted his code a certain way, the formatter does not try to reformat it
+
+tabulation.char.number=9
+tabulation.char.category=Style
+tabulation.char.name=Indentation is represented by &tab
+tabulation.char.possibleValues=2|Tab|Spaces
+tabulation.char.description=Either choose to indent with tab characters or spaces
+
+tabulation.size.number=10
+tabulation.size.category=Style
+tabulation.size.name=&Amount of spaces representing a tab
+tabulation.size.possibleValues=-1
+tabulation.size.description=Tabulation size in term of space characters
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.phpeclipse.phpdt.internal.formatter.impl;
+\rimport java.util.Map;
+
+public class FormatterOptions {
+\r /**
+ * Option IDs
+ */
+ public static final String OPTION_InsertNewlineBeforeOpeningBrace = "org.phpeclipse.phpdt.core.formatter.newline.openingBrace"; //$NON-NLS-1$
+ public static final String OPTION_InsertNewlineInControlStatement = "org.phpeclipse.phpdt.core.formatter.newline.controlStatement"; //$NON-NLS-1$
+ public static final String OPTION_InsertNewLineBetweenElseAndIf = "org.phpeclipse.phpdt.core.formatter.newline.elseIf"; //$NON-NLS-1$
+ public static final String OPTION_InsertNewLineInEmptyBlock = "org.phpeclipse.phpdt.core.formatter.newline.emptyBlock"; //$NON-NLS-1$
+ public static final String OPTION_ClearAllBlankLines = "org.phpeclipse.phpdt.core.formatter.newline.clearAll"; //$NON-NLS-1$
+ public static final String OPTION_SplitLineExceedingLength = "org.phpeclipse.phpdt.core.formatter.lineSplit"; //$NON-NLS-1$
+ public static final String OPTION_CompactAssignment = "org.phpeclipse.phpdt.core.formatter.style.assignment"; //$NON-NLS-1$
+ public static final String OPTION_TabulationChar = "org.phpeclipse.phpdt.core.formatter.tabulation.char"; //$NON-NLS-1$
+ public static final String OPTION_TabulationSize = "org.phpeclipse.phpdt.core.formatter.tabulation.size"; //$NON-NLS-1$
+
+ public static final String INSERT = "insert"; //$NON-NLS-1$
+ public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$
+ public static final String PRESERVE_ONE = "preserve one"; //$NON-NLS-1$
+ public static final String CLEAR_ALL = "clear all"; //$NON-NLS-1$
+ public static final String NORMAL = "normal"; //$NON-NLS-1$
+ public static final String COMPACT = "compact"; //$NON-NLS-1$
+ public static final String TAB = "tab"; //$NON-NLS-1$
+ public static final String SPACE = "space"; //$NON-NLS-1$
+
+ // by default, do not insert blank line before opening brace
+ public boolean newLineBeforeOpeningBraceMode = false;
+
+ // by default, do not insert blank line behind keywords (ELSE, CATCH, FINALLY,...) in control statements
+ public boolean newlineInControlStatementMode = false;
+
+ // by default, preserve one blank line per sequence of blank lines
+ public boolean clearAllBlankLinesMode = false;
+
+ // line splitting will occur when line exceeds this length
+ public int maxLineLength = 80;
+
+ public boolean compactAssignmentMode = false; // if isTrue, assignments look like x= 12 (not like x = 12);
+
+ //number of consecutive spaces used to replace the tab char
+ public int tabSize = 4; // n spaces for one tab
+ public boolean indentWithTab = true;
+
+ public boolean compactElseIfMode = true; // if true, else and if are kept on the same line.
+ public boolean newLineInEmptyBlockMode = true; // if false, no new line in {} if it's empty.
+
+ public char[] lineSeparatorSequence = System.getProperty("line.separator").toCharArray(); //$NON-NLS-1$
+/**
+ * Initializing the formatter options with default settings
+ */
+public FormatterOptions(){
+}
+/**
+ * Initializing the formatter options with external settings
+ */
+public FormatterOptions(Map settings){
+ if (settings == null) return;
+
+ // filter options which are related to the assist component
+ Object[] entries = settings.entrySet().toArray();
+ for (int i = 0, max = entries.length; i < max; i++){
+ Map.Entry entry = (Map.Entry)entries[i];
+ if (!(entry.getKey() instanceof String)) continue;
+ if (!(entry.getValue() instanceof String)) continue;
+ String optionID = (String) entry.getKey();
+ String optionValue = (String) entry.getValue();
+
+ if(optionID.equals(OPTION_InsertNewlineBeforeOpeningBrace)){
+ if (optionValue.equals(INSERT)){
+ this.newLineBeforeOpeningBraceMode = true;
+ } else if (optionValue.equals(DO_NOT_INSERT)){
+ this.newLineBeforeOpeningBraceMode = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_InsertNewlineInControlStatement)){
+ if (optionValue.equals(INSERT)){
+ this.newlineInControlStatementMode = true;
+ } else if (optionValue.equals(DO_NOT_INSERT)){
+ this.newlineInControlStatementMode = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_ClearAllBlankLines)){
+ if (optionValue.equals(CLEAR_ALL)){
+ this.clearAllBlankLinesMode = true;
+ } else if (optionValue.equals(PRESERVE_ONE)){
+ this.clearAllBlankLinesMode = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_InsertNewLineBetweenElseAndIf)){
+ if (optionValue.equals(INSERT)){
+ this.compactElseIfMode = false;
+ } else if (optionValue.equals(DO_NOT_INSERT)){
+ this.compactElseIfMode = true;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_InsertNewLineInEmptyBlock)){
+ if (optionValue.equals(INSERT)){
+ this.newLineInEmptyBlockMode = true;
+ } else if (optionValue.equals(DO_NOT_INSERT)){
+ this.newLineInEmptyBlockMode = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_SplitLineExceedingLength)){
+ try {
+ int val = Integer.parseInt(optionValue);
+ if (val >= 0) this.maxLineLength = val;
+ } catch(NumberFormatException e){
+ }
+ }
+ if(optionID.equals(OPTION_CompactAssignment)){
+ if (optionValue.equals(COMPACT)){
+ this.compactAssignmentMode = true;
+ } else if (optionValue.equals(NORMAL)){
+ this.compactAssignmentMode = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_TabulationChar)){
+ if (optionValue.equals(TAB)){
+ this.indentWithTab = true;
+ } else if (optionValue.equals(SPACE)){
+ this.indentWithTab = false;
+ }
+ continue;
+ }
+ if(optionID.equals(OPTION_TabulationSize)){
+ try {
+ int val = Integer.parseInt(optionValue);
+ if (val > 0) this.tabSize = val;
+ } catch(NumberFormatException e){
+ }
+ }
+ }
+}
+
+/**
+ *
+ * @return int
+ */
+public int getMaxLineLength() {
+ return maxLineLength;
+}
+public int getTabSize() {
+ return tabSize;
+}
+public boolean isAddingNewLineBeforeOpeningBrace() {
+ return newLineBeforeOpeningBraceMode;
+}
+public boolean isAddingNewLineInControlStatement() {
+ return newlineInControlStatementMode;
+}
+public boolean isAddingNewLineInEmptyBlock() {
+ return newLineInEmptyBlockMode;
+}
+public boolean isClearingAllBlankLines() {
+ return clearAllBlankLinesMode;
+}
+public boolean isCompactingAssignment() {
+ return compactAssignmentMode;
+}
+public boolean isCompactingElseIf() {
+ return compactElseIfMode;
+}
+public boolean isUsingTabForIndenting() {
+ return indentWithTab;
+}
+public void setLineSeparator(String lineSeparator) {
+ lineSeparatorSequence = lineSeparator.toCharArray();
+}
+/**
+ * @deprecated - should use a Map when creating the options.
+ */
+public void setMaxLineLength(int maxLineLength) {
+ this.maxLineLength = maxLineLength;
+}
+/**
+ * @deprecated - should use a Map when creating the options.
+ */
+public void setCompactElseIfMode(boolean flag) {
+ compactElseIfMode = flag;
+}
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.phpeclipse.phpdt.internal.formatter.impl;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+
+/** Represents a split line: contains an operator and all substrings
+*/
+public class SplitLine implements ITerminalSymbols{
+ public int[] operators; // the operator on which the string was split.
+ public String[] substrings;
+ public int[] startSubstringsIndexes;
+/**
+ * SplitLine constructor comment.
+ */
+public SplitLine(int[] operators, String[] substrings) {
+ this(operators, substrings, null);
+}
+/**
+ * SplitLine constructor comment.
+ */
+public SplitLine(int[] operators, String[] substrings, int[] startIndexes) {
+ super();
+ this.operators=operators;
+ this.substrings=substrings;
+ this.startSubstringsIndexes = startIndexes;
+}
+/**
+ * Prints a nice representation of the receiver
+ * @return java.lang.String
+ */
+public String toString() {
+ StringBuffer result=new StringBuffer();
+ String operatorString = new String();
+
+ for (int i=0,max=substrings.length;i<max;i++){
+ int currentOperator = operators[i];
+ String currentString = substrings[i];
+ boolean placeOperatorAhead = currentOperator != TokenNameCOMMA && currentOperator != TokenNameSEMICOLON;
+ boolean placeOperatorBehind = currentOperator == TokenNameCOMMA || currentOperator == TokenNameSEMICOLON;
+
+
+
+ switch (currentOperator){
+ case TokenNameextends:
+ operatorString="extends"; //$NON-NLS-1$
+ break;
+// case TokenNameimplements:
+// operatorString="implements"; //$NON-NLS-1$
+// break;
+// case TokenNamethrows:
+// operatorString="throws"; //$NON-NLS-1$
+// break;
+ case TokenNameSEMICOLON : // ;
+ operatorString=";"; //$NON-NLS-1$
+ break;
+ case TokenNameCOMMA : // ,
+ operatorString=","; //$NON-NLS-1$
+ break;
+ case TokenNameEQUAL : // =
+ operatorString="="; //$NON-NLS-1$
+ break;
+ case TokenNameAND_AND : // && (15.22)
+ operatorString="&&"; //$NON-NLS-1$
+ break;
+ case TokenNameOR_OR : // || (15.23)
+ operatorString="||"; //$NON-NLS-1$
+ break;
+ case TokenNameQUESTION : // ? (15.24)
+ operatorString="?"; //$NON-NLS-1$
+ break;
+
+ case TokenNameCOLON : // : (15.24)
+ operatorString=":"; //$NON-NLS-1$
+ break;
+ case TokenNameEQUAL_EQUAL : // == (15.20, 15.20.1, 15.20.2, 15.20.3)
+ operatorString="=="; //$NON-NLS-1$
+ break;
+
+ case TokenNameNOT_EQUAL : // != (15.20, 15.20.1, 15.20.2, 15.20.3)
+ operatorString="!="; //$NON-NLS-1$
+ break;
+
+ case TokenNameLESS : // < (15.19.1)
+ operatorString="<"; //$NON-NLS-1$
+ break;
+
+ case TokenNameLESS_EQUAL : // <= (15.19.1)
+ operatorString="<="; //$NON-NLS-1$
+ break;
+
+ case TokenNameGREATER : // > (15.19.1)
+ operatorString=">"; //$NON-NLS-1$
+ break;
+
+ case TokenNameGREATER_EQUAL : // >= (15.19.1)
+ operatorString=">="; //$NON-NLS-1$
+ break;
+
+// case TokenNameinstanceof : // instanceof
+// operatorString="instanceof"; //$NON-NLS-1$
+// break;
+ case TokenNamePLUS : // + (15.17, 15.17.2)
+ operatorString="+"; //$NON-NLS-1$
+ break;
+
+ case TokenNameMINUS : // - (15.17.2)
+ operatorString="-"; //$NON-NLS-1$
+ break;
+ case TokenNameMULTIPLY : // * (15.16.1)
+ operatorString="*"; //$NON-NLS-1$
+ break;
+
+ case TokenNameDIVIDE : // / (15.16.2)
+ operatorString="/"; //$NON-NLS-1$
+ break;
+
+ case TokenNameREMAINDER : // % (15.16.3)
+ operatorString="%"; //$NON-NLS-1$
+ break;
+ case TokenNameLEFT_SHIFT : // << (15.18)
+ operatorString="<<"; //$NON-NLS-1$
+ break;
+
+ case TokenNameRIGHT_SHIFT : // >> (15.18)
+ operatorString=">>"; //$NON-NLS-1$
+ break;
+
+// case TokenNameUNSIGNED_RIGHT_SHIFT : // >>> (15.18)
+// operatorString=">>>"; //$NON-NLS-1$
+// break;
+ case TokenNameAND : // & (15.21, 15.21.1, 15.21.2)
+ operatorString="&"; //$NON-NLS-1$
+ break;
+
+ case TokenNameOR : // | (15.21, 15.21.1, 15.21.2)
+ operatorString="|"; //$NON-NLS-1$
+ break;
+
+ case TokenNameXOR : // ^ (15.21, 15.21.1, 15.21.2)
+ operatorString="^"; //$NON-NLS-1$
+ break;
+ case TokenNameMULTIPLY_EQUAL : // *= (15.25.2)
+ operatorString="*="; //$NON-NLS-1$
+ break;
+
+ case TokenNameDIVIDE_EQUAL : // /= (15.25.2)
+ operatorString="/="; //$NON-NLS-1$
+ break;
+ case TokenNameREMAINDER_EQUAL : // %= (15.25.2)
+ operatorString="%="; //$NON-NLS-1$
+ break;
+
+ case TokenNamePLUS_EQUAL : // += (15.25.2)
+ operatorString="+="; //$NON-NLS-1$
+ break;
+
+ case TokenNameMINUS_EQUAL : // -= (15.25.2)
+ operatorString="-="; //$NON-NLS-1$
+ break;
+
+ case TokenNameLEFT_SHIFT_EQUAL : // <<= (15.25.2)
+ operatorString="<<="; //$NON-NLS-1$
+ break;
+
+ case TokenNameRIGHT_SHIFT_EQUAL : // >>= (15.25.2)
+ operatorString=">>="; //$NON-NLS-1$
+ break;
+
+// case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>= (15.25.2)
+// operatorString=">>>="; //$NON-NLS-1$
+// break;
+
+ case TokenNameAND_EQUAL : // &= (15.25.2)
+ operatorString="&="; //$NON-NLS-1$
+ break;
+
+ case TokenNameXOR_EQUAL : // ^= (15.25.2)
+ operatorString="^="; //$NON-NLS-1$
+ break;
+
+ case TokenNameOR_EQUAL : // |= (15.25.2)
+ operatorString="|="; //$NON-NLS-1$
+ break;
+ case TokenNameDOT : // .
+ operatorString="."; //$NON-NLS-1$
+ break;
+
+ default:
+ operatorString=""; //$NON-NLS-1$
+ }
+ if (placeOperatorAhead){
+ result.append(operatorString);
+ }
+ result.append(currentString);
+ if (placeOperatorBehind){
+ result.append(operatorString);
+ }
+ result.append('\n');
+ }
+ return ""; //$NON-NLS-1$
+}
+}