COMPARATOR =
+ Comparator.comparingInt(AnnotationOrModifier::position);
+
+ @Override
+ public int compareTo(AnnotationOrModifier o) {
+ return COMPARATOR.compare(this, o);
+ }
}
- boolean nextIsModifier() {
- switch (builder.peekToken().get()) {
+ /**
+ * The modifiers annotations for a declaration, grouped in to a prefix that contains all of the
+ * declaration annotations and modifiers, and a suffix of type annotations.
+ *
+ * For examples like {@code @Deprecated public @Nullable Foo foo();}, this allows us to
+ * format {@code @Deprecated public} as declaration modifiers, and {@code @Nullable} as a type
+ * annotation on the return type.
+ */
+ static class DeclarationModifiersAndTypeAnnotations {
+
+ private final ImmutableList declarationModifiers;
+
+ private final ImmutableList typeAnnotations;
+
+ DeclarationModifiersAndTypeAnnotations(
+ ImmutableList declarationModifiers,
+ ImmutableList typeAnnotations) {
+ this.declarationModifiers = declarationModifiers;
+ this.typeAnnotations = typeAnnotations;
+ }
+
+ static DeclarationModifiersAndTypeAnnotations create(
+ ImmutableList declarationModifiers,
+ ImmutableList typeAnnotations) {
+ return new DeclarationModifiersAndTypeAnnotations(declarationModifiers, typeAnnotations);
+ }
+
+ static DeclarationModifiersAndTypeAnnotations empty() {
+ return create(ImmutableList.of(), ImmutableList.of());
+ }
+
+ ImmutableList declarationModifiers() {
+ return declarationModifiers;
+ }
+
+ ImmutableList typeAnnotations() {
+ return typeAnnotations;
+ }
+
+ boolean hasDeclarationAnnotation() {
+ return declarationModifiers().stream().anyMatch(AnnotationOrModifier::isAnnotation);
+ }
+ }
+
+ /**
+ * Examines the token stream to convert the modifiers for a declaration into a {@link
+ * DeclarationModifiersAndTypeAnnotations}.
+ */
+ DeclarationModifiersAndTypeAnnotations splitModifiers(
+ ModifiersTree modifiersTree, List extends AnnotationTree> annotations) {
+ if (annotations.isEmpty() && !isModifier(builder.peekToken().get())) {
+ return DeclarationModifiersAndTypeAnnotations.empty();
+ }
+ RangeSet annotationRanges = TreeRangeSet.create();
+ for (AnnotationTree annotationTree : annotations) {
+ annotationRanges.add(Range.closedOpen(
+ getStartPosition(annotationTree), getEndPosition(annotationTree, getCurrentPath())));
+ }
+ ImmutableList toks = builder.peekTokens(
+ getStartPosition(modifiersTree),
+ (Input.Tok tok) ->
+ // ModifiersTree end position information isn't reliable, so scan
+ // tokens as long as
+ // we're seeing annotations or modifiers
+ annotationRanges.contains(tok.getPosition()) || isModifier(tok.getText()));
+ ImmutableList modifiers = ImmutableList.copyOf(Streams.concat(
+ toks.stream()
+ // reject tokens from inside AnnotationTrees, we
+ // only want modifiers
+ .filter(t -> !annotationRanges.contains(t.getPosition()))
+ .map(AnnotationOrModifier::ofModifier),
+ annotations.stream().map(AnnotationOrModifier::ofAnnotation))
+ .sorted()
+ .collect(toList()));
+ // Take a suffix of annotations that are well-known type annotations, and which appear after
+ // any
+ // declaration annotations or modifiers
+ ImmutableList.Builder typeAnnotations = ImmutableList.builder();
+ int idx = modifiers.size() - 1;
+ while (idx >= 0) {
+ AnnotationOrModifier modifier = modifiers.get(idx);
+ if (!modifier.isAnnotation() || !isTypeAnnotation(modifier.annotation())) {
+ break;
+ }
+ typeAnnotations.add(modifier.annotation());
+ idx--;
+ }
+ return DeclarationModifiersAndTypeAnnotations.create(
+ modifiers.subList(0, idx + 1), typeAnnotations.build().reverse());
+ }
+
+ private void formatAnnotationOrModifier(Deque modifiers) {
+ AnnotationOrModifier modifier = modifiers.removeFirst();
+ switch (modifier.getKind()) {
+ case MODIFIER:
+ token(modifier.modifier().getText());
+ if (modifier.modifier().getText().equals("non")) {
+ token(modifiers.removeFirst().modifier().getText());
+ token(modifiers.removeFirst().modifier().getText());
+ }
+ break;
+ case ANNOTATION:
+ scan(modifier.annotation(), null);
+ break;
+ }
+ }
+
+ boolean isTypeAnnotation(AnnotationTree annotationTree) {
+ Tree annotationType = annotationTree.getAnnotationType();
+ if (!(annotationType instanceof IdentifierTree)) {
+ return false;
+ }
+ return typeAnnotationSimpleNames.contains(((IdentifierTree) annotationType).getName());
+ }
+
+ private static boolean isModifier(String token) {
+ switch (token) {
case "public":
case "protected":
case "private":
@@ -2598,7 +2878,7 @@ private void visitToDeclare(
/* typeWithDims= */ Optional.empty());
}
- /** Does not omit the leading '<', which should be associated with the type name. */
+ /** Does not omit the leading {@code "<"}, which should be associated with the type name. */
protected void typeParametersRest(List extends TypeParameterTree> typeParameters, Indent plusIndent) {
builder.open(plusIndent);
builder.breakOp();
@@ -2617,6 +2897,8 @@ protected void typeParametersRest(List extends TypeParameterTree> typeParamete
builder.close();
}
+ /** Collapse chains of {@code .} operators, across multiple {@link ASTNode} types. */
+
/**
* Output a "." node.
*
@@ -2795,7 +3077,7 @@ private void visitRegularDot(List items, boolean needDot) {
length++;
}
if (!fillFirstArgument(e, items, trailingDereferences ? ZERO : minusFour)) {
- BreakTag tyargTag = new BreakTag();
+ BreakTag tyargTag = genSym();
dotExpressionUpToArgs(e, Optional.of(tyargTag));
Indent tyargIndent = Indent.If.make(tyargTag, plusFour, ZERO);
dotExpressionArgsAndParen(e, tyargIndent, (trailingDereferences || needDot) ? plusFour : ZERO);
@@ -2877,7 +3159,7 @@ private void visitDotWithPrefix(
}
Deque unconsumedPrefixes = new ArrayDeque<>(ImmutableSortedSet.copyOf(prefixes));
- BreakTag nameTag = new BreakTag();
+ BreakTag nameTag = genSym();
for (int i = 0; i < items.size(); i++) {
ExpressionTree e = items.get(i);
if (needDot) {
@@ -2897,7 +3179,7 @@ private void visitDotWithPrefix(
.build());
token(".");
}
- BreakTag tyargTag = new BreakTag();
+ BreakTag tyargTag = genSym();
dotExpressionUpToArgs(e, Optional.of(tyargTag));
if (!unconsumedPrefixes.isEmpty() && i == unconsumedPrefixes.peekFirst()) {
builder.close();
@@ -2931,7 +3213,7 @@ private boolean shouldHaveColumnLimit(ExpressionTree expr) {
}
/** Returns the simple names of expressions in a "." chain. */
- private List simpleNames(Deque stack) {
+ private static ImmutableList simpleNames(Deque stack) {
ImmutableList.Builder simpleNames = ImmutableList.builder();
OUTER:
for (ExpressionTree expression : stack) {
@@ -2987,14 +3269,14 @@ private void dotExpressionUpToArgs(ExpressionTree expression, Optional
}
/** Returns the base expression of an erray access, e.g. given {@code foo[0][0]} returns {@code foo}. */
- private ExpressionTree getArrayBase(ExpressionTree node) {
+ private static ExpressionTree getArrayBase(ExpressionTree node) {
while (node instanceof ArrayAccessTree) {
node = ((ArrayAccessTree) node).getExpression();
}
return node;
}
- private ExpressionTree getMethodReceiver(MethodInvocationTree methodInvocation) {
+ private static ExpressionTree getMethodReceiver(MethodInvocationTree methodInvocation) {
ExpressionTree select = methodInvocation.getMethodSelect();
return select instanceof MemberSelectTree ? ((MemberSelectTree) select).getExpression() : null;
}
@@ -3041,7 +3323,7 @@ private void formatArrayIndices(Deque indices) {
* Returns all array indices for the given expression, e.g. given {@code foo[0][0]} returns the expressions for
* {@code [0][0]}.
*/
- private Deque getArrayIndices(ExpressionTree expression) {
+ private static Deque getArrayIndices(ExpressionTree expression) {
Deque indices = new ArrayDeque<>();
while (expression instanceof ArrayAccessTree) {
ArrayAccessTree array = (ArrayAccessTree) expression;
@@ -3359,7 +3641,13 @@ private static boolean expressionsAreParallel(List> rows, i
if (column >= row.size()) {
continue;
}
- nodeTypes.add(row.get(column).getKind());
+ // Treat UnaryTree expressions as their underlying type for the comparison (so, for example
+ // -ve and +ve numeric literals are considered the same).
+ if (row.get(column) instanceof UnaryTree) {
+ nodeTypes.add(((UnaryTree) row.get(column)).getExpression().getKind());
+ } else {
+ nodeTypes.add(row.get(column).getKind());
+ }
}
for (Multiset.Entry nodeType : nodeTypes.entrySet()) {
if (nodeType.getCount() >= atLeastM) {
@@ -3391,8 +3679,8 @@ int declareOne(
Optional receiverExpression,
Optional typeWithDims) {
- BreakTag typeBreak = new BreakTag();
- BreakTag verticalAnnotationBreak = new BreakTag();
+ BreakTag typeBreak = genSym();
+ BreakTag verticalAnnotationBreak = genSym();
// If the node is a field declaration, try to output any declaration
// annotations in-line. If the entire declaration doesn't fit on a single
@@ -3407,16 +3695,18 @@ int declareOne(
new ArrayDeque<>(typeWithDims.isPresent() ? typeWithDims.get().dims : Collections.emptyList());
int baseDims = 0;
+ // preprocess to separate declaration annotations + modifiers, type annotations
+
+ DeclarationModifiersAndTypeAnnotations declarationAndTypeModifiers = modifiers
+ .map(m -> splitModifiers(m, m.getAnnotations()))
+ .orElseGet(() -> DeclarationModifiersAndTypeAnnotations.empty());
builder.open(
- kind == DeclarationKind.PARAMETER
- && (modifiers.isPresent()
- && !modifiers.get().getAnnotations().isEmpty())
+ kind == DeclarationKind.PARAMETER && declarationAndTypeModifiers.hasDeclarationAnnotation()
? plusFour
: ZERO);
{
- if (modifiers.isPresent()) {
- visitAndBreakModifiers(modifiers.get(), annotationsDirection, Optional.of(verticalAnnotationBreak));
- }
+ List annotations = visitModifiers(
+ declarationAndTypeModifiers, annotationsDirection, Optional.of(verticalAnnotationBreak));
boolean isVar = builder.peekToken().get().equals("var")
&& (!name.contentEquals("var") || builder.peekToken(1).get().equals("var"));
boolean hasType = type != null || isVar;
@@ -3426,6 +3716,7 @@ int declareOne(
{
builder.open(ZERO);
{
+ visitAnnotations(annotations, BreakOrNot.NO, BreakOrNot.YES);
if (typeWithDims.isPresent() && typeWithDims.get().node != null) {
scan(typeWithDims.get().node, null);
int totalDims = dims.size();
@@ -3651,8 +3942,7 @@ protected void addBodyDeclarations(
visitVariables(
variableFragments(it, bodyDeclaration),
DeclarationKind.FIELD,
- // We always want field annotations to be vertical
- Direction.VERTICAL);
+ fieldAnnotationDirection(((VariableTree) bodyDeclaration).getModifiers()));
} else {
scan(bodyDeclaration, null);
}
@@ -3671,6 +3961,7 @@ protected void addBodyDeclarations(
}
}
}
+
/** Gets the permits clause for the given node. This is only available in Java 15 and later. */
protected List extends Tree> getPermitsClause(ClassTree node) {
return ImmutableList.of();
@@ -3703,7 +3994,7 @@ private void classDeclarationTypeList(String token, List extends Tree> types)
*
* e.g. {@code int x, y;} is parsed as {@code int x; int y;}.
*/
- private List variableFragments(PeekingIterator extends Tree> it, Tree first) {
+ private static List variableFragments(PeekingIterator extends Tree> it, Tree first) {
List fragments = new ArrayList<>();
if (first.getKind() == VARIABLE) {
int start = getStartPosition(first);
@@ -3745,31 +4036,32 @@ private boolean hasTrailingToken(Input input, List extends Tree> nodes, String
/**
* Can a local with a set of modifiers be declared with horizontal annotations? This is currently true if there is
- * at most one marker annotation, and no others.
+ * at most one parameterless annotation, and no others.
*
* @param modifiers the list of {@link ModifiersTree}s
* @return whether the local can be declared with horizontal annotations
*/
- private Direction canLocalHaveHorizontalAnnotations(ModifiersTree modifiers) {
- int markerAnnotations = 0;
+ private static Direction canLocalHaveHorizontalAnnotations(ModifiersTree modifiers) {
+ int parameterlessAnnotations = 0;
for (AnnotationTree annotation : modifiers.getAnnotations()) {
if (annotation.getArguments().isEmpty()) {
- markerAnnotations++;
+ parameterlessAnnotations++;
}
}
- return markerAnnotations <= 1
- && markerAnnotations == modifiers.getAnnotations().size()
+ return parameterlessAnnotations <= 1
+ && parameterlessAnnotations
+ == modifiers.getAnnotations().size()
? Direction.HORIZONTAL
: Direction.VERTICAL;
}
/**
- * Should a declaration with a set of modifiers be declared with horizontal annotations? This is currently true if
- * all annotations are marker annotations.
+ * Should a field with a set of modifiers be declared with horizontal annotations? This is currently true if all
+ * annotations are parameterless annotations or type annotations.
*/
- private Direction inlineAnnotationDirection(ModifiersTree modifiers) {
+ private Direction fieldAnnotationDirection(ModifiersTree modifiers) {
for (AnnotationTree annotation : modifiers.getAnnotations()) {
- if (!annotation.getArguments().isEmpty()) {
+ if (!(annotation.getArguments().isEmpty() || isTypeAnnotation(annotation))) {
return Direction.VERTICAL;
}
}
@@ -3781,7 +4073,7 @@ private Direction inlineAnnotationDirection(ModifiersTree modifiers) {
*
* @param token the {@link String} to wrap in a {@link Token}
*/
- protected void token(String token) {
+ protected final void token(String token) {
builder.token(token, Token.RealOrImaginary.REAL, ZERO, /* breakAndIndentTrailingComment= */ Optional.empty());
}
@@ -3791,7 +4083,7 @@ protected void token(String token) {
* @param token the {@link String} to wrap in a {@link Token}
* @param plusIndentCommentsBefore extra indent for comments before this token
*/
- protected void token(String token, Indent plusIndentCommentsBefore) {
+ protected final void token(String token, Indent plusIndentCommentsBefore) {
builder.token(
token,
Token.RealOrImaginary.REAL,
@@ -3800,7 +4092,7 @@ protected void token(String token, Indent plusIndentCommentsBefore) {
}
/** Emit a {@link Token}, and breaks and indents trailing javadoc or block comments. */
- void tokenBreakTrailingComment(String token, Indent breakAndIndentTrailingComment) {
+ final void tokenBreakTrailingComment(String token, Indent breakAndIndentTrailingComment) {
builder.token(token, Token.RealOrImaginary.REAL, ZERO, Optional.of(breakAndIndentTrailingComment));
}
@@ -3816,12 +4108,16 @@ protected void markForPartialFormat() {
*
* @param node the ASTNode holding the input position
*/
- protected void sync(Tree node) {
+ protected final void sync(Tree node) {
builder.sync(((JCTree) node).getStartPosition());
}
+ final BreakTag genSym() {
+ return new BreakTag();
+ }
+
@Override
- public String toString() {
+ public final String toString() {
return MoreObjects.toStringHelper(this).add("builder", builder).toString();
}
}
diff --git a/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java
index 00b26de9a..b1e02a2a1 100644
--- a/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java
+++ b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java
@@ -22,10 +22,10 @@
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.palantir.javaformat.Op;
import com.palantir.javaformat.OpsBuilder;
import com.palantir.javaformat.OpsBuilder.BlankLineWanted;
import com.palantir.javaformat.java.JavaInputAstVisitor;
+import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.BindingPatternTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.CaseTree;
@@ -114,7 +114,8 @@ public Void visitBindingPattern(BindingPatternTree node, Void unused) {
private void visitBindingPattern(ModifiersTree modifiers, Tree type, Name name) {
if (modifiers != null) {
- builder.addAll(visitModifiers(modifiers, Direction.HORIZONTAL, Optional.empty()));
+ List annotations = visitModifiers(modifiers, Direction.HORIZONTAL, Optional.empty());
+ visitAnnotations(annotations, BreakOrNot.NO, BreakOrNot.YES);
}
scan(type, null);
builder.breakOp(" ");
@@ -162,11 +163,9 @@ public Void visitClass(ClassTree tree, Void unused) {
public void visitRecordDeclaration(ClassTree node) {
sync(node);
- List breaks = visitModifiers(
- node.getModifiers(), Direction.VERTICAL, /* declarationAnnotationBreak= */ Optional.empty());
+ typeDeclarationModifiers(node.getModifiers());
Verify.verify(node.getExtendsClause() == null);
boolean hasSuperInterfaceTypes = !node.getImplementsClause().isEmpty();
- builder.addAll(breaks);
token("record");
builder.space();
visit(node.getSimpleName());
diff --git a/palantir-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java b/palantir-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java
index 1f2da75ac..6d8f946c1 100644
--- a/palantir-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java
+++ b/palantir-java-format/src/test/java/com/palantir/javaformat/java/FormatterTest.java
@@ -253,8 +253,7 @@ public void importsFixedIfRequested() throws FormatterException {
+ "import java.util.List;\n"
+ "import javax.annotations.Nullable;\n\n"
+ "public class ExampleTest {\n"
- + " @Nullable\n"
- + " List> xs;\n"
+ + " @Nullable List> xs;\n"
+ "}\n";
assertThat(output).isEqualTo(expect);
}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20128588.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20128588.output
index 4ead03c80..85ac34b7b 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20128588.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20128588.output
@@ -23,17 +23,11 @@ class Test {
@Baz
void f() {}
- @Foo
- @Bar
- @Baz
- static Object field;
+ @Foo @Bar @Baz static Object field;
static @Foo @Bar @Baz Object field;
- @Foo
- @Bar
- @Baz
- Object field;
+ @Foo @Bar @Baz Object field;
@Foo(xs = 42)
@Bar
@@ -93,12 +87,7 @@ class Test {
@Deprecated
Object var;
- @Deprecated
- @Deprecated
- @Deprecated
- @Deprecated
- @Deprecated
- Object var;
+ @Deprecated @Deprecated @Deprecated @Deprecated @Deprecated Object var;
@Deprecated(x = 42)
@Deprecated
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20577626.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20577626.output
index 41811f23a..efdda3441 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20577626.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B20577626.output
@@ -1,9 +1,7 @@
class B20577626 {
private @Mock GsaConfigFlags mGsaConfig;
- @Foo
- @Bar
- private @Mock GsaConfigFlags mGsaConfig;
+ @Foo @Bar private @Mock GsaConfigFlags mGsaConfig;
@Foo
abstract @Bar void m() {}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B21465477.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B21465477.output
index 97df7e812..118ba93f9 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B21465477.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B21465477.output
@@ -1,16 +1,10 @@
class B21465477 {
- @Nullable
- private final String simpleFieldName;
-
- @Nullable
- private final String shortFlagName;
-
+ @Nullable private final String simpleFieldName;
+ @Nullable private final String shortFlagName;
private final String containerClassName;
private final String type;
private final String doc;
private final DocLevel docLevel;
-
- @Nullable
- private final String altName;
+ @Nullable private final String altName;
}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.input b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.input
index 631f0769e..efbd93c0a 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.input
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.input
@@ -44,11 +44,11 @@ class B24702438 {
void f(
int a,
- @Nullable @Deprecated ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated @Nullable ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated @Nullable ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated @Nullable ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
int c) {}
void g(
- @Nullable @Deprecated ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated ImmutableList veryVeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooong) {}
+ @Deprecated @Nullable ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated @Nullable ImmutableList veryVeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooong) {}
}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.output
index 99c2fa517..ed8541e02 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/B24702438.output
@@ -1,22 +1,14 @@
class B24702438 {
- @Inject
- int x;
-
- @Inject
- int y;
+ @Inject int x;
- @Inject
- int z;
+ @Inject int y;
- @Inject
- int x;
-
- @Inject
- int y;
+ @Inject int z;
- @Inject
- int z;
+ @Inject int x;
+ @Inject int y;
+ @Inject int z;
// this is a comment
@@ -47,17 +39,17 @@ class B24702438 {
void f(
int a,
- @Nullable @Deprecated
+ @Deprecated @Nullable
ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated
+ @Deprecated @Nullable
ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated
+ @Deprecated @Nullable
ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
int c) {}
void g(
- @Nullable @Deprecated
+ @Deprecated @Nullable
ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
- @Nullable @Deprecated
+ @Deprecated @Nullable
ImmutableList veryVeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooong) {}
}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I1.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I1.output
index 4e5ea999b..ca7ff210d 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I1.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I1.output
@@ -16,15 +16,9 @@ class Test {
class Test {
final CreationMechanism creationMechanism;
-
- @Nullable
- final String creationUserAgent;
-
+ @Nullable final String creationUserAgent;
final ClientId clientId;
-
- @Nullable
- final String creationUserAgentXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
-
+ @Nullable final String creationUserAgentXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
final Token externalId;
{
@@ -38,8 +32,7 @@ class Test {
class Test {
- @Nullable
- final String creationUserAgent;
+ @Nullable final String creationUserAgent;
{
@Nullable final String creationUserAgent;
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I13.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I13.output
index bd526afd0..46e809adf 100644
--- a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I13.output
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/I13.output
@@ -1,7 +1,6 @@
class I13 {
- @Nullable
- public int f;
+ @Nullable public int f;
@Override
public void m() {}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.input b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.input
new file mode 100644
index 000000000..ddaa8f1ad
--- /dev/null
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.input
@@ -0,0 +1,33 @@
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+class TypeAnnotations {
+
+ @Deprecated
+ public @Nullable Object foo() {}
+
+ public @Deprecated Object foo() {}
+
+ @Nullable Foo handle() {
+ @Nullable Bar bar = bar();
+ try (@Nullable Baz baz = baz()) {}
+ }
+
+ Foo(
+ @Nullable Bar //
+ param1, //
+ Baz //
+ param2) {}
+
+ void g(
+ @Deprecated @Nullable ImmutableList veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated @Nullable ImmutableList veryVeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooong) {}
+
+ @Deprecated @Nullable TypeAnnotations() {}
+
+ enum Foo {
+ @Nullable
+ BAR;
+ }
+
+ @Nullable @Nullable Object doubleTrouble() {}
+}
diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.output
new file mode 100644
index 000000000..b8a601ac0
--- /dev/null
+++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/TypeAnnotations.output
@@ -0,0 +1,37 @@
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+class TypeAnnotations {
+
+ @Deprecated
+ public @Nullable Object foo() {}
+
+ public @Deprecated Object foo() {}
+
+ @Nullable Foo handle() {
+ @Nullable Bar bar = bar();
+ try (@Nullable Baz baz = baz()) {}
+ }
+
+ Foo(
+ @Nullable Bar //
+ param1, //
+ Baz //
+ param2) {}
+
+ void g(
+ @Deprecated
+ @Nullable ImmutableList
+ veryVeryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
+ @Deprecated
+ @Nullable ImmutableList
+ veryVeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooong) {}
+
+ @Deprecated
+ @Nullable TypeAnnotations() {}
+
+ enum Foo {
+ @Nullable BAR;
+ }
+
+ @Nullable @Nullable Object doubleTrouble() {}
+}