[JEP 440] Add support for record patterns#4432
Conversation
…methods for RecordPatternExpr
…llow unit tests to pass
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
|
| assertFalse(Navigator.findNameExpression(entry, "b").isPresent()); | ||
| } | ||
|
|
||
| @Test |
There was a problem hiding this comment.
Simple AST test
| assertEqualsStringIgnoringEol(code, new DefaultPrettyPrinter().print(cu)); | ||
| } | ||
|
|
||
| @Test |
There was a problem hiding this comment.
PrettyPrinter test
| assertTransformedToString(code, stmt); | ||
| } | ||
|
|
||
| @Test |
| } | ||
|
|
||
| @Override | ||
| @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator") |
There was a problem hiding this comment.
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))); |
There was a problem hiding this comment.
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.
| // 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); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Tests to ensure declarations in nested patterns are correctly exposed to children
|
|
||
| } | ||
|
|
||
| @Nested |
There was a problem hiding this comment.
Test to ensure symbols in record patterns can be solved in instanceof expressions
|
|
||
| assertThrows(UnsolvedSymbolException.class, resolveS); | ||
| } | ||
|
|
There was a problem hiding this comment.
Test to ensure symbols in record patterns can be solved in switch expressions
|
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; | ||
| } | ||
|
|
There was a problem hiding this comment.
Comments in the code would be welcome
|
Everything seems fine to me. If you have nothing to add, I will merge your PR. Thank you for your excellent work. |
|
Can you resolve the checkstyle violations? [INFO] There are 2 errors reported by Checkstyle 10.17.0 with dev-files/JavaParser-CheckStyle.xml ruleset. |
|
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 :) |
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
ResolvedRecordPatternDeclarationclass. I could implement one similar toResolvedTypePatternDeclaration, 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!