Formatting a lambda whose parameter carries an annotation with arguments, such as @SuppressWarnings("unused"), breaks the parameter list across lines even when the whole statement fits in 120 columns.
Input
class T {
BiFunction<Integer, Integer, Integer> g = (final var x, @SuppressWarnings("unused") var y) -> x + y;
}
Output of main (2fbf175), the same on JDK 21, 25 and 27
class T {
BiFunction<Integer, Integer, Integer> g =
(final var x,
@SuppressWarnings("unused")
var y) -> x + y;
}
Expected
The input, unchanged. A lambda parameter is a parameter, and method parameters keep such an annotation on their line: void m(@SuppressWarnings("unused") int y) {} is left alone.
A marker annotation (@Deprecated var x) is already kept inline; it is the arguments that trigger the break. An explicit type instead of var, a block body or a second annotation make no difference.
Cause
JavaInputAstVisitor.visitLambdaExpression declares each parameter with inlineAnnotationDirection(parameter.getModifiers()), which answers VERTICAL for any annotation that has arguments, and a vertical annotation ends in a forced break. That rule is meant for local variable declarations, where
@SuppressWarnings("unchecked")
Function<Object, String> local = o -> (String) o;
is the wanted shape. Method parameters go through visitToDeclare(DeclarationKind.PARAMETER, Direction.HORIZONTAL, ...) instead, so their annotations stay inline.
The same code is in develop of https://github.com/palantir/palantir-java-format and in https://github.com/google/google-java-format, where the method is called fieldAnnotationDirection, so both produce this layout. I found no report of it in either tracker.
Formatting a lambda whose parameter carries an annotation with arguments, such as
@SuppressWarnings("unused"), breaks the parameter list across lines even when the whole statement fits in 120 columns.Input
Output of main (2fbf175), the same on JDK 21, 25 and 27
Expected
The input, unchanged. A lambda parameter is a parameter, and method parameters keep such an annotation on their line:
void m(@SuppressWarnings("unused") int y) {}is left alone.A marker annotation (
@Deprecated var x) is already kept inline; it is the arguments that trigger the break. An explicit type instead ofvar, a block body or a second annotation make no difference.Cause
JavaInputAstVisitor.visitLambdaExpressiondeclares each parameter withinlineAnnotationDirection(parameter.getModifiers()), which answersVERTICALfor any annotation that has arguments, and a vertical annotation ends in a forced break. That rule is meant for local variable declarations, whereis the wanted shape. Method parameters go through
visitToDeclare(DeclarationKind.PARAMETER, Direction.HORIZONTAL, ...)instead, so their annotations stay inline.The same code is in
developof https://github.com/palantir/palantir-java-format and in https://github.com/google/google-java-format, where the method is calledfieldAnnotationDirection, so both produce this layout. I found no report of it in either tracker.