diff --git a/packages/prettier-plugin-java/src/printers/blocks-and-statements.js b/packages/prettier-plugin-java/src/printers/blocks-and-statements.js index c41275621..1df79c3fd 100644 --- a/packages/prettier-plugin-java/src/printers/blocks-and-statements.js +++ b/packages/prettier-plugin-java/src/printers/blocks-and-statements.js @@ -130,9 +130,13 @@ class BlocksAndStatementPrettierVisitor { } return rejectAndConcat([ - rejectAndJoin(" ", [ctx.If[0], ctx.LBrace[0]]), - expression, - concat([ctx.RBrace[0], ifSeparator]), + rejectAndJoin(" ", [ + ctx.If[0], + concat([ + putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]), + ifSeparator + ]) + ]), ifStatement, elsePart ]); @@ -154,7 +158,7 @@ class BlocksAndStatementPrettierVisitor { return rejectAndJoin(" ", [ ctx.Switch[0], - rejectAndConcat([ctx.LBrace[0], expression, ctx.RBrace[0]]), + putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]), switchBlock ]); } @@ -207,7 +211,7 @@ class BlocksAndStatementPrettierVisitor { return rejectAndJoin(" ", [ ctx.While[0], rejectAndJoin(statementSeparator, [ - rejectAndConcat([ctx.LBrace[0], expression, ctx.RBrace[0]]), + putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]), statement ]) ]); @@ -228,9 +232,7 @@ class BlocksAndStatementPrettierVisitor { rejectAndJoin(statementSeparator, [ctx.Do[0], statement]), ctx.While[0], rejectAndConcat([ - ctx.LBrace[0], - expression, - ctx.RBrace[0], + putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]), ctx.Semicolon[0] ]) ]); @@ -363,9 +365,13 @@ class BlocksAndStatementPrettierVisitor { const block = this.visit(ctx.block); return rejectAndConcat([ - join(" ", [ctx.Synchronized[0], ctx.LBrace[0]]), - expression, - concat([ctx.RBrace[0], " "]), + join(" ", [ + ctx.Synchronized[0], + concat([ + putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]), + " " + ]) + ]), block ]); } diff --git a/packages/prettier-plugin-java/src/printers/expressions.js b/packages/prettier-plugin-java/src/printers/expressions.js index c41226d2c..07c03b567 100644 --- a/packages/prettier-plugin-java/src/printers/expressions.js +++ b/packages/prettier-plugin-java/src/printers/expressions.js @@ -14,11 +14,12 @@ const { rejectAndJoin, rejectAndConcat, sortAnnotationIdentifier, - sortTokens, rejectAndJoinSeps, findDeepElementInPartsArray, isExplicitLambdaParameter, - putIntoBraces + putIntoBraces, + separateTokensIntoGroups, + isShiftOperator } = require("./printer-utils"); class ExpressionsPrettierVisitor { @@ -153,74 +154,68 @@ class ExpressionsPrettierVisitor { } binaryExpression(ctx) { - const sortedTokens = sortTokens( - ctx.Instanceof, - ctx.AssignmentOperator, - ctx.Less, - ctx.Greater, - ctx.BinaryOperator - ); const referenceType = this.mapVisit(ctx.referenceType); const expression = this.mapVisit(ctx.expression); const unaryExpression = this.mapVisit(ctx.unaryExpression); - const segment = [unaryExpression.shift()]; - for (let i = 0; i < sortedTokens.length; i++) { - const token = sortedTokens[i]; - if (token.tokenType.tokenName === "Instanceof") { - segment.push( - rejectAndJoin(" ", [ctx.Instanceof[0], referenceType.shift()]) - ); - } else if (matchCategory(token, "'AssignmentOperator'")) { - segment.push(rejectAndJoin(" ", [token, expression.shift()])); - } else if ( - i + 1 < sortedTokens.length && - ((sortedTokens[i].image === ">" && - sortedTokens[i + 1].image === ">" && - sortedTokens[i].startOffset === - sortedTokens[i + 1].startOffset - 1) || - (sortedTokens[i].image === "<" && - sortedTokens[i + 1].image === "<" && - sortedTokens[i].startOffset === - sortedTokens[i + 1].startOffset - 1)) - ) { - if ( - sortedTokens[i + 2] && - sortedTokens[i + 2].image === ">" && - sortedTokens[i + 1].startOffset === - sortedTokens[i + 2].startOffset - 1 + + const { + groupsOfOperator, + sortedBinaryOperators + } = separateTokensIntoGroups(ctx); + const segmentsSplittedByBinaryOperator = []; + let currentSegment = []; + + groupsOfOperator.forEach(subgroup => { + currentSegment = [unaryExpression.shift()]; + for (let i = 0; i < subgroup.length; i++) { + const token = subgroup[i]; + const shiftOperator = isShiftOperator(subgroup, i); + if (token.tokenType.tokenName === "Instanceof") { + currentSegment.push( + rejectAndJoin(" ", [ctx.Instanceof[0], referenceType.shift()]) + ); + } else if (matchCategory(token, "'AssignmentOperator'")) { + currentSegment.push( + indent(rejectAndJoin(line, [token, expression.shift()])) + ); + } else if ( + shiftOperator === "leftShift" || + shiftOperator === "rightShift" ) { - segment.push( + currentSegment.push( rejectAndJoin(" ", [ - rejectAndConcat([ - token, - sortedTokens[i + 1], - sortedTokens[i + 2] - ]), + rejectAndConcat([token, subgroup[i + 1]]), unaryExpression.shift() ]) ); i++; - } else { - segment.push( + } else if (shiftOperator === "doubleRightShift") { + currentSegment.push( rejectAndJoin(" ", [ - rejectAndConcat([token, sortedTokens[i + 1]]), + rejectAndConcat([token, subgroup[i + 1], subgroup[i + 2]]), unaryExpression.shift() ]) ); + i += 2; + } else if (matchCategory(token, "'BinaryOperator'")) { + currentSegment.push( + indent(rejectAndJoin(line, [token, unaryExpression.shift()])) + ); } - i++; - } else if (matchCategory(token, "'BinaryOperator'")) { - segment.push( - indent( - rejectAndConcat([ - softline, - rejectAndJoin(" ", [token, unaryExpression.shift()]) - ]) - ) - ); } + segmentsSplittedByBinaryOperator.push( + group(rejectAndJoin(" ", currentSegment)) + ); + }); + if (groupsOfOperator.length === 0) { + return unaryExpression.shift(); } - return group(rejectAndJoin(" ", segment)); + return group( + rejectAndJoinSeps( + sortedBinaryOperators.map(elt => concat([" ", elt, line])), + segmentsSplittedByBinaryOperator + ) + ); } unaryExpression(ctx) { diff --git a/packages/prettier-plugin-java/src/printers/printer-utils.js b/packages/prettier-plugin-java/src/printers/printer-utils.js index c13eb0aa8..bb4331d56 100644 --- a/packages/prettier-plugin-java/src/printers/printer-utils.js +++ b/packages/prettier-plugin-java/src/printers/printer-utils.js @@ -294,6 +294,74 @@ function putIntoCurlyBraces(argument, separator, LBrace, RBrace) { return concat([LBrace, RBrace]); } +const andOrBinaryOperators = new Set(["&&", "||", "&", "|", "^"]); +function separateTokensIntoGroups(ctx) { + /** + * separate tokens into groups by andOrBinaryOperators ("&&", "||", "&", "|", "^") + * in order to break those operators in priority. + */ + const tokens = sortTokens( + ctx.Instanceof, + ctx.AssignmentOperator, + ctx.Less, + ctx.Greater, + ctx.BinaryOperator + ); + + const groupsOfOperator = []; + const sortedBinaryOperators = []; + let tmpGroup = []; + tokens.forEach(token => { + if ( + matchCategory(token, "'BinaryOperator'") && + andOrBinaryOperators.has(token.image) + ) { + sortedBinaryOperators.push(token); + groupsOfOperator.push(tmpGroup); + tmpGroup = []; + } else { + tmpGroup.push(token); + } + }); + + groupsOfOperator.push(tmpGroup); + + return { + groupsOfOperator, + sortedBinaryOperators + }; +} + +function isShiftOperator(tokens, index) { + if (tokens.length <= index + 1) { + return "none"; + } + + if ( + tokens[index].image === "<" && + tokens[index + 1].image === "<" && + tokens[index].startOffset === tokens[index + 1].startOffset - 1 + ) { + return "leftShift"; + } + if ( + tokens[index].image === ">" && + tokens[index + 1].image === ">" && + tokens[index].startOffset === tokens[index + 1].startOffset - 1 + ) { + if ( + tokens.length > index + 2 && + tokens[index + 2].image === ">" && + tokens[index + 1].startOffset === tokens[index + 2].startOffset - 1 + ) { + return "doubleRightShift"; + } + return "rightShift"; + } + + return "none"; +} + module.exports = { buildFqn, reject, @@ -315,5 +383,7 @@ module.exports = { rejectSeparators, handleClassBodyDeclaration, putIntoBraces, - putIntoCurlyBraces + putIntoCurlyBraces, + separateTokensIntoGroups, + isShiftOperator }; diff --git a/packages/prettier-plugin-java/test/unit-test/binary_expressions/_output.java b/packages/prettier-plugin-java/test/unit-test/binary_expressions/_output.java index e2c7bc945..dfde4da16 100644 --- a/packages/prettier-plugin-java/test/unit-test/binary_expressions/_output.java +++ b/packages/prettier-plugin-java/test/unit-test/binary_expressions/_output.java @@ -2,8 +2,8 @@ public class BinaryOperations { public void binaryOperationThatShouldBreak() { System.out.println( - "This operation with two very long string should break" - + "in a very nice way" + "This operation with two very long string should break" + + "in a very nice way" ); } diff --git a/packages/prettier-plugin-java/test/unit-test/comments/class/_output.java b/packages/prettier-plugin-java/test/unit-test/comments/class/_output.java index 20317f7af..770e9c87f 100644 --- a/packages/prettier-plugin-java/test/unit-test/comments/class/_output.java +++ b/packages/prettier-plugin-java/test/unit-test/comments/class/_output.java @@ -148,7 +148,8 @@ private ArrayTable( * elements but rowKeySet() will be empty and containsRow() won't * acknolwedge them. */ - rowKeyToIndex = Maps.indexMap(rowList); + rowKeyToIndex = + Maps.indexMap(rowList); columnKeyToIndex = Maps.indexMap(columnList); @SuppressWarnings( diff --git a/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_input.java b/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_input.java index 026e11ae8..d5e9082e5 100644 --- a/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_input.java +++ b/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_input.java @@ -68,7 +68,7 @@ private synchronized void myFunction(int arg1, int arg2 /*overloading*/){ return/*dead code*/ ; } /*at least one iteration !*/while (false); synchronized/*declares synchronizd statement*/ (this){ - while/*infinite loop*/ (true) + while/*infinite*/ (true) /*stop the program*/throw new RuntimeException(); } diff --git a/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_output.java b/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_output.java index a6f2cda0d..c0fb225af 100644 --- a/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_output.java +++ b/packages/prettier-plugin-java/test/unit-test/comments/comments-blocks-and-statements/_output.java @@ -73,7 +73,7 @@ private synchronized void myFunction(int arg1, int arg2/*overloading*/) { return/*dead code*/; } /*at least one iteration !*/while (false); synchronized/*declares synchronizd statement*/ (this) { - while/*infinite loop*/ (true) /*stop the program*/throw new RuntimeException(); + while/*infinite*/ (true) /*stop the program*/throw new RuntimeException(); } } } diff --git a/packages/prettier-plugin-java/test/unit-test/expressions/_input.java b/packages/prettier-plugin-java/test/unit-test/expressions/_input.java index f6decb6ab..98684828c 100644 --- a/packages/prettier-plugin-java/test/unit-test/expressions/_input.java +++ b/packages/prettier-plugin-java/test/unit-test/expressions/_input.java @@ -72,5 +72,107 @@ public void instanceOf() { } } + public void printSimple() { + if(myValue == 42) { + } + + if(myValue != 42) { + System.out.println("Why not 42 !"); + } + } + + public void printIf() { + Object myObject = new PrettierObject().getSingleton().getAuthentication().getCredentials().getRights().getName(); + + if(myValue == 42 || myValue == 42 && myValue == 42 && myValue == 42 || myValue == 42 && myValue == 42) { + + } + + if(myValue != 42 && 42/42 || myValue & 42 && myValue > 42 || myValue < 42 && myValue == 42) { + + } + + if(myValue != 42 && myValue == 42) { + + } + } + + public void printSwitch() { + switch(myValue == 42 || myValue == 42 && myValue == 42 && myValue == 42 || myValue == 42 && myValue == 42) { + + } + + switch(myValue != 42 && 42/42 || myValue & 42 && myValue > 42 || myValue < 42 && myValue == 42) { + + } + + switch(myValue != 42) { + + } + + switch(myValue != 42 && myValue == 42) { + + } + } + + public void printWhile() { + while/*infinite*/ (true) /*stop the program*/throw new RuntimeException(); + + while(myValue == 42 || myValue == 42 && myValue == 42 && myValue == 42 || myValue == 42 && myValue == 42) { + + } + + while(myValue != 42 && 42/42 || myValue & 42 && myValue > 42 || myValue < 42 && myValue == 42) { + + } + + while(myValue != 42) { + + } + + while(myValue != 42 && myValue == 42) { + + } + } + + public void printDoWhile() { + do{ + System.out.println("Prettier-java is cool !"); + } + while(myValue == 42 || myValue == 42 && myValue == 42 && myValue == 42 || myValue == 42 && myValue == 42); + + do { + System.out.println("Prettier-java is cool !"); + } + while(myValue != 42 && 42/42 || myValue & 42 && myValue > 42 || myValue < 42 && myValue == 42); + + do { + System.out.println("Prettier-java is cool !"); + } + while(myValue != 42); + + do { + System.out.println("Prettier-java is cool !"); + }while(myValue != 42 && myValue == 42); + } + + public void printSynchronized() { + synchronized(myValue == 42 || myValue == 42 && myValue == 42 && myValue == 42 || myValue == 42 && myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + + synchronized(myValue != 42 && 42/42 || myValue & 42 && myValue > 42 || myValue < 42 && myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + + synchronized(myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + + synchronized(myValue != 42 && myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + } + } diff --git a/packages/prettier-plugin-java/test/unit-test/expressions/_output.java b/packages/prettier-plugin-java/test/unit-test/expressions/_output.java index ef1587255..8b3c769fe 100644 --- a/packages/prettier-plugin-java/test/unit-test/expressions/_output.java +++ b/packages/prettier-plugin-java/test/unit-test/expressions/_output.java @@ -71,4 +71,160 @@ public void instanceOf() { System.out.println("instanceOf"); } } + + public void printSimple() { + if (myValue == 42) {} + + if (myValue != 42) { + System.out.println("Why not 42 !"); + } + } + + public void printIf() { + Object myObject = new PrettierObject() + .getSingleton() + .getAuthentication() + .getCredentials() + .getRights() + .getName(); + + if ( + myValue == 42 || + myValue == 42 && + myValue == 42 && + myValue == 42 || + myValue == 42 && + myValue == 42 + ) {} + + if ( + myValue != 42 && + 42 / 42 || + myValue & + 42 && + myValue > 42 || + myValue < 42 && + myValue == 42 + ) {} + + if (myValue != 42 && myValue == 42) {} + } + + public void printSwitch() { + switch ( + myValue == 42 || + myValue == 42 && + myValue == 42 && + myValue == 42 || + myValue == 42 && + myValue == 42 + ) {} + + switch ( + myValue != 42 && + 42 / 42 || + myValue & + 42 && + myValue > 42 || + myValue < 42 && + myValue == 42 + ) {} + + switch (myValue != 42) {} + + switch (myValue != 42 && myValue == 42) {} + } + + public void printWhile() { + while/*infinite*/ (true) /*stop the program*/throw new RuntimeException(); + + while ( + myValue == 42 || + myValue == 42 && + myValue == 42 && + myValue == 42 || + myValue == 42 && + myValue == 42 + ) {} + + while ( + myValue != 42 && + 42 / 42 || + myValue & + 42 && + myValue > 42 || + myValue < 42 && + myValue == 42 + ) {} + + while (myValue != 42) {} + + while (myValue != 42 && myValue == 42) {} + } + + public void printDoWhile() { + do { + System.out.println("Prettier-java is cool !"); + } while ( + myValue == 42 || + myValue == 42 && + myValue == 42 && + myValue == 42 || + myValue == 42 && + myValue == 42 + ); + + do { + System.out.println("Prettier-java is cool !"); + } while ( + myValue != 42 && + 42 / 42 || + myValue & + 42 && + myValue > 42 || + myValue < 42 && + myValue == 42 + ); + + do { + System.out.println("Prettier-java is cool !"); + } while (myValue != 42); + + do { + System.out.println("Prettier-java is cool !"); + } while (myValue != 42 && myValue == 42); + } + + public void printSynchronized() { + synchronized ( + myValue == 42 || + myValue == 42 && + myValue == 42 && + myValue == 42 || + myValue == 42 && + myValue == 42 + ) { + System.out.println("Prettier-java is cool !"); + } + + synchronized ( + myValue != 42 && + 42 / 42 || + myValue & + 42 && + myValue > 42 || + myValue < 42 && + myValue == 42 + ) { + System.out.println("Prettier-java is cool !"); + } + + synchronized (myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + + synchronized (myValue != 42 && myValue == 42) { + System.out.println("Prettier-java is cool !"); + } + } }