diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/antlr/GroovyTokenTypeBridge.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/antlr/GroovyTokenTypeBridge.java index 4fee07245b..da3e5c7898 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/antlr/GroovyTokenTypeBridge.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/antlr/GroovyTokenTypeBridge.java @@ -34,27 +34,69 @@ public class GroovyTokenTypeBridge { // Only the GroovyTokenTypes that we use inside Greclipse are represented here. // More can be added on an as needed basis. - public static int IDENT = GroovyTokenTypes.IDENT; - public static int LBRACK = GroovyTokenTypes.LBRACK; - public static int LCURLY = GroovyTokenTypes.LCURLY; - public static int LPAREN = GroovyTokenTypes.LPAREN; - public static int RPAREN = GroovyTokenTypes.RPAREN; - public static int RBRACK = GroovyTokenTypes.RBRACK; - public static int RCURLY = GroovyTokenTypes.RCURLY; - public static int STRING_CTOR_START = GroovyTokenTypes.STRING_CTOR_START; - public static int STRING_CTOR_END = GroovyTokenTypes.STRING_CTOR_END; - public static int COMMA = GroovyTokenTypes.COMMA; - public static int SEMI = GroovyTokenTypes.SEMI; - public static int EOF = GroovyTokenTypes.EOF; - public static int NLS = GroovyTokenTypes.NLS; - public static int WS = GroovyTokenTypes.WS; - public static int ML_COMMENT = GroovyTokenTypes.ML_COMMENT; - public static int SL_COMMENT = GroovyTokenTypes.SL_COMMENT; - public static int CLOSABLE_BLOCK_OP = GroovyTokenTypes.CLOSABLE_BLOCK_OP; - public static int LITERAL_as = GroovyTokenTypes.LITERAL_as; - public static int LITERAL_if = GroovyTokenTypes.LITERAL_if; - public static int LITERAL_else = GroovyTokenTypes.LITERAL_else; - public static int LITERAL_for = GroovyTokenTypes.LITERAL_for; - public static int LITERAL_switch = GroovyTokenTypes.LITERAL_switch; - public static int LITERAL_while = GroovyTokenTypes.LITERAL_while; + public static int ASSIGN = GroovyTokenTypes.ASSIGN; + public static int IDENT = GroovyTokenTypes.IDENT; + public static int LBRACK = GroovyTokenTypes.LBRACK; + public static int LCURLY = GroovyTokenTypes.LCURLY; + public static int LPAREN = GroovyTokenTypes.LPAREN; + public static int RPAREN = GroovyTokenTypes.RPAREN; + public static int RBRACK = GroovyTokenTypes.RBRACK; + public static int RCURLY = GroovyTokenTypes.RCURLY; + public static int STRING_CTOR_START = GroovyTokenTypes.STRING_CTOR_START; + public static int STRING_CTOR_END = GroovyTokenTypes.STRING_CTOR_END; + public static int COMMA = GroovyTokenTypes.COMMA; + public static int SEMI = GroovyTokenTypes.SEMI; + public static int EOF = GroovyTokenTypes.EOF; + public static int NLS = GroovyTokenTypes.NLS; + public static int WS = GroovyTokenTypes.WS; + public static int ML_COMMENT = GroovyTokenTypes.ML_COMMENT; + public static int SL_COMMENT = GroovyTokenTypes.SL_COMMENT; + public static int CLOSABLE_BLOCK_OP = GroovyTokenTypes.CLOSABLE_BLOCK_OP; + public static int LITERAL_as = GroovyTokenTypes.LITERAL_as; + public static int GT = GroovyTokenTypes.GT; + public static int LT = GroovyTokenTypes.LT; + public static int GE = GroovyTokenTypes.GE; + public static int LE = GroovyTokenTypes.LE; + public static int LITERAL_if = GroovyTokenTypes.LITERAL_if; + public static int LITERAL_else = GroovyTokenTypes.LITERAL_else; + public static int LITERAL_for = GroovyTokenTypes.LITERAL_for; + public static int LITERAL_switch = GroovyTokenTypes.LITERAL_switch; + public static int LITERAL_while = GroovyTokenTypes.LITERAL_while; + public static int LITERAL_class = GroovyTokenTypes.LITERAL_class; + public static int LITERAL_interface = GroovyTokenTypes.LITERAL_interface; + public static int LITERAL_public = GroovyTokenTypes.LITERAL_public; + public static int LITERAL_private = GroovyTokenTypes.LITERAL_private; + public static int LITERAL_protected = GroovyTokenTypes.LITERAL_protected; + public static int LITERAL_assert = GroovyTokenTypes.LITERAL_assert; + public static int LITERAL_def = GroovyTokenTypes.LITERAL_def; + public static int LITERAL_transient = GroovyTokenTypes.LITERAL_transient; + public static int LITERAL_native = GroovyTokenTypes.LITERAL_native; + public static int LITERAL_threadsafe = GroovyTokenTypes.LITERAL_threadsafe; + public static int LITERAL_synchronized = GroovyTokenTypes.LITERAL_synchronized; + public static int LITERAL_volatile = GroovyTokenTypes.LITERAL_volatile; + public static int LITERAL_static = GroovyTokenTypes.LITERAL_static; + public static int LITERAL_package = GroovyTokenTypes.LITERAL_package; + public static int LITERAL_extends = GroovyTokenTypes.LITERAL_extends; + public static int LITERAL_implements = GroovyTokenTypes.LITERAL_implements; + public static int LITERAL_return = GroovyTokenTypes.LITERAL_return; + public static int LITERAL_void = GroovyTokenTypes.LITERAL_void; + public static int LITERAL_boolean = GroovyTokenTypes.LITERAL_boolean; + public static int LITERAL_byte = GroovyTokenTypes.LITERAL_byte; + public static int LITERAL_char = GroovyTokenTypes.LITERAL_char; + public static int LITERAL_short = GroovyTokenTypes.LITERAL_short; + public static int LITERAL_int = GroovyTokenTypes.LITERAL_int; + public static int LITERAL_float = GroovyTokenTypes.LITERAL_float; + public static int LITERAL_long = GroovyTokenTypes.LITERAL_long; + public static int LITERAL_double = GroovyTokenTypes.LITERAL_double; + public static int ABSTRACT = GroovyTokenTypes.ABSTRACT; + public static int NOT_EQUAL = GroovyTokenTypes.NOT_EQUAL; + public static int EQUAL = GroovyTokenTypes.EQUAL; + public static int NUM_INT = GroovyTokenTypes.NUM_INT; + public static int NUM_FLOAT = GroovyTokenTypes.NUM_FLOAT; + public static int NUM_LONG = GroovyTokenTypes.NUM_LONG; + public static int NUM_DOUBLE = GroovyTokenTypes.NUM_DOUBLE; + public static int NUM_BIG_INT = GroovyTokenTypes.NUM_BIG_INT; + public static int NUM_BIG_DECIMAL = GroovyTokenTypes.NUM_BIG_DECIMAL; + public static int STRING_LITERAL = GroovyTokenTypes.STRING_LITERAL; + public static int COLON = GroovyTokenTypes.COLON; } diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Braces_Empty_GRE_1618.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Braces_Empty_GRE_1618.txt index b7074a09cb..e7d265f358 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Braces_Empty_GRE_1618.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Braces_Empty_GRE_1618.txt @@ -13,9 +13,9 @@ def test1 () { ###exp class FormatTest { - def test () {} + def test() {} - def test1 () { + def test1() { } } ###end \ No newline at end of file diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Closure3.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Closure3.txt index 42f5cae016..12143cfd6c 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Closure3.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_Closure3.txt @@ -8,7 +8,7 @@ def foo= { -> } foo() ###exp -def foo= { +def foo = { -> if(true) { // fragile! diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_1410.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_1410.txt index ec21fcb784..49f1a89a8f 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_1410.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_1410.txt @@ -7,7 +7,7 @@ setPreferences=true ] ###exp [ - a:1, - b:2 + a: 1, + b: 2 ] ###end \ No newline at end of file diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_921.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_921.txt index 44732c07e3..712fc3b283 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_921.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_GRE_921.txt @@ -11,7 +11,7 @@ def message = "${foo([])}" ###exp class FormatTest { - def test () { + def test() { def message = "${foo([])}" } } diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineMethodParams2.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineMethodParams2.txt index 865a6a92b9..8462d3c00f 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineMethodParams2.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineMethodParams2.txt @@ -33,12 +33,12 @@ b) { class SomeClass { @Blart( - value1='', - value2='', - value3='' + value1 = '', + value2 = '', + value3 = '' ) def foo( - s,j, + s, j, k) { } diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineStatements4.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineStatements4.txt index 6026ad7cec..c83dbac02f 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineStatements4.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_MultilineStatements4.txt @@ -9,8 +9,8 @@ println 'hello' } ###exp -String appPath,controller,clazz -new File(appPath,controller).eachLine { String line-> +String appPath, controller, clazz +new File(appPath, controller).eachLine { String line-> if(line=~/def index = \{ \}/) { // fragile! println 'hello' diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_closure_in_GString.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_closure_in_GString.txt index ffc68d95bd..7126f6290f 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_closure_in_GString.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_closure_in_GString.txt @@ -14,7 +14,7 @@ println "hoi" ###exp class Bongo { - def FLAVOURS = [all:'.all',tiny:'.tiny',form:'.form'] + def FLAVOURS = [all: '.all', tiny: '.tiny', form: '.form'] def a = "Flavour must be in: ${FLAVOURS.collect{it.key}}" def main() { diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_duplicate_spaces.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_duplicate_spaces.txt new file mode 100644 index 0000000000..9e1b859513 --- /dev/null +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_duplicate_spaces.txt @@ -0,0 +1,45 @@ +###prop +setPreferences=true +bracesEnd=next +###src +package org.test + +public abstract class EmailCommand extends Command implements Serializable , ICommand { + @Annotation ( value = "test" , a=1 ) + @Annotation2 ( ) + @Annotation3( "test" ) + def foo ( int a , Map> collection ) { + def array = [ 1, 2 ] + + if ( array.length >= 3 ) { + println "test" + } + + def a=i<2 + def b=1<2 + + return 1 <2 && 2>= 1 + } +} +###exp +package org.test + +public abstract class EmailCommand extends Command implements Serializable, + ICommand { + @Annotation(value = "test", a = 1) + @Annotation2() + @Annotation3("test") + def foo(int a, Map> collection) { + def array = [1, 2] + + if (array.length >= 3) { + println "test" + } + + def a = i<2 + def b = 1<2 + + return 1 <2 && 2 >= 1 + } +} +###end \ No newline at end of file diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_spaced_out.txt b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_spaced_out.txt index db39297ee9..bf867a05b3 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_spaced_out.txt +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/Formatter/Formatter_Test_spaced_out.txt @@ -14,7 +14,7 @@ class EmailCommand { } ###exp class EmailCommand { - def foo () { + def foo() { return 1 } } diff --git a/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/DefaultGroovyFormatter.java b/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/DefaultGroovyFormatter.java index 69653cfc17..b427bdb2f2 100644 --- a/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/DefaultGroovyFormatter.java +++ b/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/DefaultGroovyFormatter.java @@ -49,6 +49,8 @@ @SuppressWarnings("deprecation") public class DefaultGroovyFormatter extends GroovyFormatter { + private static final boolean DEBUG = true; + protected IFormatterPreferences pref; private ModuleNode rootNode; @@ -139,6 +141,10 @@ public TextEdit format() { GroovyCore.logWarning("Cannot format, probably due to compilation errors. Please fix and try again.", e); } + if (DEBUG) { + System.out.println(formattedDocument.get()); + } + if (formattedDocument.get().equals(document.get())) { return new MultiTextEdit(); } diff --git a/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/GroovyBeautifier.java b/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/GroovyBeautifier.java index 35c5e48ca8..78688d84c6 100644 --- a/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/GroovyBeautifier.java +++ b/ide/org.codehaus.groovy.eclipse.refactoring/src/org/codehaus/groovy/eclipse/refactoring/formatter/GroovyBeautifier.java @@ -15,6 +15,7 @@ */ package org.codehaus.groovy.eclipse.refactoring.formatter; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -66,6 +67,8 @@ public TextEdit getBeautifiEdits() throws BadLocationException { formatLists(edits); correctBraces(edits); removeUnnecessarySemicolons(edits); + removeUnnecessaryWhitespace(edits); + addAdditionalSpacing(edits); return edits; } finally { @@ -163,13 +166,13 @@ private void formatLists(MultiTextEdit edits) { while (before.getType() != GroovyTokenTypeBridge.LBRACK && before.getType() != GroovyTokenTypeBridge.COMMA) { before = tokens.getLastTokenBefore(before); } - replaceWhiteSpaceAfter(edits, before, formatter.getNewLine()); + replaceWhiteSpaceAfter(edits, before, formatter.getNewLine(), true, true); } catch (BadLocationException e) { GroovyCore.logException("Trouble formatting list", e); } } if (!nextTokenAs) { - replaceWhiteSpaceAfter(edits, lastToken, formatter.getNewLine()); + replaceWhiteSpaceAfter(edits, lastToken, formatter.getNewLine(), true, true); } } else { // compact the list @@ -180,13 +183,14 @@ private void formatLists(MultiTextEdit edits) { while (before.getType() != GroovyTokenTypeBridge.LBRACK && before.getType() != GroovyTokenTypeBridge.COMMA) { before = tokens.getLastTokenBefore(before); } - replaceWhiteSpaceAfter(edits, before, before.getType() == GroovyTokenTypeBridge.LBRACK ? "" : " "); + replaceWhiteSpaceAfter(edits, before, + before.getType() == GroovyTokenTypeBridge.LBRACK ? "" : " ", true, true); } catch (BadLocationException e) { Util.log(e); } } if (!nextTokenAs) { - replaceWhiteSpaceAfter(edits, lastToken, lastToken.getType() == GroovyTokenTypeBridge.SL_COMMENT ? formatter.getNewLine() : ""); + replaceWhiteSpaceAfter(edits, lastToken, lastToken.getType() == GroovyTokenTypeBridge.SL_COMMENT ? formatter.getNewLine() : "", true, true); } } } @@ -214,17 +218,24 @@ private int correctNodeLen(int nodeLen, List tokens, String newLine) { * Create an edit that replaces whitespace tokens immediately after given * token with a String. */ - private void replaceWhiteSpaceAfter(MultiTextEdit edits, Token token, String replaceWith) { + private void replaceWhiteSpaceAfter(MultiTextEdit edits, Token token, String replaceWith, boolean allWhitespaces, + boolean atLeastOneWhitespaceFound) { + GroovyDocumentScanner tokens = formatter.getTokens(); try { int editStart = tokens.getEnd(token); Token first = tokens.getNextToken(token); // first whitespace token (if any) Token last = first; // first non-whitespace token - // if no white space tokens where found then first and last will be the same token (i.e. token just after the given token) - while (isWhiteSpace(last.getType())) { + // if no white space tokens where found then first and last will be the same + // token (i.e. token just after the given token) + while ((allWhitespaces & isWhiteSpace(last.getType())) + || (!allWhitespaces & last.getType() == GroovyTokenTypeBridge.WS)) { last = tokens.getNextToken(last); } - replaceFromTo(editStart, tokens.getOffset(last), replaceWith, edits); + + if (atLeastOneWhitespaceFound || (editStart < tokens.getOffset(last))) { + replaceFromTo(editStart, tokens.getOffset(last), replaceWith, edits); + } } catch (BadLocationException e) { Util.log(e); } @@ -375,6 +386,162 @@ private void removeUnnecessarySemicolons(MultiTextEdit edits) throws BadLocation } } + private void addAdditionalSpacing(MultiTextEdit edits) { + try { + for (Token token : formatter.getTokens().getTokens(formatter.selection)) { + Token nextToken = formatter.getTokens().getNextToken(token); + int tokenType = token.getType(); + int nextTokenType = nextToken.getType(); + + boolean addSpaceAfter = false; + + // TODO how to differentiate between Generics and 1 < 2? + + if ((isValueToken(token) || tokenType == GroovyTokenTypeBridge.IDENT + || nextTokenType == GroovyTokenTypeBridge.STRING_LITERAL) && ( + // nextTokenType == GroovyTokenTypeBridge.GT || nextTokenType == + // GroovyTokenTypeBridge.LT || + nextTokenType == GroovyTokenTypeBridge.GE || nextTokenType == GroovyTokenTypeBridge.LE + || nextTokenType == GroovyTokenTypeBridge.NOT_EQUAL + || nextTokenType == GroovyTokenTypeBridge.EQUAL + || nextTokenType == GroovyTokenTypeBridge.ASSIGN)) { + + addSpaceAfter = true; + } + + if (( +// tokenType == GroovyTokenTypeBridge.GT || tokenType == GroovyTokenTypeBridge.LT || + tokenType == GroovyTokenTypeBridge.GE || tokenType == GroovyTokenTypeBridge.LE + || tokenType == GroovyTokenTypeBridge.NOT_EQUAL || tokenType == GroovyTokenTypeBridge.EQUAL + || tokenType == GroovyTokenTypeBridge.ASSIGN) + && ((isValueToken(nextToken) || nextTokenType == GroovyTokenTypeBridge.IDENT) + || nextTokenType == GroovyTokenTypeBridge.STRING_LITERAL)) { + addSpaceAfter = true; + } + + if (tokenType == GroovyTokenTypeBridge.COLON) { + addSpaceAfter = true; + } + + if (tokenType == GroovyTokenTypeBridge.COMMA && nextTokenType == GroovyTokenTypeBridge.IDENT) { + addSpaceAfter = true; + } + + int tokenEndOffset = formatter.getOffsetOfTokenEnd(token); + int nextTokenStartOffset = formatter.getOffsetOfToken(nextToken); + + if (addSpaceAfter) { + if (tokenEndOffset == nextTokenStartOffset) { + addEdit(new InsertEdit(tokenEndOffset, " "), edits); + } else { +// replaceWhiteSpaceAfter(edits, token, " ", false, false); + } + } + } + } catch (Exception e) { + GroovyCore.logException("Exception.", e); + } + } + + private void removeUnnecessaryWhitespace(MultiTextEdit edits) { + try { + for (Token token : formatter.getTokens().getTokens(formatter.selection)) { + Token nextToken = formatter.getTokens().getNextToken(token); + int tokenType = token.getType(); + int nextTokenType = nextToken.getType(); + + boolean removeAllWhitespaces = false; + boolean collapseAllWhitespaces = true; + + if (nextTokenType == GroovyTokenTypeBridge.COMMA) { + removeAllWhitespaces = true; + } + + // TODO: both Map and 1 < 2 match here, how to differentiate + // them? + if (tokenType == GroovyTokenTypeBridge.IDENT && nextTokenType == GroovyTokenTypeBridge.LT) { +// removeAllWhitespaces = true; + } + + if ((tokenType == GroovyTokenTypeBridge.LT && nextTokenType == GroovyTokenTypeBridge.IDENT) + || (tokenType == GroovyTokenTypeBridge.IDENT && nextTokenType == GroovyTokenTypeBridge.GT)) { + + removeAllWhitespaces = true; + } + + if (tokenType == GroovyTokenTypeBridge.LPAREN || nextTokenType == GroovyTokenTypeBridge.RPAREN) { + removeAllWhitespaces = true; + } + + if (tokenType == GroovyTokenTypeBridge.LBRACK || nextTokenType == GroovyTokenTypeBridge.RBRACK) { + removeAllWhitespaces = true; + } + + if (tokenType == GroovyTokenTypeBridge.IDENT && nextTokenType == GroovyTokenTypeBridge.LPAREN) { + removeAllWhitespaces = true; + } + + if (tokenType == GroovyTokenTypeBridge.IDENT && nextTokenType == GroovyTokenTypeBridge.COMMA) { + removeAllWhitespaces = true; + } + + if ((tokenType == GroovyTokenTypeBridge.GT && nextTokenType == GroovyTokenTypeBridge.GT) + || (tokenType == GroovyTokenTypeBridge.LT && nextTokenType == GroovyTokenTypeBridge.LT)) { + removeAllWhitespaces = true; + } + + if (tokenType == GroovyTokenTypeBridge.STRING_CTOR_START + && (nextTokenType == GroovyTokenTypeBridge.STRING_CTOR_END + || nextTokenType == GroovyTokenTypeBridge.EOF)) { + collapseAllWhitespaces = false; + } + + if (removeAllWhitespaces) { + replaceWhiteSpaceAfter(edits, token, "", false, false); + } else if (collapseAllWhitespaces) { + replaceWhiteSpaceAfter(edits, token, " ", false, false); + } + } + } catch (Exception e) { + GroovyCore.logException("Exception.", e); + } + } + + private boolean isValueToken(Token token) { + return Arrays.asList(GroovyTokenTypeBridge.NUM_INT, GroovyTokenTypeBridge.NUM_LONG, + GroovyTokenTypeBridge.NUM_DOUBLE, GroovyTokenTypeBridge.NUM_FLOAT, GroovyTokenTypeBridge.NUM_BIG_INT, + GroovyTokenTypeBridge.NUM_BIG_DECIMAL).contains(token.getType()); + } + + private boolean isValueLiteralToken(Token token) { + return Arrays.asList(GroovyTokenTypeBridge.LITERAL_boolean, GroovyTokenTypeBridge.LITERAL_byte, + GroovyTokenTypeBridge.LITERAL_char, GroovyTokenTypeBridge.LITERAL_short, + GroovyTokenTypeBridge.LITERAL_int, GroovyTokenTypeBridge.LITERAL_long, + GroovyTokenTypeBridge.LITERAL_double, GroovyTokenTypeBridge.LITERAL_float, GroovyTokenTypeBridge.IDENT) + .contains(token.getType()); + } + + private boolean isWhitespaceBeforeTokenNeeded(Token nextToken) { + return !(nextToken.getType() == GroovyTokenTypeBridge.COMMA + || nextToken.getType() == GroovyTokenTypeBridge.RBRACK + || nextToken.getType() == GroovyTokenTypeBridge.RPAREN + || nextToken.getType() == GroovyTokenTypeBridge.LBRACK + || nextToken.getType() == GroovyTokenTypeBridge.LPAREN) + || (nextToken.getType() == GroovyTokenTypeBridge.EQUAL + || nextToken.getType() == GroovyTokenTypeBridge.NOT_EQUAL + || nextToken.getType() == GroovyTokenTypeBridge.ASSIGN + || nextToken.getType() == GroovyTokenTypeBridge.NUM_BIG_DECIMAL + || nextToken.getType() == GroovyTokenTypeBridge.NUM_BIG_INT + || nextToken.getType() == GroovyTokenTypeBridge.NUM_DOUBLE + || nextToken.getType() == GroovyTokenTypeBridge.NUM_FLOAT + || nextToken.getType() == GroovyTokenTypeBridge.NUM_INT + || nextToken.getType() == GroovyTokenTypeBridge.NUM_LONG); + } + + private boolean isClassLiteral(Token token) { + return GroovyTokenTypeBridge.LITERAL_class == token.getType(); + } + private void addEdit(TextEdit edit, TextEdit container) { if (edit != null && edit.getOffset() >= formatter.formatOffset &&