Skip to content

[JEP 440] Add support for record patterns#4432

Merged
jlerbsc merged 25 commits intojavaparser:masterfrom
johannescoetzee:johannes/record-pattern-impl
May 30, 2024
Merged

[JEP 440] Add support for record patterns#4432
jlerbsc merged 25 commits intojavaparser:masterfrom
johannescoetzee:johannes/record-pattern-impl

Conversation

@johannescoetzee
Copy link
Copy Markdown
Collaborator

@johannescoetzee johannescoetzee commented May 23, 2024

Implements #4385. I've already described the general approach I've taken in that issue, so won't repeat that here.

The diff is huge, but I think all of this is necessary to show that the implementation works. In an attempt to make this more manageable, I used the commits to document all the steps I took while implementing this. This means the commit list is also very long, but this will also be useful as a reference for improving the documentation on adding nodes and code generation in general (which I intend to do soon).

A lot of the tests added here are just boilerplate tests which either test generated code, or are copies of similar tests for TypePatternExpr. I've left comments on the tests that test more interesting functionality.

This PR doesn't include a ResolvedRecordPatternDeclaration class. I could implement one similar to ResolvedTypePatternDeclaration, but it's not obvious to me how this would be used (and the type pattern declaration one contains a comment suggesting the author of that wasn't too sure either). Any insight on how such a class could be useful would be much appreciated!

@codecov
Copy link
Copy Markdown

codecov bot commented May 23, 2024

Codecov Report

Attention: Patch coverage is 54.89130% with 83 lines in your changes are missing coverage. Please review.

Project coverage is 51.999%. Comparing base (58a4063) to head (33b200f).
Report is 2 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##            master     #4432       +/-   ##
=============================================
+ Coverage   51.943%   51.999%   +0.056%     
=============================================
  Files          505       507        +2     
  Lines        28481     28654      +173     
  Branches      4939      4969       +30     
=============================================
+ Hits         14794     14900      +106     
- Misses       11638     11685       +47     
- Partials      2049      2069       +20     
Flag Coverage Δ
AlsoSlowTests 51.999% <54.891%> (+0.056%) ⬆️
javaparser-core 51.999% <54.891%> (+0.056%) ⬆️
javaparser-symbol-solver 51.999% <54.891%> (+0.056%) ⬆️
jdk-10 51.996% <54.891%> (+0.056%) ⬆️
jdk-11 51.996% <54.891%> (+0.056%) ⬆️
jdk-12 51.996% <54.891%> (+0.056%) ⬆️
jdk-13 51.996% <54.891%> (+0.056%) ⬆️
jdk-14 51.996% <54.891%> (+0.056%) ⬆️
jdk-15 51.996% <54.891%> (+0.056%) ⬆️
jdk-16 51.996% <54.891%> (+0.056%) ⬆️
jdk-17 51.996% <54.891%> (+0.056%) ⬆️
jdk-18 51.996% <54.891%> (+0.056%) ⬆️
jdk-8 51.994% <54.891%> (+0.056%) ⬆️
jdk-9 51.996% <54.891%> (+0.056%) ⬆️
macos-latest 51.992% <54.891%> (+0.056%) ⬆️
ubuntu-latest 51.992% <54.891%> (+0.056%) ⬆️
windows-latest 51.978% <54.891%> (+0.056%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...va/com/github/javaparser/ast/expr/PatternExpr.java 50.000% <ø> (+6.250%) ⬆️
...ub/javaparser/ast/observer/ObservableProperty.java 89.017% <100.000%> (+0.063%) ⬆️
...or/language_level_validations/Java21Validator.java 100.000% <100.000%> (ø)
...om/github/javaparser/ast/visitor/CloneVisitor.java 39.479% <100.000%> (+1.726%) ⬆️
...parser/ast/visitor/GenericVisitorWithDefaults.java 98.076% <100.000%> (+0.018%) ⬆️
...vaparser/ast/visitor/NoCommentHashCodeVisitor.java 67.592% <100.000%> (+0.302%) ⬆️
...arser/ast/visitor/ObjectIdentityEqualsVisitor.java 99.038% <100.000%> (+0.009%) ⬆️
...ser/ast/visitor/ObjectIdentityHashCodeVisitor.java 97.115% <100.000%> (+0.028%) ⬆️
...hub/javaparser/ast/visitor/VoidVisitorAdapter.java 99.054% <100.000%> (+0.011%) ⬆️
...avaparser/ast/visitor/VoidVisitorWithDefaults.java 98.048% <100.000%> (+0.019%) ⬆️
... and 17 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c52a57a...33b200f. Read the comment docs.

assertFalse(Navigator.findNameExpression(entry, "b").isPresent());
}

@Test
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Simple AST test

assertEqualsStringIgnoringEol(code, new DefaultPrettyPrinter().print(cu));
}

@Test
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

PrettyPrinter test

assertTransformedToString(code, stmt);
}

@Test
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

LPP test

}

@Override
@Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
Copy link
Copy Markdown
Collaborator Author

@johannescoetzee johannescoetzee May 23, 2024

Choose a reason for hiding this comment

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

I don't know why these @Generated annotations appeared suddenly, but this code was, in fact, generated.

