Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ErrorProneTestHelperSourceFormat check #147

Merged
merged 6 commits into from
Aug 3, 2022

Conversation

Stephan202
Copy link
Member

@Stephan202 Stephan202 commented Jun 26, 2022

I've seen this being a topic of discussion several times (most recently here), so decided to do something about it. PTAL.

Suggested commit message:

Introduce `ErrorProneTestHelperSourceFormat` check (#147)

This new checker inspects inline code passed to `CompilationTestHelper` and
`BugCheckerRefactoringTestHelper` instances. It requires that this code is
properly formatted and that its imports are organized. Only code that
represents the expected output of a refactoring operation is allowed to have
unused imports, as most `BugChecker`s do not (and are not able to) remove
imports that become obsolete as a result of applying their suggested fix(es).

Copy link
Member Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on the tests for this new checker I already saved a lot of time just running patch.sh. 😄

@@ -52,7 +52,7 @@ public Description matchMethod(MethodTree tree, VisitorState state) {

Optional<Fix> fix = tryFixOrdering(originalOrdering, sortedAnnotations, state);

Description.Builder description = buildDescription(tree);
Description.Builder description = buildDescription(originalOrdering.get(0));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way this check reports the violation on the top-most annotation, which arguably is a better location. (Even better could be to report on the first out-of-order annotation, but not sure that's worth the hassle.)

@@ -124,7 +124,7 @@ void identificationWithinBinaryOperation() {
" s + String.valueOf((String) null),",
" s + String.valueOf(null),",
" s + String.valueOf(new char[0]),",
"",
" //",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one and the one below are introduced to retain the original grouping. Seemed worthwhile.

Copy link
Member

@rickie rickie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still couldn't figure out how to get the patch command to work with a self-apply on EPS. Would really love to see that working first. Would be nice if we could add that in the README.

This will make quite some people happy.

The code is really clean and nice IMO. Could find anything 🚀

import java.util.Optional;

/**
* A {@link BugChecker} which flags and corrects improperly formatted Error Prone test code.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is quite a specific check, I'd say it makes sense to at least mention GJF and perhaps refer to their docs?
Could be like a second paragraph? I like the explanation but it feels that GJF is missing from here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point; added a sentence. (Linking to the correct/least ambiguous docs is tricky, so opted for mere Javadoc instead.

int startPos = ASTHelpers.getStartPosition(sourceLines.get(0));
int endPos = state.getEndPosition(sourceLines.get(sourceLines.size() - 1));

/* Attempt to format the source code only if it fully consists of constant expression. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Attempt to format the source code only if it fully consists of constant expression. */
/* Attempt to format the source code only if it fully consists of constant expressions. */

Right? As in, every line needs to be a constant.

return Description.NO_MATCH;
}

List<? extends ExpressionTree> sourceLines =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't want to validate the name in a way? This is valid with the current setup:
.addSourceLines(\"D.java\", \"class C {}\")"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTOH, I can see why the in/ and out/ setup can make things a bit harder. (Perhaps it's out of scope)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of validating this, but indeed would like to defer that to another checker.

@@ -26,71 +26,137 @@ void identification() {
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"class A {",
" @BeforeAll void setUp1() {}",
" {",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fail to understand where this is coming from 👀.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's to make sure that the static arguments import isn't removed by the formatter. We need to keep it because it's important for one of the tests below:

// BUG: Diagnostic contains: (but note that arguments is already statically imported)

@Stephan202 Stephan202 force-pushed the sschroevers/enforce-test-code-formatting branch from b91b16f to 223a393 Compare July 31, 2022 10:58
Copy link
Member Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased and added a commit.

Still couldn't figure out how to get the patch command to work with a self-apply on EPS. Would really love to see that working first.

I filed #171.

import java.util.Optional;

/**
* A {@link BugChecker} which flags and corrects improperly formatted Error Prone test code.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point; added a sentence. (Linking to the correct/least ambiguous docs is tricky, so opted for mere Javadoc instead.

return Description.NO_MATCH;
}

List<? extends ExpressionTree> sourceLines =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of validating this, but indeed would like to defer that to another checker.

@@ -26,71 +26,137 @@ void identification() {
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"class A {",
" @BeforeAll void setUp1() {}",
" {",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's to make sure that the static arguments import isn't removed by the formatter. We need to keep it because it's important for one of the tests below:

// BUG: Diagnostic contains: (but note that arguments is already statically imported)

@Stephan202 Stephan202 force-pushed the sschroevers/enforce-test-code-formatting branch from 223a393 to 99771b2 Compare August 1, 2022 18:55
@rickie rickie force-pushed the sschroevers/enforce-test-code-formatting branch from 99771b2 to 1789863 Compare August 2, 2022 07:44
Copy link
Member

@rickie rickie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think this is a really cool check 🚀🚀🚀.

Verified that it works by using the new .patch.sh 😄, works like a charm!

@rickie
Copy link
Member

rickie commented Aug 2, 2022

Made two tiny tweaks to the release note. Without the s it doesn't flow as good IMO.

@Stephan202
Copy link
Member Author

Made two tiny tweaks to the release note. Without the s it doesn't flow as good IMO.

As-is the text needs to be reflowed. The s-es were there for a reason, though: we're passing the data to instances of these types, not to static methods.

@rickie
Copy link
Member

rickie commented Aug 2, 2022

^ Made a new tweak, PTAL :).

@Stephan202
Copy link
Member Author

Stephan202 commented Aug 2, 2022

With "instances of" we should not have the s-es, since the grammar is is then "instances of <type>"`. Tweaked again 🙃

Copy link
Member

@Badbond Badbond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super super nice that we're going to have this now 👍 No more formatting discussions on test code content! Tried very hard to squeeze two comments out but approving regardless 👍

import java.util.Optional;

/**
* A {@link BugChecker} which flags and corrects improperly formatted Error Prone test code.
Copy link
Member

@Badbond Badbond Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is -XepPatchChecks that does the correcting right? IIUC, this BugChecker just flags it. Comitted suggestion.

Suggested change
* A {@link BugChecker} which flags and corrects improperly formatted Error Prone test code.
* A {@link BugChecker} which flags improperly formatted Error Prone test code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is consistent with other checks indeed.

Comment on lines 138 to 139
String withReorderedImports = ImportOrderer.reorderImports(source, Style.GOOGLE);
String withRemovedImports =
Copy link
Member

@Badbond Badbond Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of withReorderedImports makes sense, but withRemovedImports felt odd at the formatSource line as it intuitively indicates that imports were removed if applicable, while this is not the case if retainUnusedImports is true. However, I really don't have an alternative apart from adding 'optionally' to it, which I don't like either. Placing comment to poke your brains 🧠

Suggested change
String withReorderedImports = ImportOrderer.reorderImports(source, Style.GOOGLE);
String withRemovedImports =
String withReorderedImports = ImportOrderer.reorderImports(source, Style.GOOGLE);
String withOptionallyRemovedImports =

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, withOptionallyRemovedImports explains exactly what is going on here, so I kinda like it.

One other option could be something like: resultingImports or finalImports. To show that the variable will hold the "end result (a set of imports) that will be passed to the actual formatter".
Perhaps a synonym of final or result would be better here.

Copy link
Member

@Badbond Badbond Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like those suggestions, as long as we keep the with part, as it involves the entire source code. We could also do withExpectedReorderedImports where what we expect depends on the value of the parameter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I like withOptionallyRemovedImports the most actually. That one is most clear/accurate/honest about what is happening IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committed. Feel free to further tweak @Stephan202.

Comment on lines +130 to +133
Splitter.on('\n')
.splitToStream(formatted)
.map(state::getConstantExpression)
.collect(joining(", "))));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hehe ironically, this leaves potentially unformatted code 😄 But nice that apply-error-prone-suggestion.sh will also run fmt:format to tackle this 💪

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think I'm missing that case, when will that happen 👀? Anyway, indeed nice it's already caught by the .sh.

Copy link
Member

@Badbond Badbond Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This replaces the entire existing argument array with the result of the formatted source code split on newlines, Stringified (constant expression), joined with ,. This puts it all on a single line. You can test this combining line 60 - 62 in RequestParamTypeCheckTest.java (so new statement straight after ;). Then run apply-error-prone-suggestions.sh but without the fmt:format in there. Now you can see the output is that the entire argument array is on a single line. After running mvn fmt:format, everything looks as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh ofcourse, nice, good catch 😄.

Stephan202 and others added 6 commits August 3, 2022 19:59
This new checker inspects inline code passed to `CompilationTestHelper`
and `BugCheckerRefactoringTestHelper`. It requires that this code is
properly formatted and that its imports are organized. Only code that
represents the expected output of a refactoring operation is allowed to
have unused imports, as most `BugChecker`s do not (and are not able to)
remove imports that become obsolete as a result of applying their
suggested fix(es).
@Stephan202 Stephan202 force-pushed the sschroevers/enforce-test-code-formatting branch from c785a02 to 37be08a Compare August 3, 2022 17:59
@Stephan202
Copy link
Member Author

I can live with that new name ;). Rebased; I think we can build if the PR passes.

@Stephan202 Stephan202 merged commit 38a57db into master Aug 3, 2022
@Stephan202 Stephan202 deleted the sschroevers/enforce-test-code-formatting branch August 3, 2022 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants