Add a syntactic diagnostic for extension type augmentations that declare
representation fields. Extension type augmentations may augment the
declaration, but they must not redeclare the representation.
Thread an explicit parser option through primary constructor parsing so
extension type augmentations can omit a representation without producing
the usual missing-primary-constructor diagnostics, while still reporting
an error when a representation is present.
Register the new diagnostic in the shared and analyzer generated
diagnostic tables and add it to fix status tracking.
Change-Id: I84815bb0669a76126564e590760e93096a3af046
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505860
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Permit `abstract` on top-level variable declarations when the
augmentations feature is enabled. Previously the parser always reported
`abstract` as extraneous at the top level, which rejected valid syntax
and dropped the modifier before later stages could see it.
Thread the abstract token through top-level field parsing, record it on
`TopLevelVariableDeclaration`, and pass it through the front-end
builders. Reorder the field callback arguments so `augment` precedes
`abstract`, matching the augmentation grammar for incomplete top-level
variables and keeping the parser, listener, and outline plumbing
consistent.
Change-Id: I680414a746b707d483e485702685c95f28a9c9ac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/494564
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
A flag that tells whether constructor is in an abstract class, enum or mixin was not correctly passed for primary constructors. This flag determines whether constructor tear-off lowerings are created for backends that use this, such dart2js and dartdevc.
The parser listener is updated to pass a DeclarationKind for primary constructors, similar to what is already done for regular constructors. The enable the CFE to pass the correct flag.
Change-Id: I114417795ae276dfeab9f10a0b0fcbcd2dbfc00b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/490541
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This is one of several planned batches of changes to transition the
front end (and related packages) away from the old `withArgumentsOld`
diagnostic reporting method, and to the new `withArguments`
method. The difference between the two is that `withArguments` has
named parameters rather than positional ones, so (a) it's less likely
for parameters to be mixed up, and (b) it's compatible with the
calling conventions used by analyzer diagnostics.
As part of this transition, I'm taking the opportunity to rename the
parameters themselves (since the names previously were restricted to a
very small set of possibilities based on type), and to document them
in `messages.yaml`. To avoid fatigue (both for myself and code
reviewers), I've chosen to break the change into many smaller batches.
The only changes in this CL that were manually written are those in
`messages.yaml`. The others were produced by running the standard
diagnostic message code generator, running the script
`use_new_with_arguments.dart`, and then updating front end parser
expectations.
Change-Id: I6a6a6964699f00e7e91af2e682ce1baa1846ca13
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/478060
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Changes the `front_end` and `_fe_analyzer_shared` code that reports
the following diagnostics so that it uses `withArguments` rather than
`withArgumentsOld`:
- `expectedButGot`
- `expectedButGot2`
- `expectedAfterButGot`
- `expectedToken`
- `unmatchedToken`
- `constFieldWithoutInitializer`
- `finalFieldWithoutInitializer`
- `superclassHasNoMethod`
- `unavailableDartLibrary`
- `unsupportedPlatformDartLibraryImport`
These messages required special care because they are translated into
analyzer diagnostics by the analyzer method
`FastaErrorReporter.reportByCode`, and the logic to do the translation
depends on the exact parameter names used by the messages.
For some of the messages I've clarified the parameter names and
updated `FastaErrorReporter.reportByCode` accordingly. For others, I
left the parameter names as is.
Change-Id: I6a6a696481c75f4cbb198d1e012aa1ca4294ed61
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/476323
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This [handlePositionalArgument] and [handlePositionalRecordField] methods to the parser listener, allowing listeners to normals arguments and record fields
Change-Id: I3947e196dafffea2ab383f797904c857db8327ce
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/469620
Reviewed-by: Jens Johansen <jensj@google.com>
This adds a beginConstructor listener method and calls this before constructor instead of beginMethod. This makes it possible for listeners to fully separate handling of constructors from methods.
Change-Id: Ibcbcf76ccb6d97314d395c4c0efcb4f9d073519a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/462140
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This merges endX methods for non-top-level members into endMethod, endConstructor, endFactory and endFields.
These methods now have a DeclarationKind parameter that can be used to distinguish them.
Change-Id: I458d37a70b6c7839612f7199dad95f9a61e76e7a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/462120
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This is part of a series of CLs that will standardize CFE error
reporting to always use `codeFoo.withArguments(...)` when reporting
errors that take arguments and `codeFoo` when reporting errors that
don't take arguments, rather than `templateFoo.withArguments(...)`
when reporting errors that take arguments and `messageFoo` when
reporting errors that don't take arguments. This change will have two
advantages:
- It will lend greater consistency to the CFE codebase, by allowing
the same `code...` objects to be used both to name error codes
(e.g., in test expectations) and to report errors. This will allow
everything associated with a certain error code to be found using a
single invocation of "Find References" in the editor, rather than
having to search separately for uses of the code and the message or
template.
- It should hopefully make the experience of writing code that reports
errors more pleasant, since it will no longer be necessary to look
up an error to see whether it takes arguments before using it;
instead, the developer will be able to type the name of the message
`code...` declaration, and then use autocompletion to see whether
`.withArguments(...)` is required.
In this CL, the code generator for error messages is changed so that
both `template...` and `code...` declarations have the static type
`Template` (and, indeed, refer to the same constant
object). Previously, `code...` declarations had the static type
`Code`, and referred to a constant object with runtime type
`Code`. This will allow uses of `template...` to be replaced with
`code...`. In follow-up CLs, the uses of `template...` will be changed
to `code...`, and the `template...` declarations will be removed.
Since the `toString` methods on `Template` and `Code` differ, I had to
make some changes to ID tests and parser tests, both of which depend
on the behavior of `toString`:
- For ID tests, I was able to preserve the existing test expectations
by modifying the `errorsToText` function (in
`pkg/front_end/lib/src/testing/id_testing_utils.dart`).
- For parser tests, I wasn't able to find an easy way to preserve the
existing test expectations, so I updated the expectations to match
the new behavior.
Change-Id: I8a461d451b06dd2f88b3e59f0cb2153711b09461
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/442731
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This splits handleEndingBinaryExpression into two new listeners handleDotAccess for `.` and `?.` access and handleCascadeAccess for `..` and `?..`, both with an explicit `isNullAware` flag.
This is a step towards handling `a.b` different from `a + b` in the parser such that listeners don't have to create a value for `b` the works in both use cases; in the first is just a named operation performed on the receiver, whereas in the second case it is a full expression in its own right.
Change-Id: I04ec80401f8f2dbb8dffa86543c434e530b18cf7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/442821
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
This adds the enclosingDeclarationName to the beginMethod of the
parser listener.
This enables the removal BuilderFactory.currentTypeParameterScopeBuilder.
Change-Id: Ie2bec9432c20b8bdbd62a14e8a65c272179d4698
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/383182
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This changes the BodyBuilder to create FunctionTypeParameter instead
of FormalParameterBuilder for "parameters" in function types. This
avoids the creation of unnecessary VariableDeclaration nodes
function types.
The types of these VariableDeclarations where created before the type
variable scope was completed, introducing an artificial dependency on
the pending nullability computation.
Change-Id: Ie1203fa4c78a27f3e7a0dfad16725cbbde24a6a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/381143
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
When the parser sends events to the listener some events has a pair of
parameters, `beginToken` and `endToken`. Most of these are constructed
in such a way that the `beginToken` is the first token and the
`endToken` is the last token in that construct. This is for instance the
case with `endClassDeclaration`.
It was, however, not the case for `endMetadata` where `endToken` instead
was the next token *not* in the metadata.
In this CL I've found a changed the following to point to the last token
in the construct instead of the next token not in the construct and
renamed the parameter where it made sense:
* `endAssert` --- and renamed `semicolonToken` (which only pointed to
a semicolon for statements) to `endToken`.
* `endAwaitExpression`
* `endConstLiteral` --- and renamed `token` to `endToken`
* `endConstructorReference`
* `endFieldInitializer` --- and renamed `token` to `endToken`
* `endForIn`
* `endForInBody` --- and renamed `token` to `endToken`
* `endForStatement`
* `endForStatementBody` --- and renamed `token` to `endToken`
* `endFunctionExpression` --- and renamed `token` to `endToken`
* `endInitializer` --- and renamed `token` to `endToken`
* `endInitializers`
* `endInvalidAwaitExpression`
* `endMetadata`
* `endSwitchCase`
* `endTopLevelDeclaration` --- and renamed `nextToken` to `endToken`
* `endWhileStatement`
* `endWhileStatementBody` --- and renamed `token` to `endToken`
* `handleNoConstructorReferenceContinuationAfterTypeArguments`
In the few places in listeners where these values were used I've mostly
updated to do e.g. `endToken.text!` to retain the current behavior.
Change-Id: I25495e160d1eec5c75bcf1313b512cd04bcb1533
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364322
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Sometimes when the parser is performing error recovery it skips tokens
until it finds the next `,` or `;`, to try to get back on track. This
is handled by the `Parser.findNextCommaOrSemicolon` method.
When this method encounters a `BeginToken` (i.e., `(`, `[`, `{`, or
`<`), it needs to skip to the matching end token (using the `endToken`
getter), so that it doesn't try to resume parsing inside some nested
structure.
However, sometimes there is no matching end token (either because the
user has failed to properly matched `()`, `[]`, or `{}`, or because
the `BeginToken` is `<`, which doesn't always have a matching `>`). To
avoid a crash when this happens, `Parser.findNextCommaOrSemicolon`
needs to treat an unmatched `BeginToken` like an ordinary token, and
just advance to the next token.
Fixes https://github.com/dart-lang/sdk/issues/54236.
Bug: https://github.com/dart-lang/sdk/issues/54236
Change-Id: Id208c7a46c9c00b69f7f460a638d59486ebaffea
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/339980
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This passes the first token of these top level declaration directly
to the endX listener method.
In the CFE this is used to ensure that can handle the new modifiers in
the textual outline. Furthermore, support for extension types is added
and having an "unknown chunk" now results in an error. The latter should
help us keep the textual outline up-to-date wrt new features.
Change-Id: I813d6162b6cba0a2bf550ed33a6091abf9bf49f8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324702
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Two of these tests (`recordPattern_nullable_beforeAs` and
`recordPattern_nullable_beforeWhen`) verify that the fix for #52439
(Destructuring with explicit type of nullable record is a parsing
error), which causes `(...)? identifier` to be recognized as a
variable pattern, doesn't get confused by the pseudo-identifiers `as`
and `when`, and so it continues to correctly parse `(...)? as ...` as a
cast pattern and `(...)? when ...` as a guarded pattern.
The other two tests (`recordPattern_nonNullable_beforeAs` and
`recordPattern_nonNullable_beforeWhen`) verify that `(...) as ...` and
`(...) when ...` are parsed correctly. These forms were never broken,
but they were not well tested either.
Bug: https://github.com/dart-lang/sdk/issues/52439
Change-Id: I866e1c7a6a8e47e0cd91a1a77654405f395b50da
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/305844
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Previously, if a record-typed variable pattern lacked a `var` or
`final` keyword, and was followed by one of the tokens `||`, `&&`,
`as`, `?`, `!`, `when`, or `=>`, the parser would fail to recognize
it. This happened because the call to `computeVariablePatternType`
wasn't passing `true` for the optional parameter `required`; that in
turn placed `computeType` in a mode where it believed it was parsing a
potentially ambiguous construct in a top-level declaration, and hence
it would only accept the record type if the variable name was followed
by something that looked like part of a correct declaration (e.g. a
comma).
The fix is to pass `true` for the optional parameter `required` of
`computeVariablePatternType`. This places `computeType` in a mode
where it accepts the record type regardless of what follows it. This
is correct behavior since at the point where a variable pattern is
being parsed, ambiguities have already been taken care of and the
construct being parsed is most definitely a variable pattern.
Fixes#52521.
Change-Id: If20772ad914827a29df45c27eefb382ec1f470d2
Bug: https://github.com/dart-lang/sdk/issues/52521
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/305848
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In rare circumstances involving syntax errors, the `parsePattern`
method inserts a synthetic token but does not consume any
tokens. Usually when this happens it's not a problem, because whatever
method is calling `parsePattern` consumes some tokens, so the parser
always makes progress. However, when parsing list patterns, after
calling `parsePattern`, the parser would look for a `,`, and if it
didn't find one, it would supply a synthetic `,` and call
`parsePattern` again, resulting in an infinite loop. A similar
situation happened with map patterns, though the situation was more
complex because in between the calls to `parsePattern`, the parser
would also create synthetic key expressions and `:`s.
To fix the problem, when parsing a list or map pattern, after the call
to `parsePattern`, the parser checks whether any tokens were
consumed. If no tokens were consumed, it ignores the next token from
the input stream in order to make progress.
I also investigated whether there were similar issues with
parenthesized/record patterns and switch expressions, since those
constructs also consist of a sequence of patterns separated by tokens
and other things that could in principle be supplied
synthetically. Fortunately, parser recovery doesn't get into an
infinite loop in those cases, so I didn't make any further
changes. But I did include test cases to make sure.
Fixes#52352.
Bug: https://github.com/dart-lang/sdk/issues/52352
Change-Id: Idc8140236f6054deb1fd3c862036fe47dd84f30b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/302803
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In https://dart-review.googlesource.com/c/sdk/+/299400, the parser was
adjusted so that it no longer accepts `when` and `as` as the names for
variable patterns in cases where there is a possible ambiguity
(e.g. `int when` is not accepted as a pattern because `int` is a
legitimate pattern, therefore `when` could introduce a guard
clause). This change further prohibits `when` and `as` from being the
names of variable patterns or identifier patterns even in the case
where there is no ambiguity. This is in line with the discussion at
https://github.com/dart-lang/sdk/issues/52199#issuecomment-1526297771,
and the spec change at
https://github.com/dart-lang/language/pull/3033.
Three new error codes are introduced, to cover the three circumstances
in which `when` or `as` might be used illegally: in a declared
variable pattern, in an assigned variable pattern, or in an identifier
pattern. I've also added analyzer tests to ensure that the parser
recovers from these errors nicely. Unfortunately, nice error recovery
is only feasible in the non-ambiguous cases.
I've also updated the language test expectations in
`tests/language/patterns/version_2_32_changes_error_test.dart` to
reflect the new error messages, and added a few more examples of uses
of `when` and `as` that are still permitted.
Fixes#52260.
Bug: https://github.com/dart-lang/sdk/issues/52260
Change-Id: I229f627aa639659c30b83c74895759207da279f7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/301482
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This change fixes parsing of case clauses such as:
case foo when !flag:
Constructions like this require some lookahead in order to parse
correctly, because the token `when` is valid both as an identifier and
as a part of the grammar for a case clause. Therefore, at the time
`foo` is encountered, the parser must decide whether it is looking at
a variable pattern (`foo when`, where `when` is the name of the
variable) or an identifier pattern (`foo`, where `when` begins the
case's guard clause). Previous to this fix, the algorithm for
disambiguating these two choices was as follows:
- If the token sequence starting at `foo` looked like a type, and the
token that follows was an identifier, the parser assumed it was
looking at a variable pattern with a type; otherwise it assumed it
was looking at an identifier pattern.
- EXCEPT that if the token that followed the supposed type was `when`
or `as` (both of which are valid identifiers), then it probed
further:
- If the token that followed `when` or `as` was a token that could
legitimately follow a pattern, then it assumed that it was looking
at a variable pattern with a type. (The tokens that could
legitimately follow a pattern are `,`, `:`, `||`, `&&`, `)`, `}`,
`]`, `as`, `when`, `?`, `!`).
- Otherwise it assumed that it was looking at an identifier pattern.
This didn't fully disambiguate, because the third bullet didn't
account for the fact that the tokens `as`, `when`, and `!` could
_either_ legitimately follow a pattern _or_ legitimately begin an
expression (or, in the case of `when`, a type), therefore constructs
like the following were incorrectly parsed:
- `case foo when as:` (where `as` is a local boolean variable)
- `case foo when when:` (where `when` is a local boolean variable)
- `case foo when !flag:` (where `flag` is a local boolean variable)
- `case foo as when:` (where `when` is the name of a type)
The solution is to simplify the disambiguation logic so that if if the
token that follows the supposed type is `when` or `as`, then the
parser assumes that it's looking at an identifier pattern, _not_ a
typed variable pattern.
The consequence of this is that the above four constructions are
parsed correctly; however it is no longer possible for a typed
variable pattern to name a variable `when` or `as`.
For consistency we would like to prohibit _any_ variable pattern from
naming a variable `when` or `as`, however to keep this change as small
as possible (and reduce the risk involved in a possible cherry-pick)
that will be postponed until a later CL.
Fixes#52199.
Bug: https://github.com/dart-lang/sdk/issues/52199
Change-Id: Ibab9b92f01e3e4020d7d64f1ff000a9b964a4564
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/299400
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>