concreteSyntaxModelByClass.put(SimpleName.class, attribute(ObservableProperty.IDENTIFIER));
concreteSyntaxModelByClass.put(SingleMemberAnnotationExpr.class, sequence(comment(), token(GeneratedJavaParserConstants.AT), child(ObservableProperty.NAME), token(GeneratedJavaParserConstants.LPAREN), child(ObservableProperty.MEMBER_VALUE), token(GeneratedJavaParserConstants.RPAREN)));
concreteSyntaxModelByClass.put(StringLiteralExpr.class, sequence(comment(), stringToken(ObservableProperty.VALUE)));
concreteSyntaxModelByClass.put(TextBlockLiteralExpr.class, sequence(comment(), textBlockToken(ObservableProperty.VALUE)));
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I seem to have rearranged some items here to maintain alphabetic order. I can't remember why I chose to do that for this PR, so can undo it if that's preferred.

Comment on lines -81 to -93
// look for declaration in a pattern label for this entry
for (Expression e : wrappedNode.getLabels()) {
if (!e.isTypePatternExpr()) {
continue;
}

TypePatternExpr typePatternExpr = e.asTypePatternExpr();
if (typePatternExpr.getNameAsString().equals(name)) {
JavaParserPatternDeclaration decl = JavaParserSymbolDeclaration.patternVar(typePatternExpr, typeSolver);
return SymbolReference.solved(decl);
}
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I added this logic while adding support for switch pattern expressions. The possibility of having record patterns as well complicates this, however, so I moved the logic for finding declarations in patterns to AbstractJavaParserContext to avoid duplicating that. For that to work, I added the typePatternExprsExposedToChild method below which just finds all pattern exprs in the entry label and returns them (since they're all exposed to the children of this entry)


// First check if there are any pattern expressions available to this node.
Context parentContext = optionalParentContext.get();
if(parentContext instanceof BinaryExprContext || parentContext instanceof IfStatementContext) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The changes in this method are all to keep type solving logic for patterns contained. See a comment about this below in SwitchEntryContext

return wrappedNode;
}

public List<TypePatternExpr> typePatternExprsDiscoveredInPattern(PatternExpr patternExpr) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In the symbol solver, we're generally only interested in TypePatternExprs since these contain the variable declarations needed. This method just does a breadth-first traversal of the pattern tree to discover all TypePatternExprs contained in the nested RecordPatternExpr structure.

}

@Nested
class RecordPatternExprTests {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Tests to ensure declarations in nested patterns are correctly exposed to children


}

@Nested
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Test to ensure symbols in record patterns can be solved in instanceof expressions


assertThrows(UnsolvedSymbolException.class, resolveS);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Test to ensure symbols in record patterns can be solved in switch expressions

@johannescoetzee johannescoetzee marked this pull request as ready for review May 23, 2024 16:53
@johannescoetzee
Copy link
Copy Markdown
Collaborator Author

The codecov bot messages suggest I missed some boilerplate tests. I'll add those either tomorrow or early next week

public N getWrappedNode() {
return wrappedNode;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comments in the code would be welcome

@jlerbsc
Copy link
Copy Markdown
Collaborator

jlerbsc commented May 29, 2024

Everything seems fine to me. If you have nothing to add, I will merge your PR. Thank you for your excellent work.

@jlerbsc
Copy link
Copy Markdown
Collaborator

jlerbsc commented May 29, 2024

Can you resolve the checkstyle violations?

[INFO] There are 2 errors reported by Checkstyle 10.17.0 with dev-files/JavaParser-CheckStyle.xml ruleset.
Error: src/main/java/com/github/javaparser/resolution/Context.java:[26,8] (imports) UnusedImports: Unused import - com.github.javaparser.ast.expr.PatternExpr.
Error: src/main/java/com/github/javaparser/ast/expr/RecordPatternExpr.java:[11,8] (imports) UnusedImports: Unused import - java.util.regex.Pattern.

@johannescoetzee
Copy link
Copy Markdown
Collaborator Author

johannescoetzee commented May 30, 2024

I've updated the pr with a comment explaining the type pattern discovery method, tests that should satisfy some of the codecov issues (but not all) and which fixed checkstyle violations.

@jlerbsc if the remaining codecov violations are acceptable (they're all for generated boilerplate, as far as I can tell, except for the deprecated PrettyPrinterVisitor method which I added for anyone still using that, but which is tested in the new DefaultPrettyPrintVisitor), then I don't have anything further to add to this PR.

I think fixing #4440 should then be the only remaining task for java 21 support, but please let me know if you can think of anything I missed!

Edit: looks like I added enough tests to get the coverage above average and therefore codecov bot is happy, but I could still add some more if that's preferred :)

@jlerbsc jlerbsc merged commit 61d3619 into javaparser:master May 30, 2024
@jlerbsc jlerbsc added this to the next release milestone May 30, 2024
@jlerbsc jlerbsc added the PR: Added A PR that introduces new behaviour (e.g. functionality, tests) label May 30, 2024
@johannescoetzee johannescoetzee deleted the johannes/record-pattern-impl branch May 30, 2024 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Added A PR that introduces new behaviour (e.g. functionality, tests)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants