68c974e25e
Prior to the introduction of the "anonymous methods" experiment, a `return` statement and a `throw` expression behaved identically from the point of view of flow analysis, since both had the effect of causing control flow to jump outside the function that flow analysis is analyzing*. So they were both implemented using a single flow analysis method called `handleExit`. (*Technically a `return` from an inner function could lead to a point in an enclosing function, and a `throw` could lead to a `catch`, but flow analysis handles both of these possibilities using a conservative approximation (see the `FlowModel.conservativeJoin` method), rather than modeling them as direct jumps. But a `return` statement inside a block-bodied anonymous method is known to jump directly to the code that follows the anonymous method invocation, so `handleExit` is not the correct way to model it. Prior to this CL, this was handled in the analyzer's resolver (the corresponding CFE logic hasn't been written yet) by treating anonymous methods as a kind of loop construct. When visiting a return statement, the resolver would find the innermost enclosing function expression, local function, or block-bodied anonymous method; if it was a block-bodied anonymous method, then it would achieve the desired effect by calling `FlowAnalysis.handleBreak` rather than `FlowAnalysis.handleExit`. This was an abstraction leak, because in effect it put some of the business logic of flow analysis in its client (namely, the knowledge that return statements in block-bodied anonymous methods have a different flow analysis behavior than return statements elsewhere). This CL moves this business logic into flow analysis through the addition of a `FlowAnalysis.handleReturn` method. Flow analysis keeps track of whether the current point in the code being analyzed is inside a block-bodied anonymous method using the new field `FlowAnalysis._anonymousBlockContext`, which points to either `null` or an instance of a new type, `_AnonymousBlockContext`. This field is updated in proper nesting fashion by the methods: - `anonymousBlockBody_begin` - `anonymousBlockBody_end` - `_functionExpression_begin` - `_functionExpression_end` Finally, some aspects of https://dart-review.googlesource.com/c/sdk/+/482786 that are no longer necessary are rolled back: - A node no longer needs to be passed to `anonymousBlockBody_begin`. - The mapping from nodes to branch targets is changed back to a mapping from statements to branch targets, since it no longer needs to accept an anonymous method invocation as a key. Change-Id: I8b0f35cab016fc5bd609cfa1581ecaa36a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/485020 Reviewed-by: Erik Ernst <eernst@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
FE/analyzer shared code
This package contains logic that is shared between the front_end and analyzer packages. It is intended solely to facilitate development of the Dart SDK, and is not intended for use by end users. In particular, this package has no public API, so no guarantee is made of compatibility between one version of the package and the next.
End users should consider using the analyzer package to analyze Dart source code.