diff --git a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java index 4eb5b00ef..5f51b33ee 100644 --- a/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java +++ b/open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java @@ -678,10 +678,18 @@ public Void visitBreak(BreakTree node, Void unused) { @Override public Void visitTypeCast(TypeCastTree node, Void unused) { sync(node); - builder.open( - plusFour, - BreakBehaviours.preferBreakingLastInnerLevel(true), - LastLevelBreakability.ACCEPT_INLINE_CHAIN); + // An inline chain that ends at this level must have room for the whole type before the break in front of the + // operand. Without IF_FIRST_LEVEL_FITS the chain measured the type up to its first break, the one after the + // "<" of a parameterized type, and once inlined the type itself had to take that break: "(PrivilegedAction<" + // at the end of one line and "String>)" on the next. The type stays breakable for the rare cast that does not + // fit on a line at all. + builder.open(OpenOp.builder() + .debugName("typeCast") + .plusIndent(plusFour) + .breakBehaviour(BreakBehaviours.preferBreakingLastInnerLevel(true)) + .breakabilityIfLastLevel(LastLevelBreakability.ACCEPT_INLINE_CHAIN) + .partialInlineability(PartialInlineability.IF_FIRST_LEVEL_FITS) + .build()); token("("); scan(node.getType(), null); token(")"); diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.input b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.input new file mode 100644 index 000000000..ef55c2ccc --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.input @@ -0,0 +1,36 @@ +class TCPTransport { + @SuppressWarnings("removal") + static final Log tcpLog = Log.getLog( + "sun.rmi.transport.tcp", "tcp", LogStream.parseLevel(AccessController.doPrivileged((PrivilegedAction< + String>) + () -> System.getProperty("sun.rmi.transport.tcp.logLevel")))); + + static final Level level = LogStream.parseLevel(AccessController.doPrivileged((PrivilegedAction)()->System.getProperty("sun.rmi.transport.tcp.logLevel.and.some.more"))); + + static final Log methodReference = Log.getLog("sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel( + AccessController.doPrivileged( + ( PrivilegedAction ) + SomeVeryLongClassNameToFillTheLine + :: getTheTcpLogLevelProperty))); + + static final Log twoTypeArguments = + Log.getLog("sun.rmi.transport.tcp", "tcp", LogStream.parseLevel(AccessController.doPrivileged((Function< String ,Integer >) s-> + System.getProperty("sun.rmi.transport.tcp.logLevel.x")))); + + static final Log nested = Log.getLog("sun.rmi.transport.tcp", "tcp", LogStream.parseLevel(AccessController.doPrivileged((Map>) () -> System.getProperty("sun.rmi.transport.tcp.lv")))); + + static final Log qualified = Log.getLog("sun.rmi.transport.tcp", "tcp", + LogStream.parseLevel(AccessController.doPrivileged((java.util.function. + Function) s -> System.getProperty("sun.rmi.logLevel")))); + + static final Log intersection = Log.getLog("sun.rmi.transport.tcp", "tcp", LogStream.parseLevel( + AccessController.doPrivileged((Runnable + &java.io.Serializable) () -> System.getProperty("sun.rmi.transport.tcp.logLevelxx")))); + + static final Log annotated = Log.getLog("sun.rmi.transport.tcp", "tcp", + LogStream.parseLevel(AccessController.doPrivileged((Function<@Nullable String, Integer [ ]>) + s -> System.getProperty("sun.rmi.transport.tcp.lvl")))); +} diff --git a/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.output b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.output new file mode 100644 index 000000000..c179a2667 --- /dev/null +++ b/open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/ojf-issue-60-cast-type-in-inline-chain.output @@ -0,0 +1,47 @@ +class TCPTransport { + @SuppressWarnings("removal") + static final Log tcpLog = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.tcp.logLevel")))); + + static final Level level = LogStream.parseLevel(AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.tcp.logLevel.and.some.more"))); + + static final Log methodReference = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (PrivilegedAction) SomeVeryLongClassNameToFillTheLine::getTheTcpLogLevelProperty))); + + static final Log twoTypeArguments = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (Function) s -> System.getProperty("sun.rmi.transport.tcp.logLevel.x")))); + + static final Log nested = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (Map>) () -> System.getProperty("sun.rmi.transport.tcp.lv")))); + + static final Log qualified = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (java.util.function.Function) s -> System.getProperty("sun.rmi.logLevel")))); + + static final Log intersection = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (Runnable & java.io.Serializable) () -> System.getProperty("sun.rmi.transport.tcp.logLevelxx")))); + + static final Log annotated = Log.getLog( + "sun.rmi.transport.tcp", + "tcp", + LogStream.parseLevel(AccessController.doPrivileged( + (Function<@Nullable String, Integer[]>) s -> System.getProperty("sun.rmi.transport.tcp.lvl")))); +}