Skip to content

Conversation

sktpy
Copy link
Contributor

@sktpy sktpy commented Feb 17, 2024

Resolves #14344

Reasoning for the changes are mentioned in the corresponding review comments of mine.


Regression: (Report)
Differences found (expected).

  • Added violations(71): Example (rest occurrences are similar). (Line 123)
componentPlugins = new DualKeyHashMap<> ();
//                                    ^
//  '>' is followed by whitespace  ---+

This added violation was not detected before (a false negative, reasoning in the description of the Issue this PR resolves)

  • Removed violations(3): Example (rest occurrences are similar). (Line 78)
return new <@BG Inner<@BH Integer>> @BI Inner<@BJ Inner<@BK Integer>>(null);
//         ^
//         +---  '<' is preceded with whitespace.

This removed violation is a false positive which was detected as a violation before because generics enclosing Annotations that were succeeding new keyword weren't detected as the cases where they should be preceded with a whitespace.
These cases are now detected properly in the fix (See comment).

Diff Regression config: https://gist.githubusercontent.com/sktpy/44a31ea4e946a0755fa3e331fd65de98/raw/50e5257788a0f001f2ad184b1a7cbac7910e8b5b/check.xml

@sktpy sktpy marked this pull request as draft February 17, 2024 10:22
Copy link
Contributor

Report generation failed on phase "parse_body",
step "Parsing content of PR description".
Link: https://github.com/checkstyle/checkstyle/actions/runs/7941040371

@sktpy
Copy link
Contributor Author

sktpy commented Feb 17, 2024

GitHub, generate report or else... 😈🔪

Copy link
Contributor

https://checkstyle-diff-reports.s3.us-east-2.amazonaws.com/28c7818_2024125529/reports/diff/index.html

@@ -54,6 +54,7 @@ public void testWhitespaceAroundGenerics() throws Exception {
"14:46: " + getCheckMessage(messages, msgPreceded, ">"),
"15:33: " + getCheckMessage(messages, msgFollowed, "<"),
"15:33: " + getCheckMessage(messages, msgPreceded, "<"),
"15:46: " + getCheckMessage(messages, msgFollowed, ">"),
Copy link
Contributor Author

@sktpy sktpy Feb 17, 2024

Choose a reason for hiding this comment

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

All the similar additions in expected violations is due to following:
In this instance the extra violation is in the following line:


Before the fix, check didn't considered the whitespace between > ( as a violation, this is now correctly identified in the fix.

* @param ast ast
* @return true if generic after {@code LITERAL_NEW}
*/
private static boolean isGenericAfterNew(DetailAST ast) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Method name change from isGenericBeforeCtor() to isGenericAfterNew(), this describes method's behaviour more accurately, as it only identified the cases where generic existed after new keyword.
The method didn't identified cases where generic preceded constructor invocation () which was the cause for the false negative.

The method now also identifies a new similar case for Annotations (case 3.)

//
// new <String>Object()
// ^
// 3. +--- ws required
Copy link
Contributor Author

@sktpy sktpy Feb 17, 2024

Choose a reason for hiding this comment

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

Added example new <String>Object() in the comments as isGenericBeforeCtor() (now isGenericAfterNew()) was added earlier to be used in this method to detect a new type of case for which a preceding whitespace was required, but the comment was not updated in that commit to reflect this new behaviour.

package com.puppycrawl.tools.checkstyle.checks.whitespace.genericwhitespace;

public class InputGenericWhitespaceBeforeRecordHeader {
record Session<T>() {}
Copy link
Contributor Author

@sktpy sktpy Feb 17, 2024

Choose a reason for hiding this comment

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

Disclaimer: Contains some off-topic observations.

The purpose of this input and the corresponding test is to kill the mutation which survived after the changes in Check.
Surviving mutation was replacing charAfter == '(' with false in the following line:


Why this didn't survived before:

Before the fix, check didn't identified all the cases where generic was present before constructor invocation, which meant some CTOR cases where > was succeeded with ( weren't filtered through the following if statement:

if (isGenericBeforeMethod(ast) || isGenericBeforeCtor(ast)) {

Such cases went through isCharacterValidAfterGenericEnd() in the following else if block, making the mutant produce illegal follow violation, hence killing the mutant.
Due to the fix, all the possible existing cases where > could be succeeded by ( were filtered through the if statement, meaning none of the inputs went through isCharacterValidAfterGenericEnd(), hence creating that surviving mutation.

So after a bit of mutant hunting to find a valid input where > could be succeeded by ( but wasn't before Method or Ctor, found out that such valid input exist for generic before record header, which was able to kill the mutant.

As of now, we don't have a clear definition in the documentation on how to handle whitespace for generic that is before a record header, current check does not count space between > and ( of record header as a violation, will open an Issue shortly for discussing if it should(See #14502), based on the decision of the discussion, will update the Check accordingly and strengthen the test inputs for the records in a separate PR.

Funny thing is that if there is supposed to be violation for the case above, this will revive the mutant, as we will now be filtering the killing input in the if statement(this in my knowledge makes for all possible cases where generic can be followed by (), which will mean that the surviving mutated operand could be safely removed if no regressions are found and no one is aware of such input.

*/
private static boolean isGenericBeforeCtor(DetailAST ast) {
private static boolean isGenericBeforeCtorInvocation(DetailAST ast) {
Copy link
Contributor Author

@sktpy sktpy Feb 17, 2024

Choose a reason for hiding this comment

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

The method is used to identify cases where > should not be followed by whitespace, fixing the false negative.

@sktpy
Copy link
Contributor Author

sktpy commented Feb 17, 2024

Failing checks in CI are unrelated. (Cirrus, YAML Validation for site.xml)

@sktpy sktpy marked this pull request as ready for review February 17, 2024 15:51
Copy link
Member

@romani romani left a comment

Choose a reason for hiding this comment

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

Please extend inputs by a bit more cases.
We need to not rely on regression too much in future, so we collecting all different types of how code can be written.

Copy link
Member

@romani romani left a comment

Choose a reason for hiding this comment

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

items:

@sktpy sktpy force-pushed the issue-14344-genericwhitespace-false-negative branch 3 times, most recently from 3c611a0 to c5abe70 Compare February 19, 2024 13:26
…n to the '>' rule for succeeding whitespaces
@sktpy sktpy force-pushed the issue-14344-genericwhitespace-false-negative branch from c5abe70 to d79288a Compare February 21, 2024 14:27
Copy link
Member

@romani romani left a comment

Choose a reason for hiding this comment

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

ok to merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GenericWhitespace Check ignores exception to the ">" rule for succeeding whitespaces
3 participants