Skip to content

Commit 2730c64

Browse files
committed
reachability metadata
1 parent 19e6298 commit 2730c64

7 files changed

Lines changed: 114 additions & 12 deletions

File tree

palantir-java-format-jdk-bootstrap/src/main/java/com/palantir/javaformat/bootstrap/NativeImageFormatterService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public ImmutableList<Replacement> getFormatReplacements(String input, Collection
6161
}
6262
return MAPPER.readValue(output.get(), new TypeReference<>() {});
6363
} catch (IOException e) {
64-
throw new UncheckedIOException(String.format("Error running the native image command %s", output), e);
64+
throw new UncheckedIOException(
65+
String.format("Error running the native image command; received output: %s", output), e);
6566
}
6667
}
6768

palantir-java-format-native/src/main/resources/META-INF/native-image/reachability-metadata.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@
5050
"type": "com.google.common.collect.RegularImmutableList",
5151
"allDeclaredFields": true
5252
},
53+
{
54+
"type": "java.util.ImmutableCollections$AbstractImmutableList",
55+
"allDeclaredFields": true
56+
},
57+
{
58+
"type": "java.util.ImmutableCollections$AbstractImmutableCollection",
59+
"allDeclaredFields": true
60+
},
61+
{
62+
"type": "java.util.ImmutableCollections$List12",
63+
"allDeclaredFields": true
64+
},
5365
{
5466
"type": "com.google.common.collect.SingletonImmutableList",
5567
"allDeclaredFields": true

palantir-java-format/src/main/java/com/palantir/javaformat/doc/Token.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
import com.palantir.javaformat.Input;
2525
import com.palantir.javaformat.Op;
2626
import com.palantir.javaformat.Output;
27+
import com.palantir.javaformat.java.StringWrapper;
2728
import java.util.Optional;
2829

2930
/** A leaf {@link Doc} for a token. */
3031
@Immutable
3132
public final class Token extends Doc implements Op {
33+
3234
/** Is a Token a real token, or imaginary (e.g., a token generated incorrectly, or an EOF)? */
3335
public enum RealOrImaginary {
3436
REAL,
@@ -104,13 +106,12 @@ public void add(DocBuilder builder) {
104106
builder.add(this);
105107
}
106108

107-
// TODO(crogoz): this is where the token gets computed. I need to differentiate between multiLine Strings and single
108109
// Strings
109110
@Override
110111
protected float computeWidth() {
111-
if (token.getTok().getOriginalText().startsWith("\"\"\"")) {
112+
if (token.getTok().getOriginalText().startsWith(StringWrapper.TEXT_BLOCK_DELIMITER)) {
112113
// hack hack hack to not consider the size of the textBlock such that we won't break
113-
return 0;
114+
return StringWrapper.TEXT_BLOCK_DELIMITER.length();
114115
}
115116
return token.getTok().length();
116117
}
@@ -129,9 +130,9 @@ protected Range<Integer> computeRange() {
129130
public State computeBreaks(
130131
CommentsHelper commentsHelper, int maxWidth, State state, Obs.ExplorationNode observationNode) {
131132
String text = token.getTok().getOriginalText();
132-
if (token.getTok().getOriginalText().startsWith("\"\"\"")) {
133+
if (token.getTok().getOriginalText().startsWith(StringWrapper.TEXT_BLOCK_DELIMITER)) {
133134
// hack hack hack to not consider the size of the textBlock such that we won't break
134-
return state.withColumn(state.column() + 3);
135+
return state.withColumn(state.column() + StringWrapper.TEXT_BLOCK_DELIMITER.length());
135136
}
136137
return state.withColumn(state.column() + text.length());
137138
}

palantir-java-format/src/main/java/com/palantir/javaformat/java/FormatFileCallable.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@
3030
import java.util.List;
3131
import java.util.Set;
3232
import java.util.concurrent.Callable;
33-
import java.util.logging.Logger;
3433

3534
/** Encapsulates information about a file to be formatted, including which parts of the file to format. */
3635
class FormatFileCallable implements Callable<String> {
3736
private static final ObjectMapper MAPPER =
3837
JsonMapper.builder().addModule(new GuavaModule()).build();
39-
private static final Logger log = Logger.getLogger("FormatFileCallable");
38+
4039
private final String input;
4140
private final CommandLineOptions parameters;
4241
private final JavaFormatterOptions options;
@@ -55,12 +54,12 @@ public String call() throws FormatterException {
5554

5655
Formatter formatter = Formatter.createFormatter(options);
5756
if (parameters.outputReplacements()) {
58-
Set<Range<Integer>> rangesToChange = characterRanges(input).asRanges();
57+
RangeSet<Integer> characterRanges = characterRanges(input);
58+
Set<Range<Integer>> rangesToChange = characterRanges.asRanges();
5959
List<Replacement> replacements = formatter.getFormatReplacements(input, rangesToChange);
60-
// log.severe("rangesToChange: " + rangesToChange);
6160
if (parameters.reflowLongStrings()) {
6261
String formattedText = applyReplacements(input, replacements);
63-
if (!StringWrapper.needWrapping(options.maxLineLength(), formattedText)) {
62+
if (!StringWrapper.linesNeedWrapping(options.maxLineLength(), formattedText, characterRanges)) {
6463
return writeFormatReplacements(replacements);
6564
}
6665
String formattedSource = StringWrapper.wrap(options.maxLineLength(), formattedText, formatter);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2798,7 +2798,6 @@ private void visitRegularDot(List<ExpressionTree> items, boolean needDot) {
27982798
int length = needDot0 ? minLength : 0;
27992799
for (ExpressionTree e : items) {
28002800
if (needDot) {
2801-
// Don't add a break after a text block
28022801
if (length > minLength) {
28032802
builder.breakOp(Break.builder()
28042803
.fillMode(FillMode.UNIFIED)

palantir-java-format/src/main/java/com/palantir/javaformat/java/StringWrapper.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
import com.google.common.collect.ImmutableList;
2323
import com.google.common.collect.ImmutableSet;
2424
import com.google.common.collect.Range;
25+
import com.google.common.collect.RangeSet;
2526
import com.google.common.collect.TreeRangeMap;
27+
import com.google.common.collect.TreeRangeSet;
2628
import com.palantir.javaformat.Newlines;
29+
import com.palantir.javaformat.Utils;
2730
import com.sun.source.tree.BinaryTree;
2831
import com.sun.source.tree.LiteralTree;
2932
import com.sun.source.tree.MemberSelectTree;
@@ -493,6 +496,42 @@ public static boolean needWrapping(int columnLimit, String input) {
493496
return false;
494497
}
495498

499+
/** Returns true if any lines in the given Java source exceed the column limit. */
500+
public static boolean linesNeedWrapping(int columnLimit, String input, RangeSet<Integer> initialRangesToChange) {
501+
// TODO(cushon): consider adding Newlines.lineIterable?
502+
RangeSet<Integer> linesToChange = TreeRangeSet.create();
503+
Iterator<String> it = Newlines.lineIterator(input);
504+
int i = 0;
505+
boolean insideTextBlock = false;
506+
while (it.hasNext()) {
507+
String line = it.next();
508+
if (line.length() > columnLimit) {
509+
linesToChange.add(Range.closedOpen(i, i + 1));
510+
}
511+
if (!insideTextBlock && line.contains(TEXT_BLOCK_DELIMITER)) {
512+
insideTextBlock = true;
513+
linesToChange.add(Range.closedOpen(i, i + 1));
514+
} else if (insideTextBlock && line.contains(TEXT_BLOCK_DELIMITER)) {
515+
insideTextBlock = false;
516+
linesToChange.add(Range.closedOpen(i, i + 1));
517+
} else if (insideTextBlock) {
518+
linesToChange.add(Range.closedOpen(i, i + 1));
519+
}
520+
++i;
521+
}
522+
RangeSet<Integer> charRangeToCheck = Utils.lineRangesToCharRanges(input, linesToChange);
523+
return hasOverlap(initialRangesToChange, charRangeToCheck);
524+
}
525+
526+
static boolean hasOverlap(RangeSet<Integer> a, RangeSet<Integer> b) {
527+
for (Range<Integer> range : a.asRanges()) {
528+
if (!b.subRangeSet(range).isEmpty()) {
529+
return true;
530+
}
531+
}
532+
return false;
533+
}
534+
496535
/** Parses the given Java source. */
497536
private static JCTree.JCCompilationUnit parse(String source, boolean allowStringFolding) throws FormatterException {
498537
Context context = new Context();

palantir-java-format/src/test/java/com/palantir/javaformat/java/StringWrapperTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import static com.google.common.truth.Truth.assertThat;
1818

1919
import com.google.common.base.Joiner;
20+
import com.google.common.collect.Range;
21+
import com.google.common.collect.RangeSet;
22+
import com.google.common.collect.TreeRangeSet;
2023
import org.junit.jupiter.api.Test;
2124
import org.junit.jupiter.api.parallel.Execution;
2225
import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -48,6 +51,54 @@ public void testAwkwardLineEndWrapping() throws Exception {
4851
assertThat(StringWrapper.wrap(100, input, Formatter.create())).isEqualTo(output);
4952
}
5053

54+
@Test
55+
public void testLinesNeedWrapping() throws FormatterException {
56+
String input =
57+
"""
58+
class Value {
59+
String a = \"""
60+
hello
61+
\""".codePoints();
62+
63+
String b = getMyValue();
64+
65+
String c = String.format("This is a String that contains more characters %s", getValue());
66+
}
67+
""";
68+
String output =
69+
"""
70+
class Value {
71+
String a = \"""
72+
hello
73+
\""".codePoints();
74+
75+
String b = getMyValue();
76+
77+
String c =
78+
String.format("This is a String"
79+
+ " that contains more"
80+
+ " characters"
81+
+ " %s", getValue());
82+
}
83+
""";
84+
85+
RangeSet<Integer> fullInput = TreeRangeSet.create();
86+
fullInput.add(Range.closedOpen(0, input.length()));
87+
assertThat(StringWrapper.linesNeedWrapping(40, input, fullInput)).isTrue();
88+
assertThat(StringWrapper.wrap(40, input, Formatter.create())).isEqualTo(output);
89+
90+
RangeSet<Integer> noStringInput = TreeRangeSet.create();
91+
int bAssignment = input.indexOf("String b");
92+
int bEndLine = input.indexOf("\n", bAssignment);
93+
noStringInput.add(Range.closed(bAssignment, bEndLine));
94+
assertThat(StringWrapper.linesNeedWrapping(40, input, noStringInput)).isFalse();
95+
96+
RangeSet<Integer> onlyStringLiteralInput = TreeRangeSet.create();
97+
onlyStringLiteralInput.add(Range.closedOpen(bEndLine + 1, input.length()));
98+
assertThat(StringWrapper.linesNeedWrapping(40, input, onlyStringLiteralInput))
99+
.isTrue();
100+
}
101+
51102
private static String lines(String... line) {
52103
return Joiner.on('\n').join(line) + '\n';
53104
}

0 commit comments

Comments
 (0)