Skip to content

Commit bebecbb

Browse files
authored
Merge pull request #160 from openjavaformat/test/formatter-cases
Run formatter test cases from files under test-cases/
2 parents a13b036 + d5e569e commit bebecbb

1,438 files changed

Lines changed: 29188 additions & 13732 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitattributes‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# A formatter test case is compared byte for byte, line breaks included, so git must not convert them.
2+
*.case -text

‎open-java-format-benchmarks/build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ tasks.named('jmh', JMHTask.class) {
3232
environment.put('JARS_CLASSPATH', configurations.named('formatterNativeJars').map { conf -> conf.collect { it.absolutePath }.join(":") })
3333
}
3434

35-
// src/test/resources/PalantirDeeplyNestedCalls.java is a symlink to a formatter test input, which has to
35+
// src/test/resources/PalantirDeeplyNestedCalls.java is a copy of a formatter test input, which has to
3636
// keep its unformatted shape: leave src/test/resources out of any formatting step added to this build.
3737

3838
jmhCompileGeneratedClasses {

‎open-java-format-benchmarks/src/test/resources/PalantirDeeplyNestedCalls.java‎

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
class PalantirDeeplyNestedCalls {
2+
private static MagicConfigV1 testSheetV1 = MagicConfigV1.builder()
3+
.foooos(ImmutableList.of(testFieldOneV1))
4+
.baaars(ImmutableList.of(MagicConfigV1.builder()
5+
.foooos(ImmutableList.of(testFieldTwoV1, testFieldThreeV1))
6+
.baaars(ImmutableList.of(MagicConfigV1.builder()
7+
.baaars(ImmutableList.of(MagicConfigV1.builder()
8+
.baaars(ImmutableList.of(MagicConfigV1.builder()
9+
.foooos(ImmutableList.of(testFieldFourV1))
10+
.build()))
11+
.build()))
12+
.build()))
13+
.build()))
14+
.build();
15+
16+
void testMethod() {
17+
assertThat(ConfigServiceV1.getAllItems(item1, item2, item3, item4))
18+
.containsExactlyInAnyOrderElementsOf(Set.of(
19+
new ItemWithCustomLocator(
20+
ItemConfigV1.DEFAULT_CONFIG.toCustomString(),
21+
ItemConfigV1.createCustomConfig(ItemConfigV1Locator.of(TEST_ITEM_A))),
22+
new ItemWithCustomLocator(
23+
ItemConfigV1.builder()
24+
.id(getId(TEST_ITEM_A))
25+
.name(ItemName.of(TEST_API_NAME.get()))
26+
.apiName(TEST_API_NAME)
27+
.spec(ItemConfigV1Spec.native_(NativeItemConfigV1Spec.model(TestModel.of())))
28+
.category(TestCatalog.TEST_CATEGORY_ALPHA)
29+
.creator(TestCatalog.TEST_CREATOR_BETA)
30+
.status(ItemLifecycleStatus.EXPERIMENTAL)
31+
.statusV2(ItemLifecycleStatusV2.experimental(LifecycleStatusExperimental.of()))
32+
.inputSpec(ItemInputSpec.unknownInputType(UnknownInputSpec.of()))
33+
.creationDate(ItemMetadataInfo.builder().build())
34+
.performanceAttributes(
35+
ItemAttributes.builder().build())
36+
.categories(TestCatalog.TEST_CATEGORY_ALPHA)
37+
.build(),
38+
CustomItemLocator.hosted(HostedItemLocator.of(TEST_ITEM_B))),
39+
new ItemWithCustomLocator(
40+
ItemConfigV1.builder()
41+
.id(getId(TestModelCatalog.MODEL_XYZ_123.apiName()))
42+
.name(ItemName.of(TestModelCatalog.MODEL_XYZ_123
43+
.apiName()
44+
.get()))
45+
.apiName(TestModelCatalog.MODEL_XYZ_123.apiName())
46+
.spec(ItemConfigV1Spec.native_(
47+
NativeItemConfigV1Spec.hubModel(HubModelSpec.of())))
48+
.category(TestCatalog.TEST_CATEGORY_ALPHA)
49+
.creator(TestCatalog.TEST_CREATOR_BETA)
50+
.status(ItemLifecycleStatus.EXPERIMENTAL)
51+
.statusV2(ItemLifecycleStatusV2.experimental(LifecycleStatusExperimental.of()))
52+
.inputSpec(ItemInputSpec.unknownInputType(UnknownInputSpec.of()))
53+
.creationDate(ItemMetadataInfo.builder().build())
54+
.performanceAttributes(
55+
ItemAttributes.builder().build())
56+
.categories(TestCatalog.TEST_CATEGORY_ALPHA)
57+
.build(),
58+
CustomItemLocator.hosted(HostedItemLocator.of(TEST_ITEM_C))),
59+
// Discovered items
60+
new ItemWithCustomLocator(
61+
TestModelCatalog.MODEL_ABC_456.toItemApi(),
62+
CustomItemLocator.discovered(DiscoveredItemLocator.of())),
63+
new ItemWithCustomLocator(
64+
ItemConfigV1.builder()
65+
.id(getId(TEST_API_NAME))
66+
.name(ItemName.of(TEST_API_NAME.get()))
67+
.apiName(TEST_API_NAME)
68+
.spec(ItemConfigV1Spec.native_(
69+
NativeItemConfigV1Spec.hubModel(HubModelSpec.of())))
70+
.category(TestCatalog.TEST_CATEGORY_ALPHA)
71+
.creator(TestCatalog.TEST_CREATOR_BETA)
72+
.status(ItemLifecycleStatus.EXPERIMENTAL)
73+
.statusV2(ItemLifecycleStatusV2.experimental(LifecycleStatusExperimental.of()))
74+
.inputSpec(ItemInputSpec.unknownInputType(UnknownInputSpec.of()))
75+
.creationDate(ItemMetadataInfo.builder().build())
76+
.performanceAttributes(
77+
ItemAttributes.builder().build())
78+
.categories(TestCatalog.TEST_CATEGORY_ALPHA)
79+
.build(),
80+
CustomItemLocator.discovered(DiscoveredItemLocator.of()))));
81+
}
82+
83+
public Map<FooBarRid, BazQuxMetrics> otherMethod(
84+
FooAuthHeader authHeader, Set<FooBarRid> thingRids, WidgetTimeRange timeRange) {
85+
return myCustomService
86+
.get()
87+
.fetchData(authHeader, FooMyCustomClass.of(thingRids, timeRange))
88+
.entrySet()
89+
.stream()
90+
.collect(Collectors.toMap(
91+
Map.Entry::getKey, entry -> entry.getValue().getMetrics()));
92+
}
93+
}

‎open-java-format-idea-plugin/src/test/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingServiceTest.java‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,8 @@ void tearDown() throws Exception {
8282

8383
@Test
8484
void defaultFormatSettings() throws Exception {
85-
String input = Files.readString(
86-
Paths.get("../open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/A.input"));
87-
String output = Files.readString(
88-
Path.of("../open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/A.output"));
85+
String input = Files.readString(Paths.get("src/test/resources/A.input"));
86+
String output = Files.readString(Path.of("src/test/resources/A.output"));
8987
PsiFile file = createPsiFile("com/foo/FormatTest.java", input);
9088
ReformatCodeProcessor processor = new ReformatCodeProcessor(file, false);
9189
WriteCommandAction.runWriteCommandAction(file.getProject(), () -> {

open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/A.input renamed to open-java-format-idea-plugin/src/test/resources/A.input

File renamed without changes.

open-java-format/src/test/resources/com/palantir/javaformat/java/testdata/A.output renamed to open-java-format-idea-plugin/src/test/resources/A.output

File renamed without changes.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ case BreakOnlyIfInnerLevelsThenFitOnOneLine(boolean keepIndentWhenInlined) -> {
566566
// levels that are meant to look good even if partially inlined, e.g. method
567567
// chains, which will catch things like builders, but not other kinds of levels like
568568
// constant expressions.
569-
// See the palantir-expression-lambdas.input test for an example of what this is
570-
// trying to avoid.
569+
// See the palantir-expression-lambdas cases in test-cases/testdata for an example of
570+
// what this is trying to avoid.
571571

572572
// For this, need to actually check the last inner level of `lastLevel` (2 levels down).
573573
if (innerLevel.docs.isEmpty() || !(getLast(innerLevel.docs) instanceof Level)) {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ public static Formatter createFormatter(JavaFormatterOptions options) {
108108
return new Formatter(options, false);
109109
}
110110

111+
/** The options this formatter formats with. */
112+
JavaFormatterOptions options() {
113+
return options;
114+
}
115+
111116
/**
112117
* Construct a {@code Formatter} given a Java compilation unit. Parses the code; builds a {@link JavaInput} and the
113118
* corresponding {@link JavaOutput}.

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

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,18 @@ private static String wrapOnce(final int columnLimit, String input, Formatter fo
8282
return input;
8383
}
8484

85-
TreeRangeMap<Integer, String> replacements = getReflowReplacements(columnLimit, input);
85+
// The pieces continue the way the formatter continues a chain of +: four columns times the multiplier of its
86+
// style, eight in OJF.
87+
var continuationIndent = 4 * formatter.options().indentationMultiplier();
88+
TreeRangeMap<Integer, String> replacements = getReflowReplacements(columnLimit, continuationIndent, input);
8689
String firstPass =
8790
formatter.formatSource(input, replacements.asMapOfRanges().keySet());
8891

8992
if (!firstPass.equals(input)) {
9093
// If formatting the replacement ranges resulted in a change, recalculate the replacements on
9194
// the updated input.
9295
input = firstPass;
93-
replacements = getReflowReplacements(columnLimit, input);
96+
replacements = getReflowReplacements(columnLimit, continuationIndent, input);
9497
}
9598

9699
String result = applyReplacements(input, replacements);
@@ -99,7 +102,7 @@ private static String wrapOnce(final int columnLimit, String input, Formatter fo
99102
String secondPass = formatter.formatSource(result, rangesAfterAppliedReplacements(replacements));
100103

101104
if (!secondPass.equals(result)) {
102-
replacements = getReflowReplacements(columnLimit, secondPass);
105+
replacements = getReflowReplacements(columnLimit, continuationIndent, secondPass);
103106
result = applyReplacements(secondPass, replacements);
104107
}
105108

@@ -141,21 +144,23 @@ private static ImmutableSet<Range<Integer>> rangesAfterAppliedReplacements(
141144
return outputRanges.build();
142145
}
143146

144-
public static TreeRangeMap<Integer, String> getReflowReplacements(int columnLimit, final String input)
145-
throws FormatterException {
146-
return new Reflower(columnLimit, input).getReflowReplacements();
147+
public static TreeRangeMap<Integer, String> getReflowReplacements(
148+
int columnLimit, int continuationIndent, final String input) throws FormatterException {
149+
return new Reflower(columnLimit, continuationIndent, input).getReflowReplacements();
147150
}
148151

149152
private static class Reflower {
150153

151154
private final String input;
152155
private final int columnLimit;
156+
private final int continuationIndent;
153157
private final String separator;
154158
private final JCTree.JCCompilationUnit unit;
155159
private final Position.LineMap lineMap;
156160

157-
Reflower(int columnLimit, String input) throws FormatterException {
161+
Reflower(int columnLimit, int continuationIndent, String input) throws FormatterException {
158162
this.columnLimit = columnLimit;
163+
this.continuationIndent = continuationIndent;
159164
this.input = input;
160165
this.separator = Newlines.guessLineSeparator(input);
161166
this.unit = parse(input, /* allowStringFolding= */ false);
@@ -418,7 +423,16 @@ private void wrapLongStrings(
418423

419424
// Get the original source text of the string literals, excluding `"` and `+`.
420425
ImmutableList<String> components = stringComponents(input, unit, flat);
421-
var plain = reflow(columnLimit, trailing, components, first.get(), startColumn, fistLineCol, "", "");
426+
var plain = reflow(
427+
columnLimit,
428+
continuationIndent,
429+
trailing,
430+
components,
431+
first.get(),
432+
startColumn,
433+
fistLineCol,
434+
"",
435+
"");
422436
chains.add(new Chain(
423437
flat,
424438
first.get(),
@@ -443,6 +457,7 @@ private void wrapLongStrings(
443457
var components = stringComponents(input, unit, chain.flat());
444458
var pieces = reflow(
445459
columnLimit,
460+
continuationIndent,
446461
markers.tail(2).length(),
447462
components,
448463
chain.firstInChain(),
@@ -460,7 +475,7 @@ private String join(Chain chain, List<String> pieces, String firstLineMarkers, S
460475
return render(
461476
separator,
462477
pieces,
463-
chain.firstInChain() ? chain.firstLineColumn() + 4 : chain.startColumn() - 2,
478+
chain.firstInChain() ? chain.firstLineColumn() + continuationIndent : chain.startColumn() - 2,
464479
firstLineMarkers,
465480
otherLineMarkers);
466481
}
@@ -680,6 +695,8 @@ private static boolean isEscaped(String input, int idx) {
680695
* {@link #render}.
681696
*
682697
* @param columnLimit the number of columns to wrap at
698+
* @param continuationIndent how far the lines after the first are indented from the start of the first, before
699+
* their {@code + }, when the text begins its chain
683700
* @param trailing extra space to leave after the last line
684701
* @param components the text to reflow
685702
* @param first0 true if the text includes the beginning of its enclosing concat chain, i.e. a
@@ -692,6 +709,7 @@ private static boolean isEscaped(String input, int idx) {
692709
*/
693710
private static List<String> reflow(
694711
int columnLimit,
712+
int continuationIndent,
695713
int trailing,
696714
ImmutableList<String> components,
697715
boolean first0,
@@ -727,8 +745,8 @@ private static List<String> reflow(
727745
// add the split line to the output, and process whatever's left
728746
lines.add(String.join("", line));
729747
if (first) {
730-
// Subsequent lines have a four-space continuation indent and a `+ `.
731-
width -= 6;
748+
// Subsequent lines have a continuation indent and a `+ `.
749+
width -= continuationIndent + 2;
732750
// Also, switch to firstLineStartColumn in order to account for the fact that continuations
733751
// should get indented from the beginning of the first line.
734752
// This is to handle cases like:

0 commit comments

Comments
 (0)