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

Add support for switch expressions #520

Merged
merged 21 commits into from
Dec 21, 2021
Merged

Add support for switch expressions #520

merged 21 commits into from
Dec 21, 2021

Conversation

msridhar
Copy link
Collaborator

Fixes #289

Checker Framework 3.21.0 added support for switch expressions; we build on that to support the expressions in NullAway. We also add a jdk17-unit-tests module to test the support (which requires a JDK 12+ compiler).

(Copy of #518, but now from a branch on the main repo so Coveralls works)

@coveralls
Copy link

coveralls commented Dec 18, 2021

Pull Request Test Coverage Report for Build #610

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 67 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.07%) to 89.335%

Files with Coverage Reduction New Missed Lines %
src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java 24 90.77%
src/main/java/com/uber/nullaway/NullAway.java 43 93.96%
Totals Coverage Status
Change from base Build #603: -0.07%
Covered Lines: 3602
Relevant Lines: 4032

💛 - Coveralls

@msridhar
Copy link
Collaborator Author

This PR is ready to review I think. We don't get Coveralls support for the new jdk17-unit-tests module but I plan to add that in a follow-up. In any case, see NullawayJDK17Test for tests of switch expressions which do cover the new code.

ExpressionTree switchExpression = tree.getExpression();
if (switchExpression instanceof ParenthesizedTree) {
switchExpression = ((ParenthesizedTree) switchExpression).getExpression();
ExpressionTree switchSelectorExpression = tree.getExpression();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This variable rename is to avoid confusion now that we have switch expressions. Also, add a comment to explain the stripping of one level of parens

@msridhar
Copy link
Collaborator Author

JMH results. For master branch:

Benchmark                      Mode  Cnt   Score   Error  Units
AutodisposeBenchmark.compile  thrpt   25  17.580 ± 0.143  ops/s
CaffeineBenchmark.compile     thrpt   25   4.196 ± 0.012  ops/s

This PR:

Benchmark                      Mode  Cnt   Score   Error  Units
AutodisposeBenchmark.compile  thrpt   25  17.648 ± 0.181  ops/s
CaffeineBenchmark.compile     thrpt   25   4.237 ± 0.035  ops/s

So there's no slowdown on the benchmarks.

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

This basically LGTM, but I wonder if we shouldn't partition that long unit test a bit...

@@ -1944,8 +1949,13 @@ private boolean mayBeNullExpr(VisitorState state, ExpressionTree expr) {
exprMayBeNull = nullnessFromDataflow(state, expr);
break;
default:
throw new RuntimeException(
"whoops, better handle " + expr.getKind() + " " + state.getSourceForNode(expr));
// match switch expressions by comparing strings, so the code compiles on JDK versions < 12
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unfortunate, but makes sense...

SwitchExpressionNode node, TransferInput<Nullness, NullnessStore> input) {
// The cfg includes assignments of the value of each case body of the switch expression
// to the switch expression var (a synthetic local variale). So, the dataflow result
// for the switch expression is just the result for the switch expression var
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice work on the CF part here!

}

@Test
public void testSwitchExpression() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

These are a lot of test cases in a single test method. I am fine with landing as is, but... would it be too complicated to partition this into a few different test cases? (Basically one for each of the testX methods of SwitchExpr, since they all seem fairly independent)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, done in ae2900d

@msridhar msridhar enabled auto-merge (squash) December 21, 2021 00:12
Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

LGTM. Ready to merge! (The Coveralls regression is a CI limitation and should be addressed soon by #521 )

@msridhar msridhar merged commit 2835649 into master Dec 21, 2021
@msridhar msridhar deleted the handle-switch-expr branch December 21, 2021 19:41
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.

Support switch expressions
3 participants