Description
A nice property of nearly all analyzer AstNode
types is that the set of Token
, AstNode
, and NodeList
objects that are pointed to by the AstNode
always covers non-overlapping ranges of tokens.
However, FormalParameterList
is an exception, because FormalParameterList.parameters
is a NodeList
of all the parameters (including required positional, optional positional, and named parameters), and FormalParameterList.leftDelimiter
is the {
or [
token that precedes the first optional positional or named parameter. Therefore, FormalParameterList.leftDelimiter
, when present, is a token that is within the span of tokens pointed to by FormalParameterList.parameters
.
An unfortunate consequence of this is that the lists returned by FormalParameterList.childEntities
and FormalParameterListImpl.namedChildEntities
behave oddly: they expand out the parameters
node list into its constituent elements, and insert the leftDelimiter
at the appropriate spot in the list.
This seems confusing and bug-prone to me. I think we should consider changing the FormalParameterList
AST representation from this:
class FormalParameterList {
Token get leftParenthesis;
NodeList<FormalParameter> get parameters;
Token? get leftDelimiter;
Token? get rightDelimiter;
Token get rightParenthesis;
}
To something more like this:
class FormalParameterList {
Token get leftParenthesis;
NodeList<FormalParameter> get requiredPositionalParameters;
OptionalOrNamedFormalParameters? get optionalPositionalParameters;
OptionalOrNamedFormalParameters? get namedParameters;
Token get rightParenthesis;
}
class OptionalOrNamedFormalParameters {
Token get leftDelimiter;
NodeList<FormalParameter> get parameters;
Token get rightDelimiter;
}
In addition to avoiding overlap between nodelists and tokens, this would have the advantage of more closely following the grammar of the language spec, and would be potentially more future-proof if we ever decide to allow a single function to have both optional positional and named parameters.