Skip to content

Commit 307e091

Browse files
cushonabashev
authored andcommitted
Keep the space between a unary minus and a negative literal
javac folds a minus in front of a decimal literal into the literal itself, so "- -1" parses as one unary minus applied to the literal "-1". The check that keeps a space between two prefix operators only looked for a nested unary expression, so the output was "--1": the decrement operator on a literal, which does not compile. "- -x" was fine, the literal case was not. This ports google/google-java-format#576 by Liam Miller-Cushon: a literal whose source starts with "-" counts as a unary minus in that check. The golden B183431894 comes from upstream, with the expected output in this project's style. The 15,747 files of the JDK 21 sources format exactly as before.
1 parent 746fb60 commit 307e091

3 files changed

Lines changed: 30 additions & 7 deletions

File tree

‎open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,18 +1663,22 @@ public Void visitMemberSelect(MemberSelectTree node, Void unused) {
16631663
public Void visitLiteral(LiteralTree node, Void unused) {
16641664
sync(node);
16651665
String sourceForNode = getSourceForNode(node, getCurrentPath());
1666-
// A negative numeric literal -n is usually represented as unary minus on n,
1667-
// but that doesn't work for integer or long MIN_VALUE. The parser works
1668-
// around that by representing it directly as a signed literal (with no
1669-
// unary minus), but the lexer still expects two tokens.
1670-
if (sourceForNode.startsWith("-")) {
1666+
if (isUnaryMinusLiteral(sourceForNode)) {
16711667
token("-");
16721668
sourceForNode = sourceForNode.substring(1).trim();
16731669
}
16741670
token(sourceForNode);
16751671
return null;
16761672
}
16771673

1674+
// A negative numeric literal -n is usually represented as unary minus on n,
1675+
// but that doesn't work for integer or long MIN_VALUE. The parser works
1676+
// around that by representing it directly as a signed literal (with no
1677+
// unary minus), but the lexer still expects two tokens.
1678+
private static boolean isUnaryMinusLiteral(String literalTreeSource) {
1679+
return literalTreeSource.startsWith("-");
1680+
}
1681+
16781682
private void visitPackage(ExpressionTree packageName, List<? extends AnnotationTree> packageAnnotations) {
16791683
if (!packageAnnotations.isEmpty()) {
16801684
for (AnnotationTree annotation : packageAnnotations) {
@@ -1759,10 +1763,10 @@ private boolean ambiguousUnaryOperator(UnaryTree node, String operatorName) {
17591763
default:
17601764
return false;
17611765
}
1762-
if (!(node.getExpression() instanceof UnaryTree)) {
1766+
JCTree.Tag tag = unaryTag(node.getExpression());
1767+
if (tag == null) {
17631768
return false;
17641769
}
1765-
JCTree.Tag tag = ((JCTree) node.getExpression()).getTag();
17661770
if (tag.isPostUnaryOp()) {
17671771
return false;
17681772
}
@@ -1772,6 +1776,17 @@ private boolean ambiguousUnaryOperator(UnaryTree node, String operatorName) {
17721776
return true;
17731777
}
17741778

1779+
private JCTree.Tag unaryTag(ExpressionTree expression) {
1780+
if (expression instanceof UnaryTree) {
1781+
return ((JCTree) expression).getTag();
1782+
}
1783+
if (expression instanceof LiteralTree
1784+
&& isUnaryMinusLiteral(getSourceForNode(expression, getCurrentPath()))) {
1785+
return JCTree.Tag.MINUS;
1786+
}
1787+
return null;
1788+
}
1789+
17751790
@Override
17761791
public Void visitPrimitiveType(PrimitiveTypeTree node, Void unused) {
17771792
sync(node);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class B183431894 {
2+
int a = - -1;
3+
int d = + +1;
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class B183431894 {
2+
int a = - -1;
3+
int d = + +1;
4+
}

0 commit comments

Comments
 (0)