Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipe Mulet2001-08-31 11:31:58 +0000
committerPhilipe Mulet2001-08-31 11:31:58 +0000
commitbecb90e1558665e7eb78bdc22fe7887be60ce94e (patch)
tree663e3489d987b2c84a7be6d798b230f80b19ebc2
parent920183be55fd3129494ea2f8098d4170b355398c (diff)
downloadeclipse.jdt.core-becb90e1558665e7eb78bdc22fe7887be60ce94e.tar.gz
eclipse.jdt.core-becb90e1558665e7eb78bdc22fe7887be60ce94e.tar.xz
eclipse.jdt.core-becb90e1558665e7eb78bdc22fe7887be60ce94e.zip
*** empty log message ***
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java4
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java4536
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/BatchImageBuilder.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/IncrementalImageBuilder.java2
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/JavaDevelopmentContextImpl.java9
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/StateImpl.java1
6 files changed, 2270 insertions, 2286 deletions
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index 15fadba2fb..9df13c0b57 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -4,7 +4,7 @@ package org.eclipse.jdt.internal.codeassist;
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
-import java.util.Locale;
+import java.util.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.env.*;
@@ -58,7 +58,7 @@ public final class SelectionEngine extends Engine implements ISearchRequestor {
* set of options used to configure the code assist engine.
*/
-public SelectionEngine(ISearchableNameEnvironment nameEnvironment, ISelectionRequestor requestor, ConfigurableOption[] settings) {
+public SelectionEngine(ISearchableNameEnvironment nameEnvironment, ISelectionRequestor requestor, Map settings) {
this.requestor = requestor;
this.nameEnvironment = nameEnvironment;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
index 5ac820c496..3850710a09 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
@@ -9,2289 +9,2273 @@ import org.eclipse.jdt.internal.compiler.parser.InvalidInputException;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.parser.TerminalSymbols;
-import org.eclipse.jdt.internal.compiler.ConfigurableOption;
import org.eclipse.jdt.internal.formatter.impl.FormatterOptions;
import org.eclipse.jdt.internal.formatter.impl.SplitLine;
-import java.util.Locale;
+import java.util.*;
+
/** <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 TerminalSymbols {
- public FormatterOptions options;
-
- /**
- * Represents a block in the <code>constructions</code> stack.
- */
- public static final int BLOCK = TerminalSymbols.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;
-/**
- * Creates a new instance of Code Formatter using the FormattingOptions object
- * given as argument
- * @deprecated Use CodeFormatter(ConfigurableOption[]) instead
- */
-public CodeFormatter() {
- this(null);
-}
-/**
- * Creates a new instance of Code Formatter using the given settings.
- */
-public CodeFormatter(ConfigurableOption[] settings) {
-
- // initialize internal state
- constructionsCount = 0;
- constructions = new int[10];
- currentLineIndentationLevel = indentationLevel = initialIndentationLevel;
- currentCommentOffset = -1;
-
- // initialize primary and secondary scanners
- scanner = new Scanner(true,true); // regular scanner for forming lines
- scanner.recordLineSeparator = true; // to remind of the position of the beginning of the line.
- splitScanner = new Scanner(true,true); // secondary scanner to split long lines formed by primary scanning
-
- // initialize current line buffer
- currentLineBuffer = new StringBuffer();
- this.options = new FormatterOptions(settings);
-}
-/**
- * Sets the behaviour of the formatter about the braces using the given flag.<br>
- * <ul>
- * <li>if true, the formatter add new line & indent before the opening brace.
- * <li>if false, the formatter leaves the brace on the same line.
- * </ul>
- * @deprecated backward compatibility with VAJ
- */
-
- /** */
-public void addNewLineOnOpeningBrace(boolean flag) {
- options.setNewLineBeforeOpeningBraceMode(flag);
-}
-/**
- * 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;
- }
-}
-/**
- * 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 (options.maxLineLength!=0){
- if (containsOpenCloseBraces) {
- containsOpenCloseBraces = false;
- outputLine(currentString,
- false,
- indentationLevelForOpenCloseBraces,
- 0,
- -1,
- null,
- 0);
- indentationLevelForOpenCloseBraces = currentLineIndentationLevel;
- } else {
- outputLine(currentString,
- false,
- currentLineIndentationLevel,
- 0,
- -1,
- null,
- 0);
- }
- } else {
- formattedSource.append(currentString);
- }
-}
-/**
- * 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();
- } 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) {
- 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) {
- pendingNewLines =
- (pendingNewLines < newLinesInWhitespace)
-// (isComment(token))
- ? 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_JAVADOC) && 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 :
-
- // 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;
- 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 :
- 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_JAVADOC :
- 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] == '\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;
-
- // to be replaced by a nicer condition.
-
- 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_JAVADOC) {
- 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 a given source string, starting indenting it at depth 0
- * using default options.
- */
-public static String format(String sourceString) {
- return format(sourceString, 0, null);
-}
-/**
- * Formats a given source string, starting indenting it at a particular
- * depth and using the given options
- */
-public static String format(String sourceString, int initialIndentationLevel, ConfigurableOption[] options) {
- CodeFormatter formatter = new CodeFormatter(options);
- formatter.setInitialIndentationLevel(initialIndentationLevel);
- return formatter.formatSourceString(sourceString);
-}
-/**
- * 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.setSourceBuffer(sourceChars);
- format();
- return formattedSource.toString();
-}
-/**
- * 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 = beginningOfLine ; i < currentStartPosition ; i++){
- char currentCharacter = source[i];
- switch(currentCharacter){
- case '\t':
- offset += options.tabSize;
- case '\n':
- case '\r':
- break;
- default:
- offset++;
- }
- }
-
- return offset;
-}
-/**
- * Returns all the options of the Code Formatter to be shown by the UI
- *
- * @param locale java.util.Locale
- * @return org.eclipse.jdt.internal.compiler.java.ConfigurableOption[]
- */
-public static ConfigurableOption[] getDefaultOptions(Locale locale) {
- String[] ids = ConfigurableOption.getIDs(CodeFormatter.class.getName(),locale);
-
- ConfigurableOption[] result = new ConfigurableOption[ids.length];
- for(int i = 0 ; i < ids.length ; i++){
- result[i] = new ConfigurableOption(ids[i],locale);
- }
-
- return result;
-}
-/**
- * Returns the array of mapped positions.
- * Returns null is no positions have been set.
- * @return int[]
- */
-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_JAVADOC;
- 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);
- }
- }
- updateMappedPositions(scanner.startPosition);
-}
-/**
- * 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_JAVADOC :
- case Scanner.TokenNameCOMMENT_BLOCK :
- case Scanner.TokenNameCOMMENT_LINE :
- boolean endOfLine = false;
- int currentCommentOffset = getCurrentCommentOffset();
- int beginningOfLineSpaces = 0;
- for (int i = startPosition, max = scanner.currentPosition; i < max; i++) {
- char currentCharacter = source[i];
- switch(currentCharacter) {
- case '\r' :
- case '\n' :
- endOfLine = true;
- currentLineBuffer.append(currentCharacter);
- beginningOfLineSpaces = 0;
- break;
- case '\t' :
- 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 {
- currentLineBuffer.append(currentCharacter);
- }
- break;
- case ' ' :
- if (endOfLine) {
- // we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
- beginningOfLineSpaces++;
- if (beginningOfLineSpaces > currentCommentOffset)
- currentLineBuffer.append(currentCharacter);
- } else {
- currentLineBuffer.append(currentCharacter);
- }
- break;
- default:
- beginningOfLineSpaces = 0;
- currentLineBuffer.append(currentCharacter);
- endOfLine = false;
- }
- }
- break;
- default:
- currentLineBuffer.append(source, startPosition, scanner.currentPosition - startPosition);
- }
- updateMappedPositions(startPosition);
-}
-/**
- * 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
- || currentString.length() < 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);
- }
- }
-
- boolean containsMultiLineComment = currentString.lastIndexOf("/*") != -1; //$NON-NLS-1$
- int numberOfSpaces = 0;
- int max = currentString.length();
- 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);
- increaseSplitDelta(options.lineSeparatorSequence.length);
-
- if (containsMultiLineComment) {
- // fix for 1FGGQCN: LFCOM:ALL - Space management in comments for the formatter
- dumpTab(currentLineIndentationLevel);
- } else {
- // 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) {
- 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;
- int[] splitLineStartIndexes = splitLine.startSubstringsIndexes;
-
- 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("/*") || currentResult.startsWith("//")) //$NON-NLS-2$ //$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;
-}
-/**
- * Sets the behaviour of the formatter about the braces
- * using <coe>newBraceIndentationLevel</code><br>
- * <ul>
- * <li>if 0, the formatter add new line & indent
- * when current token is open brace,
- * remove extra indentation when current token is close brace.
- * <li>if -1, the formatter does not add a new line before the brace.</ul>
- *
- * @deprecated backward compatibility with VAJ APIs,
- * use addNewLineOnOpeningBrace(boolean) instead
- * @see addNewLineOnOpeningBrace(boolean)
- */
-public void setBraceIndentationLevel(int newBraceIndentationLevel) {
- options.setNewLineBeforeOpeningBraceMode(newBraceIndentationLevel==0);
-}
-/**
- * Sets the behaviour of the formatter regarding the whitespaces
- * in the string to format.
- * @param newClearBlankLines true if the blank lines can be wiped out
- * false otherwise.
- *
- * @deprecated backward compatibility with VAJ
- */
-public void setClearBlankLines(boolean newClearBlankLines) {
- options.setClearAllBlankLinesMode(newClearBlankLines);
-}
-/**
- * Sets the number of consecutive spaces used to replace the tab char
- * if <code>newIndentationLength</code> is greater than one.<br>
- * @param newIndentationLength 1 if 1 indent = 1 tab char, n>1 if 1 indent = n consecutive spaces.
- *
- * @deprecated backward compatibility with VAJ
- */
-public void setIndentationLength(int newIndentationLength) {
- options.setTabSize(newIndentationLength);
-}
-/**
- * Sets the initial indentation level
- * @param indentationLevel new indentation level
- *
- * @deprecated
- */
-public void setInitialIndentationLevel(int newIndentationLevel) {
- this.initialIndentationLevel = currentLineIndentationLevel = indentationLevel = newIndentationLevel;
-}
-/**
- * Sets the behaviour of the scanner.<br>
- * if <code>flag</code> is true, newline & indent won't be added
- * between close brace and else, (do) while, catch, and finally.
- * @param flag must be true if newline & indent must NOT
- * be added between close brace and else, (do) while,
- * catch, and finally, false otherwise.
- *
- * @deprecated backward compatibility with VAJ
- */
-public void setNewlineInCompoundStatement(boolean flag) {
- options.setNewlineInControlStatementMode(flag);
-}
-/**
- * Set the positions to map. The mapped positions should be retrieved using the
- * getMappedPositions() method.
- * @see getMappedPositions()
- * @param positions int[]
- */
-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) {
- // 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.setSourceBuffer(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
- indexToMap = positionsToMap.length; // no more mapping
- return;
- }
- if (Character.isWhitespace(source[posToMap])) {
- 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++;
- }
-}
-}
+ public FormatterOptions options;
+
+ /**
+ * Represents a block in the <code>constructions</code> stack.
+ */
+ public static final int BLOCK = TerminalSymbols.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;
+
+ /**
+ * Creates a new instance of Code Formatter using the FormattingOptions object
+ * given as argument
+ * @deprecated Use CodeFormatter(ConfigurableOption[]) instead
+ */
+ public CodeFormatter() {
+ this(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, true); // regular scanner for forming lines
+ scanner.recordLineSeparator = true;
+ // to remind of the position of the beginning of the line.
+ splitScanner = new Scanner(true, true);
+ // 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;
+ }
+ }
+
+ /**
+ * 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 (options.maxLineLength != 0) {
+ if (containsOpenCloseBraces) {
+ containsOpenCloseBraces = false;
+ outputLine(
+ currentString,
+ false,
+ indentationLevelForOpenCloseBraces,
+ 0,
+ -1,
+ null,
+ 0);
+ indentationLevelForOpenCloseBraces = currentLineIndentationLevel;
+ } else {
+ outputLine(currentString, false, currentLineIndentationLevel, 0, -1, null, 0);
+ }
+ } else {
+ formattedSource.append(currentString);
+ }
+ }
+
+ /**
+ * 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();
+ } 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) {
+ 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_JAVADOC)
+ && 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 :
+
+ // 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;
+ 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 :
+ 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_JAVADOC :
+ 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] == '\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_JAVADOC) {
+ 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 a given source string, starting indenting it at depth 0
+ * using default options.
+ */
+ public static String format(String sourceString) {
+ return format(sourceString, 0, null);
+ }
+
+ /**
+ * Formats a given source string, starting indenting it at a particular
+ * depth and using the given options
+ */
+ public static String format(
+ String sourceString,
+ int initialIndentationLevel,
+ Map options) {
+ CodeFormatter formatter = new CodeFormatter(options);
+ formatter.setInitialIndentationLevel(initialIndentationLevel);
+ return formatter.formatSourceString(sourceString);
+ }
+
+ /**
+ * 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.setSourceBuffer(sourceChars);
+ format();
+ return formattedSource.toString();
+ }
+
+ /**
+ * 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 = beginningOfLine; i < currentStartPosition; i++) {
+ char currentCharacter = source[i];
+ switch (currentCharacter) {
+ case '\t' :
+ offset += options.tabSize;
+ case '\n' :
+ case '\r' :
+ break;
+ default :
+ offset++;
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Returns the array of mapped positions.
+ * Returns null is no positions have been set.
+ * @return int[]
+ */
+ 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_JAVADOC;
+ 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);
+ }
+ }
+ updateMappedPositions(scanner.startPosition);
+ }
+
+ /**
+ * 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_JAVADOC :
+ case Scanner.TokenNameCOMMENT_BLOCK :
+ case Scanner.TokenNameCOMMENT_LINE :
+ boolean endOfLine = false;
+ int currentCommentOffset = getCurrentCommentOffset();
+ int beginningOfLineSpaces = 0;
+ for (int i = startPosition, max = scanner.currentPosition; i < max; i++) {
+ char currentCharacter = source[i];
+ switch (currentCharacter) {
+ case '\r' :
+ case '\n' :
+ endOfLine = true;
+ currentLineBuffer.append(currentCharacter);
+ beginningOfLineSpaces = 0;
+ break;
+ case '\t' :
+ 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 {
+ currentLineBuffer.append(currentCharacter);
+ }
+ break;
+ case ' ' :
+ if (endOfLine) {
+ // we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
+ beginningOfLineSpaces++;
+ if (beginningOfLineSpaces > currentCommentOffset)
+ currentLineBuffer.append(currentCharacter);
+ } else {
+ currentLineBuffer.append(currentCharacter);
+ }
+ break;
+ default :
+ beginningOfLineSpaces = 0;
+ currentLineBuffer.append(currentCharacter);
+ endOfLine = false;
+ }
+ }
+ break;
+ default :
+ currentLineBuffer.append(
+ source,
+ startPosition,
+ scanner.currentPosition - startPosition);
+ }
+ updateMappedPositions(startPosition);
+ }
+
+ /**
+ * 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
+ || currentString.length() < 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);
+ }
+ }
+ boolean containsMultiLineComment = currentString.lastIndexOf("/*") != -1; //$NON-NLS-1$
+ int numberOfSpaces = 0;
+ int max = currentString.length();
+ 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);
+ increaseSplitDelta(options.lineSeparatorSequence.length);
+
+ if (containsMultiLineComment) {
+ // fix for 1FGGQCN: LFCOM:ALL - Space management in comments for the formatter
+ dumpTab(currentLineIndentationLevel);
+ } else {
+ // 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) {
+ 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;
+ int[] splitLineStartIndexes = splitLine.startSubstringsIndexes;
+
+ 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.
+ * @see getMappedPositions()
+ * @param positions int[]
+ */
+ 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) {
+ // 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.setSourceBuffer(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
+ indexToMap = positionsToMap.length; // no more mapping
+ return;
+ }
+ if (Character.isWhitespace(source[posToMap])) {
+ 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++;
+ }
+ }
+
+ /**
+ * 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
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/BatchImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/BatchImageBuilder.java
index 4b6e2c2b90..e15cb344c5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/BatchImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/BatchImageBuilder.java
@@ -4,9 +4,9 @@ package org.eclipse.jdt.internal.core.builder.impl;
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
+import java.util.Map;
import java.util.Vector;
-import org.eclipse.jdt.internal.compiler.ConfigurableOption;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.core.Assert;
import org.eclipse.jdt.internal.core.Util;
@@ -37,7 +37,7 @@ public BatchImageBuilder(StateImpl state) {
* This constructor has been created for testing purposes. This allows
* tests to control the compiler options used by the batch build.
*/
-protected BatchImageBuilder(StateImpl state, ConfigurableOption[] options) {
+protected BatchImageBuilder(StateImpl state, Map options) {
fDC = (JavaDevelopmentContextImpl) state.getDevelopmentContext();
fCompilerOptions = options;
fNewState = state;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/IncrementalImageBuilder.java
index 398878fa64..3e2ac54e53 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/IncrementalImageBuilder.java
@@ -203,7 +203,7 @@ public void applySourceDelta(Hashtable deltas) {
fNewState = fOldState.copy(fNewProject, fImageContext);
// options might have changed since last builder run, thus refresh them
- fCompilerOptions = JavaModelManager.getOptions();
+ fCompilerOptions = JavaCore.getOptions();
try {
/* find out what has changed at the package level */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/JavaDevelopmentContextImpl.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/JavaDevelopmentContextImpl.java
index 118f597b18..67fb6b46c8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/JavaDevelopmentContextImpl.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/JavaDevelopmentContextImpl.java
@@ -9,6 +9,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
+import java.util.Map;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
@@ -16,8 +17,8 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.ConfigurableOption;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.core.Util;
@@ -139,7 +140,7 @@ public IImageBuilder createState(IProject project, IImageContext buildContext, I
/**
* @see IDevelopmentContext
*/
-public IImageBuilder createState(IProject project, IImageContext buildContext, IProblemReporter problemReporter, ConfigurableOption[] compilerOptions) {
+public IImageBuilder createState(IProject project, IImageContext buildContext, IProblemReporter problemReporter, Map compilerOptions) {
StateImpl state = new StateImpl(this, project, buildContext);
BatchImageBuilder builder = new BatchImageBuilder(state, compilerOptions);
if (problemReporter != null) {
@@ -204,8 +205,8 @@ public IState getCurrentState() throws NotPresentException {
/**
* Reads the default compiler options.
*/
-protected static ConfigurableOption[] getDefaultCompilerOptions() {
- return JavaModelManager.getOptions();
+protected static Map getDefaultCompilerOptions() {
+ return JavaCore.getOptions();
}
/**
* Returns the default package handle (java.lang).
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/StateImpl.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/StateImpl.java
index b22c4dcabe..24d7dc99d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/StateImpl.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/impl/StateImpl.java
@@ -35,7 +35,6 @@ import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ConfigurableOption;
import org.eclipse.jdt.internal.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;

Back to the top