Version 2.17.0-182.1.beta
Merge '2.17.0-182.0.dev' into beta
diff --git a/.dart_tool/OWNERS b/.dart_tool/OWNERS
new file mode 100644
index 0000000..d52dde4
--- /dev/null
+++ b/.dart_tool/OWNERS
@@ -0,0 +1,2 @@
+# Generated file
+per-file package_config.json=*
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index e47664f..51bc8f5 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,6 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2022-01-12T18:16:46.198227",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -136,7 +135,7 @@
"name": "boolean_selector",
"rootUri": "../third_party/pkg/boolean_selector",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "browser_launcher",
@@ -172,7 +171,7 @@
"name": "clock",
"rootUri": "../third_party/pkg/clock",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "collection",
@@ -229,6 +228,12 @@
"languageVersion": "2.12"
},
{
+ "name": "dart2wasm",
+ "rootUri": "../pkg/dart2wasm",
+ "packageUri": "lib/",
+ "languageVersion": "2.12"
+ },
+ {
"name": "dart_internal",
"rootUri": "../pkg/dart_internal",
"packageUri": "lib/",
@@ -271,24 +276,12 @@
"languageVersion": "2.15"
},
{
- "name": "devtools_server",
- "rootUri": "../third_party/devtools/devtools_server",
- "packageUri": "lib/",
- "languageVersion": "2.12"
- },
- {
"name": "devtools_shared",
"rootUri": "../third_party/devtools/devtools_shared",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
- "name": "diagnostic",
- "rootUri": "../pkg/diagnostic",
- "packageUri": "lib/",
- "languageVersion": "2.0"
- },
- {
"name": "expect",
"rootUri": "../pkg/expect",
"packageUri": "lib/",
@@ -310,7 +303,7 @@
"name": "file_testing",
"rootUri": "../third_party/pkg/file/packages/file_testing",
"packageUri": "lib/",
- "languageVersion": "2.1"
+ "languageVersion": "2.12"
},
{
"name": "fixnum",
@@ -345,7 +338,7 @@
"name": "glob",
"rootUri": "../third_party/pkg/glob",
"packageUri": "lib/",
- "languageVersion": "2.12"
+ "languageVersion": "2.15"
},
{
"name": "html",
@@ -623,7 +616,7 @@
"name": "source_map_stack_trace",
"rootUri": "../third_party/pkg/source_map_stack_trace",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "source_maps",
@@ -671,7 +664,7 @@
"name": "string_scanner",
"rootUri": "../third_party/pkg/string_scanner",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "sync_http",
@@ -689,7 +682,7 @@
"name": "term_glyph",
"rootUri": "../third_party/pkg/term_glyph",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "test",
@@ -760,7 +753,7 @@
"name": "vector_math",
"rootUri": "../third_party/pkg/vector_math",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.14"
},
{
"name": "vm",
@@ -781,6 +774,12 @@
"languageVersion": "2.12"
},
{
+ "name": "wasm_builder",
+ "rootUri": "../pkg/wasm_builder",
+ "packageUri": "lib/",
+ "languageVersion": "2.12"
+ },
+ {
"name": "watcher",
"rootUri": "../third_party/pkg/watcher",
"packageUri": "lib/",
diff --git a/.github/OWNERS b/.github/OWNERS
new file mode 100644
index 0000000..12997a6
--- /dev/null
+++ b/.github/OWNERS
@@ -0,0 +1,2 @@
+file:/tools/OWNERS_PRODUCT
+file:/tools/OWNERS_INFRA
diff --git a/.packages b/.packages
index e8855d6..646a631 100644
--- a/.packages
+++ b/.packages
@@ -2,10 +2,9 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
-# .package file containing links to all packages in /pkg, and checked out
-# by DEPS into /third_party/pkg and /third_party/pkg_tested.
-# Please update this file if you add a package to DEPS or /pkg
-#
+# This file is generated; do not edit. To re-generate, run:
+# 'dart tools/generate_package_config.dart'.
+
_fe_analyzer_shared:pkg/_fe_analyzer_shared/lib
_js_interop_checks:pkg/_js_interop_checks/lib
analysis_server:pkg/analysis_server/lib
@@ -20,10 +19,12 @@
bazel_worker:third_party/pkg/bazel_worker/lib
benchmark_harness:third_party/pkg/benchmark_harness/lib
boolean_selector:third_party/pkg/boolean_selector/lib
-build_integration:pkg/build_integration/lib
browser_launcher:third_party/pkg/browser_launcher/lib
+build_integration:pkg/build_integration/lib
+characters:third_party/pkg/characters/lib
charcode:third_party/pkg/charcode/lib
cli_util:third_party/pkg/cli_util/lib
+clock:third_party/pkg/clock/lib
collection:third_party/pkg/collection/lib
compiler:pkg/compiler/lib
convert:third_party/pkg/convert/lib
@@ -33,6 +34,7 @@
dart2js_runtime_metrics:pkg/dart2js_runtime_metrics/lib
dart2js_tools:pkg/dart2js_tools/lib
dart2native:pkg/dart2native/lib
+dart2wasm:pkg/dart2wasm/lib
dart_internal:pkg/dart_internal/lib
dart_style:third_party/pkg_tested/dart_style/lib
dartdev:pkg/dartdev/lib
@@ -40,14 +42,15 @@
dds:pkg/dds/lib
dds_service_extensions:pkg/dds_service_extensions/lib
dev_compiler:pkg/dev_compiler/lib
-devtools_server:third_party/devtools/devtools_server/lib
devtools_shared:third_party/devtools/devtools_shared/lib
-diagnostic:pkg/diagnostic/lib
expect:pkg/expect/lib
ffi:third_party/pkg/ffi/lib
+file:third_party/pkg/file/packages/file/lib
+file_testing:third_party/pkg/file/packages/file_testing/lib
fixnum:third_party/pkg/fixnum/lib
-frontend_server:pkg/frontend_server/lib
front_end:pkg/front_end/lib
+frontend_server:pkg/frontend_server/lib
+frontend_server_client:third_party/pkg/webdev/frontend_server_client/lib
glob:third_party/pkg/glob/lib
html:third_party/pkg/html/lib
http:third_party/pkg/http/lib
@@ -73,7 +76,7 @@
nnbd_migration:pkg/nnbd_migration/lib
oauth2:third_party/pkg/oauth2/lib
observatory:runtime/observatory/lib
-observatory_test_package:runtime/observatory/tests/service/observatory_test_package
+observatory_2:runtime/observatory_2/lib
package_config:third_party/pkg_tested/package_config/lib
path:third_party/pkg/path/lib
pedantic:third_party/pkg/pedantic/lib
@@ -83,6 +86,7 @@
protobuf:third_party/pkg/protobuf/protobuf/lib
pub:third_party/pkg/pub/lib
pub_semver:third_party/pkg/pub_semver/lib
+scrape:pkg/scrape/lib
sdk_library_metadata:sdk/lib/_internal/sdk_library_metadata/lib
shelf:third_party/pkg/shelf/lib
shelf_packages_handler:third_party/pkg/shelf_packages_handler/lib
@@ -91,9 +95,9 @@
shelf_web_socket:third_party/pkg/shelf_web_socket/lib
smith:pkg/smith/lib
source_map_stack_trace:third_party/pkg/source_map_stack_trace/lib
-sourcemap_testing:pkg/sourcemap_testing/lib
source_maps:third_party/pkg/source_maps/lib
source_span:third_party/pkg/source_span/lib
+sourcemap_testing:pkg/sourcemap_testing/lib
sse:third_party/pkg/sse/lib
stack_trace:third_party/pkg/stack_trace/lib
status_file:pkg/status_file/lib
@@ -106,7 +110,6 @@
test_api:third_party/pkg/test/pkgs/test_api/lib
test_core:third_party/pkg/test/pkgs/test_core/lib
test_descriptor:third_party/pkg/test_descriptor/lib
-test_package:pkg/vm_service/test/test_package
test_process:third_party/pkg/test_process/lib
test_reflective_loader:third_party/pkg/test_reflective_loader/lib
test_runner:pkg/test_runner/lib
@@ -117,9 +120,11 @@
vm:pkg/vm/lib
vm_service:pkg/vm_service/lib
vm_snapshot_analysis:pkg/vm_snapshot_analysis/lib
+wasm_builder:pkg/wasm_builder/lib
watcher:third_party/pkg/watcher/lib
-webdriver:third_party/pkg/webdriver/lib
-webkit_inspection_protocol:third_party/pkg/webkit_inspection_protocol/lib
web_components:third_party/pkg/web_components/lib
web_socket_channel:third_party/pkg/web_socket_channel/lib
+webdriver:third_party/pkg/webdriver/lib
+webkit_inspection_protocol:third_party/pkg/webkit_inspection_protocol/lib
yaml:third_party/pkg/yaml/lib
+yaml_edit:third_party/pkg/yaml_edit/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ddc529..4a99aaa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,27 @@
- Add `Finalizer` and `WeakReference` which can potentially detect when
objects are "garbage collected".
+- Add `isMimeType` method to `UriData` class, to allow case-insensitive
+ checking of the MIME type.
+- Add `isCharset` and `isEncoding` methods to `UriData` class,
+ to allow case-insensitive and alternative-encoding-name aware checking
+ of the MIME type "charset" parameter.
+- Make `UriData.fromString` and `UriData.fromBytes` recognize and omit
+ a "text/plain" `mimeType` even if it is not all lower-case.
#### `dart:ffi`
- Add `ref=` and `[]=` methods to the `StructPointer` and `UnionPointer`
extensions. They copy a compound instance into a native memory region.
+#### `dart:html`
+
+- Add `scrollIntoViewIfNeeded` to `Element`. Previously, this method was nested
+ within `scrollIntoView` based on the `ScrollAlignment` value. `scrollIntoView`
+ is unchanged for now, but users who intend to use the native
+ `Element.scrollIntoViewIfNeeded` should use the new `scrollIntoViewIfNeeded`
+ definition instead.
+
#### `dart:indexed_db`
- `IdbFactory.supportsDatabaseNames` has been deprecated. It will always return
@@ -19,36 +34,81 @@
#### `dart:io`
-- **Breaking Change** [#45410](https://github.com/dart-lang/sdk/issues/45410):
- `HttpClient` no longer transmits some headers (i.e. `authorization`,
- `www-authenticate`, `cookie`, `cookie2`) when processing redirects to
- a different domain.
+- **Breaking Change** [#47887](https://github.com/dart-lang/sdk/issues/47887):
+ `HttpClient` has a new `connectionFactory` property, which allows socket
+ creation to be customized. Classes that `implement HttpClient` may be broken
+ by this change. Add the following method to your classes to fix them:
+
+ ```dart
+ void set connectionFactory(
+ Future<ConnectionTask<Socket>> Function(
+ Uri url, String? proxyHost, int? proxyPort)?
+ f) =>
+ throw UnsupportedError("connectionFactory not implemented");
+ ```
+
+- **Breaking Change** [#48093](https://github.com/dart-lang/sdk/issues/48093):
+ `HttpClient` has a new `keyLog` property, which allows TLS keys to be logged
+ for debugging purposes. Classes that `implement HttpClient` may be broken by
+ this change. Add the following method to your classes to fix them:
+
+ ```dart
+ void set keyLog(Function(String line)? callback) =>
+ throw UnsupportedError("keyLog not implemented");
+ ```
+
+- Add a optional `keyLog` parameter to `SecureSocket.connect` and
+ `SecureSocket.startConnect`.
+
+- Deprecate `SecureSocket.renegotiate` and `RawSecureSocket.renegotiate`,
+ which were no-ops.
+
+#### `dart:isolate`
+
+- Add `Isolate.run` to run a function in a new isolate.
### Tools
#### Dart command line
-- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dart2js` tool has been
marked deprecated as previously announced.
Its replacement is the `dart compile js` command.
Should you find any issues, or missing features, in the replacement
command, kindly file [an issue](https://github.com/dart-lang/sdk/issues/new).
-- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dartdevc` tool has been marked deprecated as previously
announced and will be deleted in a future Dart stable relase. This tool
was intended for use only by build systems like bazel, `build_web_compilers`
and `flutter_tools`. The functionality remains available for those systems,
but it is no longer exposed as a command-line tool in the SDK.
- Please share any concerns in the
+ Please share any concerns in the
[breaking change tracking issue](https://github.com/dart-lang/sdk/issues/46100).
-- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dartdoc` tool has been removed as
previously announced. Its replacement is the `dart doc` command.
-## 2.16.0
+- The template names used in the `dart create` command have been simplified,
+ and the current template names are now the set shown below. (Note: for
+ backwards compatibility the former template names can still be used.)
+```
+ [console] (default) A command-line application.
+ [package] A package containing shared Dart libraries.
+ [server-shelf] A server app using package:shelf.
+ [web] A web app that uses only core Dart libraries.
+```
+
+## 2.16.1 - 2022-02-09
+
+This is a patch release that fixes an AOT precompiler crash when building some
+Flutter apps (issue [flutter/flutter#97301][]).
+
+[flutter/flutter#97301]: https://github.com/flutter/flutter/issues/97301
+
+## 2.16.0 - 2022-02-03
### Core libraries
@@ -60,13 +120,18 @@
#### `dart:io`
-- **Breaking Change** [#47653](https://github.com/dart-lang/sdk/issues/47653):
-On Windows, `Directory.rename` will no longer delete a directory if
-`newPath` specifies one. Instead, a `FileSystemException` will be thrown.
-
-- **Breaking Change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
-The `Platform.packageRoot` API has been removed. It had been marked deprecated
-in 2018, as it doesn't work with any Dart 2.x release.
+- **Security advisory**
+ [CVE-2022-0451](https://github.com/dart-lang/sdk/security/advisories/GHSA-c8mh-jj22-xg5h),
+ **breaking change** [#45410](https://github.com/dart-lang/sdk/issues/45410):
+ `HttpClient` no longer transmits some headers (i.e. `authorization`,
+ `www-authenticate`, `cookie`, `cookie2`) when processing redirects to a
+ different domain.
+- **Breaking change** [#47653](https://github.com/dart-lang/sdk/issues/47653):
+ On Windows, `Directory.rename` will no longer delete a directory if
+ `newPath` specifies one. Instead, a `FileSystemException` will be thrown.
+- **Breaking change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
+ The `Platform.packageRoot` API has been removed. It had been marked deprecated
+ in 2018, as it doesn't work with any Dart 2.x release.
- Add optional `sourcePort` parameter to `Socket.connect`, `Socket.startConnect`, `RawSocket.connect` and `RawSocket.startConnect`
- **Breaking Change** [#45410](https://github.com/dart-lang/sdk/issues/45410):
@@ -76,7 +141,7 @@
#### `dart:isolate`
-- **Breaking Change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
+- **Breaking change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
The `Isolate.packageRoot` API has been removed. It had been marked deprecated
in 2018, as it doesn't work with any Dart 2.x release.
@@ -84,7 +149,7 @@
#### Dart command line
-- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dartanalyzer` tool has been
marked deprecated as previously announced.
Its replacement is the `dart analyze` command.
@@ -93,7 +158,7 @@
[an issue]: https://github.com/dart-lang/sdk/issues/new
-- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dartdoc` tool has been
marked deprecated as previously announced.
Its replacement is the `dart doc` command.
@@ -118,7 +183,7 @@
Updated the Linter to `1.18.0`, which includes changes that
- extends `camel_case_types` to cover enums.
-- fixes `no_leading_underscores_for_local_identifiers` to not
+- fixes `no_leading_underscores_for_local_identifiers` to not
mis-flag field formal parameters with default values.
- fixes `prefer_function_declarations_over_variables` to not
mis-flag non-final fields.
@@ -153,6 +218,22 @@
## 2.15.0 - 2021-12-08
+- **Security advisory**
+ [CVE-2021-22567](https://github.com/dart-lang/sdk/security/advisories/GHSA-8pcp-6qc9-rqmv):
+ Bidirectional Unicode text can be interpreted and compiled differently than
+ how it appears in editors and code-review tools. Exploiting this an attacker
+ could embed source that is invisible to a code reviewer but that modifies the
+ behavior of a program in unexpected ways. Dart 2.15.0 introduces new analysis
+ warnings that flags the use of these.
+
+- **Security advisory**
+ [CVE-2021-22568](https://github.com/dart-lang/sdk/security/advisories/GHSA-r32f-vhjp-qhj7):
+ A malicious third-party package repository may impersonate a user on pub.dev
+ for up to one hour after the user has published a package to that third-party
+ package repository using `dart pub publish`. As of Dart SDK version 2.15.0
+ requests to third-party package repositories will no longer include an OAuth2
+ `access_token` intended for pub.dev.
+
### Language
The following features are new in the Dart 2.15 [language version][]. To use
@@ -464,7 +545,7 @@
#### `dart:io`
-- **Breaking Change** [#46875](https://github.com/dart-lang/sdk/issues/46875):
+- **Breaking change** [#46875](https://github.com/dart-lang/sdk/issues/46875):
The `SecurityContext` class in `dart:io` has been updated to set the minimum
TLS protocol version to TLS1_2_VERSION (1.2) instead of TLS1_VERSION.
- Add `RawSocket.sendMessage`, `RawSocket.receiveMessage` that allow passing of
@@ -481,14 +562,14 @@
#### `dart:web_sql`
-- **Breaking Change** [#46316](https://github.com/dart-lang/sdk/issues/46316):
+- **Breaking change** [#46316](https://github.com/dart-lang/sdk/issues/46316):
The WebSQL standard was abandoned more than 10
years ago and is not supported by many browsers. This release completely
deletes the `dart:web_sql` library.
#### `dart:html`
-- **Breaking Change** [#46316](https://github.com/dart-lang/sdk/issues/46316):
+- **Breaking change** [#46316](https://github.com/dart-lang/sdk/issues/46316):
Related to the removal of `dart:web_sql` (see above), `window.openDatabase`
has been removed.
@@ -496,12 +577,12 @@
#### Dart command line
-- **Breaking Change** [#46100][]: The standalone `dart2native` tool has been
+- **Breaking change** [#46100][]: The standalone `dart2native` tool has been
removed as previously announced. Its replacements are the
`dart compile exe` and `dart compile aot-snapshot` commands, which offer the
same functionality.
-- **Breaking Change**: The standalone `dartfmt` tool has been removed as
+- **Breaking change**: The standalone `dartfmt` tool has been removed as
previously announced. Its replacement is the `dart format` command.
Note that `dart format` has [a different set of options and
@@ -512,11 +593,11 @@
#### Dart VM
-- **Breaking Change** [#45451](https://github.com/dart-lang/sdk/issues/45451):
+- **Breaking change** [#45451](https://github.com/dart-lang/sdk/issues/45451):
Support for `dart-ext:`-style native extensions has been removed as previously
announced. Use `dart:ffi` to bind to native libraries instead.
-- **Breaking Change** [#46754](https://github.com/dart-lang/sdk/issues/46754):
+- **Breaking change** [#46754](https://github.com/dart-lang/sdk/issues/46754):
Isolates spawned via the `Isolate.spawn()` API are now grouped, operate on the
same managed heap and can therefore share various VM-internal data structures.
@@ -805,7 +886,7 @@
### Dart VM
-- **Breaking Change** [#45071][]: `Dart_NewWeakPersistentHandle`'s and
+- **Breaking change** [#45071][]: `Dart_NewWeakPersistentHandle`'s and
`Dart_NewFinalizableHandle`'s `object` parameter no longer accepts `Pointer`s
and subtypes of `Struct`. Expandos no longer accept `Pointer`s and subtypes of
`Struct`s.
@@ -816,13 +897,13 @@
#### Dart command line
-- **Breaking Change** [#46100][]: The standalone `dart2native` tool has been
+- **Breaking change** [#46100][]: The standalone `dart2native` tool has been
marked deprecated, and now prints a warning message. Its replacements are the
`dart compile exe` and `dart compile aot-snapshot` commands, which offer the
same functionality. The `dart2native` tool will be removed from the Dart SDK
in Dart 2.15.
-- **Breaking Change**: The standalone `dartfmt` tool has been marked deprecated,
+- **Breaking change**: The standalone `dartfmt` tool has been marked deprecated,
and now prints a warning message. Instead, use `dart format`. The `dartfmt`
tool will be removed from the Dart SDK in Dart 2.15.
@@ -946,7 +1027,7 @@
#### Dart2JS
-* **Breaking Change** [#46545][]: Dart2JS emits ES6+ JavaScript by default,
+* **Breaking change** [#46545][]: Dart2JS emits ES6+ JavaScript by default,
thereby no longer supporting legacy browsers. Passing the
`--legacy-javascript` flag will let you opt out of this update, but this
flag will be removed in a future release. Modern browsers will not be
@@ -958,7 +1039,7 @@
#### Dart Dev Compiler (DDC)
-- **Breaking Change** [#44154][]: Subtyping relations of `package:js` classes
+- **Breaking change** [#44154][]: Subtyping relations of `package:js` classes
have been changed to be more correct and consistent with Dart2JS.
Like `anonymous` classes, non-`anonymous` classes will no longer check the
underlying type in DDC. The internal type representation of these objects have
@@ -1127,10 +1208,10 @@
## 2.12.3 - 2021-04-14
-This is a patch release that fixes a vulnerability in `dart:html` related to DOM
-clobbering. See the [vulnerability advisory][cve-2021-22540] for more details.
-Thanks again to **Vincenzo di Cicco** for finding and reporting this
-vulnerability.
+**Security advisory**: This is a patch release that fixes a vulnerability in
+`dart:html` related to DOM clobbering. See the security advisory
+[CVE-2021-22540][cve-2021-22540] for more details. Thanks again to **Vincenzo di
+Cicco** for finding and reporting this vulnerability.
[cve-2021-22540]:
https://github.com/dart-lang/sdk/security/advisories/GHSA-3rfv-4jvg-9522
@@ -1156,7 +1237,7 @@
### Language
-- **Breaking Change** [Null safety][] is now enabled by default in all code that
+- **Breaking change** [Null safety][] is now enabled by default in all code that
has not opted out. With null safety, types in your code are non-nullable by
default. Null can only flow into parts of your program where you want it. With
null safety, your runtime null-dereference bugs turn into edit-time analysis
@@ -1176,7 +1257,7 @@
- The postfix `!` null assertion operator
- The `?..` and `?[]` null-aware operators
-- **Breaking Change** [#44660][]: Fixed an implementation bug where `this` would
+- **Breaking change** [#44660][]: Fixed an implementation bug where `this` would
sometimes undergo type promotion in extensions.
[null safety]: https://dart.dev/null-safety/understanding-null-safety
@@ -1228,12 +1309,12 @@
### Dart VM
-- **Breaking Change** [#42312][]: `Dart_WeakPersistentHandle`s no longer
+- **Breaking change** [#42312][]: `Dart_WeakPersistentHandle`s no longer
auto-delete themselves when the referenced object is garbage collected to
avoid race conditions, but they are still automatically deleted when the
isolate group shuts down.
-- **Breaking Change** [#42312][]: `Dart_WeakPersistentHandleFinalizer` is
+- **Breaking change** [#42312][]: `Dart_WeakPersistentHandleFinalizer` is
renamed to `Dart_HandleFinalizer` and had its `handle` argument removed. All
API functions using that type have been updated.
@@ -1241,7 +1322,7 @@
### Foreign Function Interface (`dart:ffi`)
-- **Breaking Change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
+- **Breaking change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
`Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
`Pointer<T extends Struct>[]` are being deprecated in the current stable
release (2.12), and are planned to be fully removed in the following stable
@@ -1251,7 +1332,7 @@
constant `T` on invocations. For migration notes see the breaking change
request.
-- **Breaking Change** [#44622][]: Subtypes of `Struct` without any native member
+- **Breaking change** [#44622][]: Subtypes of `Struct` without any native member
are being deprecated in the current stable release (2.12), and are planned to
be fully removed in the following stable release (2.13). Migrate opaque types
to extend `Opaque` rather than `Struct`.
@@ -1533,7 +1614,7 @@
### Dart VM
-- **Breaking Change** [#42982][]: `dart_api_dl.cc` is renamed to `dart_api_dl.c`
+- **Breaking change** [#42982][]: `dart_api_dl.cc` is renamed to `dart_api_dl.c`
and changed to a pure C file.
- Introduces `Dart_FinalizableHandle`s. They do auto-delete, and the weakly
referred object cannot be accessed through them.
@@ -1622,7 +1703,7 @@
#### `dart:convert`
-- **Breaking Change** [#41100][]: When encoding a string containing unpaired
+- **Breaking change** [#41100][]: When encoding a string containing unpaired
surrogates as UTF-8, the unpaired surrogates will be encoded as replacement
characters (`U+FFFD`). When decoding UTF-8, encoded surrogates will be treated
as malformed input. When decoding UTF-8 with `allowMalformed: true`, the
@@ -1654,7 +1735,7 @@
#### `dart:html`
-- **Breaking Change**: `CssClassSet.add()` previously returned `null` if the
+- **Breaking change**: `CssClassSet.add()` previously returned `null` if the
`CssClassSet` corresponded to multiple elements. In order to align with the
null-safe changes in the `Set` interface, it will now return `false` instead.
The same applies for `CssClassSet.toggle`.
@@ -1675,7 +1756,7 @@
#### `dart:mirrors`
-- **Breaking Change** [#42714][]: web compilers (dart2js and DDC) now produce a
+- **Breaking change** [#42714][]: web compilers (dart2js and DDC) now produce a
compile-time error if `dart:mirrors` is imported.
Most projects should not be affected. Since 2.0.0 this library was unsupported
@@ -1726,7 +1807,7 @@
### Dart VM
-- **Breaking Change** [#41100][]: When printing a string using the `print`
+- **Breaking change** [#41100][]: When printing a string using the `print`
function, the default implementation (used when not overridden by the embedder
or the current zone) will print any unpaired surrogates in the string as
replacement characters (`U+FFFD`). Similarly, the `Dart_StringToUTF8` function
@@ -1884,12 +1965,12 @@
#### `dart:html`
-- **Breaking Change** [#39627][]: Changed the return type of several HTML native
+- **Breaking change** [#39627][]: Changed the return type of several HTML native
methods involving futures. In return types that matched `Future<List<T>>`,
`T was` changed to `dynamic`. These methods would have resulted in a runtime
error if they were used.
-- **Breaking Change**: `Node.insertAllBefore()` erroneously had a return type of
+- **Breaking change**: `Node.insertAllBefore()` erroneously had a return type of
`Node`, even though it was not returning anything. This has been corrected to
`void`.
@@ -2023,7 +2104,7 @@
### Foreign Function Interface (`dart:ffi`)
-- **Breaking Change**: Changed `Pointer.asFunction()` and
+- **Breaking change**: Changed `Pointer.asFunction()` and
`DynamicLibrary.lookupFunction()` to extension methods. Invoking them
dynamically previously already threw an exception, so the runtime behavior
stays the same. However, the extension methods are only visible if `dart:ffi`
@@ -2042,7 +2123,7 @@
frequently encounter code that is accepted by one compiler but then fails in the
other.
-- **Breaking Change**: Deleted the legacy (analyzer based) version of DDC. For
+- **Breaking change**: Deleted the legacy (analyzer based) version of DDC. For
additional details see the [announcement][ddc].
- The `--kernel` option is now ignored and defaults to true. There is no
@@ -2055,12 +2136,12 @@
deleted from `dart-sdk/lib/dev_compiler` in favor of the versions located at
`dart-sdk/lib/dev_compiler/kernel`.
-- **Breaking Change**: Functions passed to JavaScript using the recommended
+- **Breaking change**: Functions passed to JavaScript using the recommended
`package:js` interop specification must now be wrapped with a call to
`allowInterop`. This behavior was always enforced by Dart2JS, but was not
enforced consistently by DDC. It is now enforced by both.
-- **Breaking Change**: Constructors in `@JS()` classes must be marked with
+- **Breaking change**: Constructors in `@JS()` classes must be marked with
`external`. Previously the `external` could be omitted in some cases with DDC
but doing so would cause incorrect behavior with Dart2JS.
@@ -2131,16 +2212,16 @@
- JS interop classes with an index operator are now static errors instead of
causing invalid code in Dart2JS.
-- **Breaking Change**: The subtyping rule for generic functions is now more
+- **Breaking change**: The subtyping rule for generic functions is now more
forgiving. Corresponding type parameter bounds now only need to be mutual
subtypes rather than structurally equal up to renaming of bound type variables
and equating all top types.
-- **Breaking Change**: Types are now normalized. See [normalization][] for the
+- **Breaking change**: Types are now normalized. See [normalization][] for the
full specification. Types will now be printed in their normal form, and mutual
subtypes with the same normal form will now be considered equal.
-- **Breaking Change**: Constructors in `@JS()` classes must be marked with
+- **Breaking change**: Constructors in `@JS()` classes must be marked with
`external`. Previously, the external could be omitted for unused constructors.
Omitting `external` for a constructor which is used would cause incorrect
behavior at runtime, now omitting it on any constructor is a static error.
@@ -2151,7 +2232,7 @@
Other dart2js changes:
-- **Breaking Change**: The `--package-root` flag, which was hidden and disabled
+- **Breaking change**: The `--package-root` flag, which was hidden and disabled
in Dart 2.0.0, has been completely removed. Passing this flag will now cause
`dart2js` to fail.
@@ -2215,10 +2296,10 @@
## 2.7.2 - 2020-03-23
-This is a patch release that addresses a vulnerability in `dart:html`
-[NodeValidator][] related to DOM clobbering of `previousSibling`. See the
-[vulnerability advisory][cve-2020-8923] for more details. Thanks to **Vincenzo
-di Cicco** for finding and reporting this issue.
+**Security advisory**: This is a patch release that addresses a vulnerability in
+`dart:html` [NodeValidator][] related to DOM clobbering of `previousSibling`.
+See the security advisory [CVE-2020-8923][cve-2020-8923] for more details.
+Thanks to **Vincenzo di Cicco** for finding and reporting this issue.
This release also improves compatibility with ARMv8 processors (issue [40001][])
and dart:io stability (issue [40589][]).
@@ -2235,7 +2316,7 @@
[40217]: https://github.com/dart-lang/sdk/issues/40217
-**Breaking Change**: The Dart SDK for macOS is now only available for x64 (issue
+**Breaking change**: The Dart SDK for macOS is now only available for x64 (issue
[39810][]).
[39810]: https://github.com/dart-lang/sdk/issues/39810
@@ -2250,7 +2331,7 @@
### Language
-- **Breaking Change**: [Static extension members][] are accessible when imported
+- **Breaking change**: [Static extension members][] are accessible when imported
with a prefix (issue [671][]). In the extension method **preview** launch,
importing a library with a prefix hid all extension members in addition to
hiding the extension name, thereby making them inaccessible in the importing
@@ -3231,7 +3312,7 @@
#### `dart:io`
-- **Breaking Change:** Adding to a closed `IOSink` now throws a `StateError`.
+- **Breaking change:** Adding to a closed `IOSink` now throws a `StateError`.
- Added ability to get and set low level socket options.
[29554]: https://github.com/dart-lang/sdk/issues/29554
@@ -3928,8 +4009,8 @@
- **(Breaking)** "dart:isolate" and "dart:mirrors" are no longer supported when
using Dart for the web. They are still supported in the command-line VM.
-- **(Breaking)** Pub's transformer-based build system has been [replaced by a
- new build system][transformers].
+- **(Breaking)** Pub's transformer-based build system has been replaced by a
+ [new build system][build system].
- The `new` keyword is optional and can be omitted. Likewise, `const` can be
omitted inside a const context ([issue 30921][]).
@@ -3938,8 +4019,8 @@
[issue 30345]: https://github.com/dart-lang/sdk/issues/30345
[issue 30921]: https://github.com/dart-lang/sdk/issues/30921
-[strong mode]: https://www.dartlang.org/guides/language/sound-dart
-[transformers]: https://www.dartlang.org/tools/pub/obsolete
+[strong mode]: https://dart.dev/guides/language/type-system
+[build system]: https://github.com/dart-lang/build
### Language
@@ -4866,7 +4947,7 @@
```
To opt back into the warnings, add the following to the
-[.analysis_options](https://www.dartlang.org/guides/language/analysis-options)
+[.analysis_options](https://dart.dev/guides/language/analysis-options)
file for your project.
```
@@ -5301,7 +5382,7 @@
- We have improved the way that the VM locates the native code library for a
native extension (e.g. `dart-ext:` import). We have updated this
- [article on native extensions](https://www.dartlang.org/articles/dart-vm/native-extensions)
+ [article on native extensions](https://dart.dev/server/c-interop-native-extensions)
to reflect the VM's improved behavior.
- Linux builds of the VM will now use the `tcmalloc` library for memory
@@ -6092,7 +6173,7 @@
### Tool changes
- `dart2js` and Dartium now support improved Javascript Interoperability via the
- [js package](https://pub.dartlang.org/packages/js).
+ [js package](https://pub.dev/packages/js).
- `docgen` and `dartdocgen` no longer ship in the SDK. The `docgen` sources have
been removed from the repository.
@@ -6208,7 +6289,7 @@
- Documentation tools
- `dartdoc` is now the default tool to generate static HTML for API docs.
- [Learn more](https://pub.dartlang.org/packages/dartdoc).
+ [Learn more](https://pub.dev/packages/dartdoc).
- `docgen` and `dartdocgen` have been deprecated. Currently plan is to remove
them in 1.13.
@@ -6401,7 +6482,7 @@
### Tool changes
- This is the first release that does not include the Eclipse-based **Dart
- Editor**. See [dartlang.org/tools](https://www.dartlang.org/tools/) for
+ Editor**. See [dart.dev/tools](https://dart.dev/tools#ides-and-editors) for
alternatives.
- This is the last release that ships the (unsupported) dart2dart (aka
`dart2js --output-type=dart`) utility as part of dart2js
@@ -6481,8 +6562,8 @@
- Enum support is fully enabled. See [the language tour][enum] for more details.
-[async]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#asynchrony
-[enum]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#enums
+[async]: https://dart.dev/guides/language/language-tour#asynchrony
+[enum]: https://dart.dev/guides/language/language-tour#enums
### Tool changes
@@ -6496,7 +6577,7 @@
- Analysis supports more and better hints, including unused variables and unused
private members.
-[dartfmt]: https://www.dartlang.org/tools/dartfmt/
+[dartfmt]: https://dart.dev/tools/dart-format
### Core library changes
@@ -6514,7 +6595,7 @@
#### Details
For more information on any of these changes, see the corresponding
-documentation on the [Dart API site](http://api.dartlang.org).
+documentation on the [Dart API site](http://api.dart.dev).
- `dart:async`:
@@ -6666,7 +6747,7 @@
the same page.
[pub global activate]:
- https://www.dartlang.org/tools/pub/cmd/pub-global.html#running-a-script-from-your-path
+ https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path
### Core library changes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6802814..cdfcdaf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,7 +11,7 @@
click that icon to report a bug on the page.
* To report an API doc bug,
[create an SDK issue](https://github.com/dart-lang/sdk/issues/new?title=API%20doc%20issue:).
- * Contribute to the Dart developer websites such as [dart.dev](https://dart.dev) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)) and [dart.dev/web](https://dart.dev/web) (repo: [dart-lang/site-www/src/web](https://github.com/dart-lang/site-www/tree/master/src/web)). For more information, see [Writing for Dart and Flutter websites](https://github.com/dart-lang/site-shared/wiki/Writing-for-Dart-and-Flutter-websites).
+ * Contribute to the Dart developer websites such as [dart.dev](https://dart.dev) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)). For more information, see [Writing for Dart and Flutter websites](https://github.com/dart-lang/site-shared/blob/master/doc/writing-for-dart-and-flutter-websites.md).
* Improve the API reference docs at [api.dart.dev](https://api.dart.dev) by editing doc comments in the [Dart SDK repo](https://github.com/dart-lang/sdk/tree/main/sdk/lib). For more information on how to write API docs, see [Effective Dart: Documentation](https://dart.dev/guides/language/effective-dart/documentation).
## Before you contribute
@@ -20,9 +20,13 @@
Before you start working on a larger contribution, you should get in touch with us first through the [Dart Issue Tracker](https://dartbug.com) with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on.
-All submissions, including submissions by project members, require review. We use the same code-review tools and process as the chromium project. In order to submit a patch, you need to get the [depot\_tools](http://dev.chromium.org/developers/how-tos/depottools).
+All submissions, including submissions by project members, require review. We use the same code-review tools and process as the chromium project.
-We occasionally take pull requests, e.g., for comment changes, but the main flow is to use the Rietveld review system as explained below.
+We occasionally take pull requests, e.g., for comment changes, but the main flow is to use the Gerrit review system as explained below.
+
+## Setting up Environment
+
+In order to submit a patch, you need to get the [depot\_tools](http://dev.chromium.org/developers/how-tos/depottools).
## Getting the code
@@ -69,7 +73,9 @@
git cl upload -s
```
-The above command returns a URL for the review. Attach this review to your issue in https://dartbug.com
+The above command returns a URL for the review. Attach this review to your issue in https://dartbug.com.
+
+To update the cl, just commit your changes and run `git cl upload -s` for your branch.
If you have commit access, when the review is done and the patch is good to go, submit the patch on https://dart-review.googlesource.com:
diff --git a/DEPS b/DEPS
index 56ed123..dc14ff7 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
# hashes. It requires access to the dart-build-access group, which EngProd
# has.
- "co19_rev": "1247f4096b835f31465e8f71dece427e95b51534",
+ "co19_rev": "a38d7c5685e64499cfbdbfe6548fbd5b63b57f15",
# This line prevents conflicts when both packages are rolled simultaneously.
"co19_2_rev": "995745937abffe9fc3a6441f9f0db27b2d706e4c",
@@ -59,15 +59,15 @@
# Checkout extra javascript engines for testing or benchmarking.
# d8, the V8 shell, is always checked out.
"checkout_javascript_engines": False,
- "d8_tag": "version:9.9.3",
+ "d8_tag": "version:10.0.40",
"jsshell_tag": "version:95.0",
# As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
# should be kept up to date with the revisions pulled by the Flutter engine.
# The list of revisions for these tools comes from Fuchsia, here:
- # https://fuchsia.googlesource.com/integration/+/HEAD/prebuilts
+ # https://fuchsia.googlesource.com/integration/+/HEAD/toolchain
# If there are problems with the toolchain, contact fuchsia-toolchain@.
- "clang_revision": "e3a7f0e2f9ab566bd9b71fb54fe77e947b061a12",
+ "clang_revision": "1aa59ff2f789776ebfa2d4b315fd3ea589652b4a",
"gn_revision": "b79031308cc878488202beb99883ec1f2efd9a6d",
# Scripts that make 'git cl format' work.
@@ -80,7 +80,7 @@
"async_rev": "80886150a5e6c58006c8ae5a6c2aa7108638e2a9",
"bazel_worker_rev": "ceeba0982d4ff40d32371c9d35f3d2dc1868de20",
"benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
- "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
+ "boolean_selector_rev": "437e7f06c7e416bed91e16ae1df453555897e945",
"boringssl_gen_rev": "ced85ef0a00bbca77ce5a91261a5f2ae61b1e62f",
"boringssl_rev" : "87f316d7748268eb56f2dc147bd593254ae93198",
"browser-compat-data_tag": "v1.0.22",
@@ -89,11 +89,11 @@
"charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
"chrome_rev" : "19997",
"cli_util_rev" : "b0adbba89442b2ea6fef39c7a82fe79cb31e1168",
- "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
- "collection_rev": "a4c941ab94044d118b2086a3f261c30377604127",
+ "clock_rev" : "5631a0612f4ac7e1b32f7c9a00fc7c00a41615e1",
+ "collection_rev": "e1407da23b9f17400b3a905aafe2b8fa10db3d86",
"convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
"crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
- "csslib_rev": "158bfa94eed08c12c07a8ee0a3fded0ebdcd1fcb",
+ "csslib_rev": "518761b166974537f334dbf264e7f56cb157a96a",
# Note: Updates to dart_style have to be coordinated with the infrastructure
# team so that the internal formatter `tools/sdks/dart-sdk/bin/dart format`
@@ -107,17 +107,17 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_rev": "6f894c0ca33686122be9085f06e5b9bf6ad55262",
+ "dart_style_rev": "d7b73536a8079331c888b7da539b80e6825270ea",
- "dartdoc_rev" : "f9cfab1b84176873c80b89e7c8b54c669344f9ed",
- "devtools_rev" : "f265c3028d5ed9a454762532bed144fa36b2e4d5",
+ "dartdoc_rev" : "a39f378f8100b907e6285ac825967d764fd664ad",
+ "devtools_rev" : "b9f2039239cc72ac8b26f8a5fe46123f34d53ce1",
"ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
"fixnum_rev": "848341f061359ef7ddc0cad472c2ecbb036b28ac",
- "file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
- "glob_rev": "a62acf590598f458d3198d9f2930c1c9dd4b1379",
- "html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
+ "file_rev": "1ebc38852ffed24b564910317982298b56c2cedd",
+ "glob_rev": "da1f4595ee2f87982cbcc663d4cac244822d9227",
+ "html_rev": "f108bce59d136c584969fd24a5006914796cf213",
"http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
- "http_multi_server_rev": "de1b312164c24a1690b46c6e97bd47eff40c4649",
+ "http_multi_server_rev": "34bf7f04b61cce561f47f7f275c2cc811534a05a",
"http_parser_rev": "202391286ddc13c4c3c284ac5b511f04697250ed",
"http_rev": "1e42ffa181b263f7790f276a5465832bff7ce615",
"icu_rev" : "81d656878ec611cb0b42d52c82e9dae93920d9ba",
@@ -126,11 +126,11 @@
"json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
"linter_tag": "1.18.0",
"lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
- "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
+ "logging_rev": "dfbe88b890c3b4f7bc06da5a7b3b43e9e263b688",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"markdown_rev": "7479783f0493f6717e1d7ae31cb37d39a91026b2",
"matcher_rev": "07595a7739d47a8315caba5a8e58fb9ae3d81261",
- "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
+ "mime_rev": "7f4252d469de032aa4df9f90e827dbac4b8efa48",
"mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
"oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
"package_config_rev": "8731bf10b5375542792a32a0f7c8a6f370583d96",
@@ -142,7 +142,7 @@
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
"protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
"pub_rev": "8f5ab7b1aba3b9f66b56246d77e167990339d317",
- "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
+ "pub_semver_rev": "ea6c54019948dc03042c595ce9413e17aaf7aa38",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
"shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
@@ -150,27 +150,27 @@
"shelf_proxy_tag": "v1.0.0",
"shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
"shelf_web_socket_rev": "24fb8a04befa75a94ac63a27047b231d1a22aab4",
- "source_map_stack_trace_rev": "1c3026f69d9771acf2f8c176a1ab750463309cce",
+ "source_map_stack_trace_rev": "80709f2d2fe5086ab50d744a28a2d26ea4384a1b",
"source_maps-0.9.4_rev": "38524",
"source_maps_rev": "6499ee3adac8d469e2953e2e8ba4bdb4c2fbef90",
"source_span_rev": "dc189b455d823e2919667f6c5dcb41ab7483bce0",
"sse_rev": "9084339389eb441d0c0518cddac211a097e78657",
"stack_trace_rev": "5220580872625ddee41e9ca9a5f3364789b2f0f6",
"stream_channel_rev": "3fa3e40c75c210d617b8b943b9b8f580e9866a89",
- "string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
+ "string_scanner_rev": "0e53bf9059e8e22a3b346aac7ec755a0f8314eb6",
"sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
"test_descriptor_rev": "ead23c1e7df079ac0f6457a35f7a71432892e527",
"test_process_rev": "7c73ec8a8a6e0e63d0ec27d70c21ca4323fb5e8f",
- "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
+ "term_glyph_rev": "4885b7f8af6931e23d3aa6d1767ee3f9a626923d",
"test_reflective_loader_rev": "fcfce37666672edac849d2af6dffc0f8df236a94",
"test_rev": "099dcc4d052a30c6921489cfbefa1c8531d12975",
"typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
"usage_rev": "f0cb8f7cce8b675255c81488dbab8cf9f2f56404",
- "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
+ "vector_math_rev": "0cbed0914d49a6a44555e6d5444c438a4a4c3fc1",
"watcher_rev": "f76997ab0c857dc5537ac0975a9ada92b54ef949",
"webdriver_rev": "ff5ccb1522edf4bed578ead4d65e0cbc1f2c4f02",
"web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
- "web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
+ "web_socket_channel_rev": "99dbdc5769e19b9eeaf69449a59079153c6a8b1f",
"WebCore_rev": "bcb10901266c884e7b3740abc597ab95373ab55c",
"webdev_rev": "832b096c0c24798d3df46faa7b7661fe930573c2",
"webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..911f0bb
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,23 @@
+# Global approvers - only to be used as a last resort.
+asiva@google.com #{LAST_RESORT_SUGGESTION}
+athom@google.com #{LAST_RESORT_SUGGESTION}
+kustermann@google.com #{LAST_RESORT_SUGGESTION}
+leafp@google.com #{LAST_RESORT_SUGGESTION}
+sigmund@google.com #{LAST_RESORT_SUGGESTION}
+vegorov@google.com #{LAST_RESORT_SUGGESTION}
+vsm@google.com #{LAST_RESORT_SUGGESTION}
+
+# DEPS
+per-file DEPS=file:/tools/OWNERS_ENG
+
+# Changelog, AUTHORS, and .git* do not require approval.
+per-file CHANGELOG.md,AUTHORS,.gitattributes,.gitconfig,.gitignore=*
+
+# Product documentation
+per-file CONTRIBUTING.md,LICENSE,PATENT_GRANT,README.*,SECURITY.md=file:/tools/OWNERS_PRODUCT
+
+# Top level build files
+per-file .clang-format,BUILD.gn,sdk_args.gni=file:/tools/OWNERS_VM
+
+# Generated file
+per-file .packages=*
diff --git a/SECURITY.md b/SECURITY.md
index a341d38..573f212 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,3 +1,8 @@
## Reporting vulnerabilities
To report potential vulnerabilities, please see our security policy on
[https://dart.dev/security](https://dart.dev/security).
+
+## Published security advisories
+
+For advisories published for the Dart SDK, see
+[security advisories](https://github.com/dart-lang/sdk/security/advisories?state=published).
diff --git a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
index b3d40c0..3451cc3 100644
--- a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
@@ -4,6 +4,8 @@
// ignore_for_file: avoid_function_literals_in_foreach_calls
+import 'dart:math' show Random;
+
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:fixnum/fixnum.dart';
@@ -240,7 +242,9 @@
class DummyBenchmark extends BenchmarkBase {
DummyBenchmark(String name) : super(name);
@override
- double measure() => 2000 * 1000 * 1.0; // A rate of one run per 2s.
+ // A rate of one run per 2s, with a millisecond of noise. Some variation is
+ // needed for Golem's noise-based filtering and regression detection.
+ double measure() => (2000 + Random().nextDouble() - 0.5) * 1000;
}
/// Create [ParseJsBigIntBenchmark], or a dummy benchmark if JavaScript BigInt
diff --git a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
index db19b68..2ff130d 100644
--- a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
@@ -6,6 +6,8 @@
// @dart=2.9
+import 'dart:math' show Random;
+
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:fixnum/fixnum.dart';
@@ -242,7 +244,9 @@
class DummyBenchmark extends BenchmarkBase {
DummyBenchmark(String name) : super(name);
@override
- double measure() => 2000 * 1000 * 1.0; // A rate of one run per 2s.
+ // A rate of one run per 2s, with a millisecond of noise. Some variation is
+ // needed for Golem's noise-based filtering and regression detection.
+ double measure() => (2000 + Random().nextDouble() - 0.5) * 1000;
}
/// Create [ParseJsBigIntBenchmark], or a dummy benchmark if JavaScript BigInt
diff --git a/benchmarks/Iterators/dart/Iterators.dart b/benchmarks/Iterators/dart/Iterators.dart
new file mode 100644
index 0000000..d4ff6c4
--- /dev/null
+++ b/benchmarks/Iterators/dart/Iterators.dart
@@ -0,0 +1,651 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// # Benchmark for iterators of common collections.
+///
+/// The purpose of this benchmark is to detect performance changes in the
+/// iterators for common collections (system Lists, Maps, etc).
+///
+/// ## Polymorphic benchmarks
+///
+/// Benchmark names beginning with `Iterators.poly.`.
+///
+/// These benchmark use the iterators from a common polymorphic for-in loop, so
+/// none of the methods involved in iterating are inlined. This gives an
+/// indication of worst-case performance.
+///
+/// Iterables of different sizes (small (N=1) and large (N=100)) are used to
+/// give insight into the fixed vs per-element costs.
+///
+/// Results are normalized by iterating 1000 elements and reporting the time per
+/// element. There is an outer loop that calls the iterator loop in `sinkAll`.
+///
+/// The dispatched (polymorphic) calls are to `get:iterator`, `moveNext` and
+/// `get:current`.
+///
+/// | N | outer | `get:iterator` | `moveNext` | `get:current` |
+/// | ---: | ----: | -------------: | ---------: | ------------: |
+/// | 0* | 1000 | 1000 | 1000 | 0 |
+/// | 1 | 1000 | 1000 | 2000 | 1000 |
+/// | 2* | 500 | 500 | 1500 | 1000 |
+/// | 100 | 10 | 10 | 1010 | 1000 |
+///
+/// * By default only the N=1 and N=100 benchmarks arer run. The N=0 and N=2
+/// series are available running manually with `--0` and `--2` command-line
+/// arguments.
+///
+/// Generic Iterables have benchmarks for different element types. There are
+/// benchmarks for `int` type arguments, which have a fast type test, and for
+/// `Thing<Iterable<Comparable>>`, which is harder to test quickly. These tests
+/// are distingished by `int` and `Hard` in the name.
+///
+/// ## Monomorphic benchmarks
+///
+/// Benchmark names beginning with `Iterators.mono.`.
+///
+/// A subset of the polymorphic benchmarks are also implemented with a
+/// per-benchmark for-in loop directly iterating a collection of known
+/// representation. This gives the compiler the opportunity to inline the
+/// methods into the loop and represents the best-case performance.
+///
+/// ## Example benchmarks
+///
+/// The name has 4-7 words separated by periods. The first word is always
+/// 'Iterators', and the second is either 'mono' for monomorphic loops, or
+/// 'poly' for benchmarks using a shared polymorphic loop. The last word is a
+/// number which is the size (length) of the Iterable.
+///
+/// ### Iterators.mono.const.Map.int.values.100
+///
+/// A for-in loop over the values iterable of a known constant Map with value
+/// type `int` and 100 entries.
+///
+/// ### Iterators.poly.Runes.1
+///
+/// An interation over the String.runes iterable of a single character String
+/// using the shared polymorphic loop.
+///
+/// ### Iterators.poly.HashMap.Hard.keys.100
+///
+/// An iteration of over the keys iterable of a HashMap with key type
+/// `Thing<Iterable<Comparable>>` and 100 entries.
+///
+/// ### Iterators.*.UpTo.*
+///
+/// The UpTo iterable is a minimal iterable that provides successive
+/// numbers. The `moveNext` and `get:current` methods are small. Comparing
+/// Iterators.poly.UpTo.*.100 to Iterators.poly.*.100 gives an indication of how
+/// much work is done by `moveNext` (and sometimes `get:current`).
+///
+/// ### Iterators.mono.Nothing.*
+///
+/// The Nothing benchmark has no iteration over an iterable and is used to get a
+/// baseline time for running the benchmark loop for monomorphic
+/// benchmarks. This can be a substantial fraction of
+///
+/// Consider the times
+///
+/// Iterators.mono.CodeUnits.1 = 7.0ns
+/// Iterators.mono.Nothing.1 = 3.1ns
+///
+/// Because the trip count (i.e. 1) of the for-in loop is so small, there is a
+/// lot of overhead attributable to the outer loop in `MonoBenchmark.run`. The
+/// 1000/1 = 1000 trips of outer loops takes 3.1us (3.1ns * 1000 trips), so
+/// CodeUnits is spending only 7.0-3.1 = 3.9ns per character in the for-in
+/// loop over the `.codeUnits` of the single-character String.
+///
+/// Iterators.mono.CodeUnits.100 = 1.83ns
+/// Iterators.mono.Nothing.100 = 0.05ns
+///
+/// Now the outer loop runs only 1000/100 = 10 times, for 0.05us. If we subtract
+/// this from 1.83, we get 1.78ns per character for long strings.
+///
+library iterators_benchmark;
+
+// TODO(48277): Update when fixed:
+// ignore_for_file: unnecessary_lambdas
+
+import 'dart:collection';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+
+import 'data.dart';
+
+const targetSize = 1000;
+
+class Emitter implements ScoreEmitter {
+ @override
+ void emit(String testName, double value) {
+ // [value] is microseconds per ten calls to `run()`.
+ final nanoSeconds = value * 1000;
+ final singleElementTimeNs = nanoSeconds / 10 / targetSize;
+ print('$testName(RunTimeRaw): $singleElementTimeNs ns.');
+ }
+}
+
+abstract class Benchmark extends BenchmarkBase {
+ final int size;
+ bool selected = false;
+ Benchmark._(String name, this.size)
+ : super('Iterators.$name.$size', emitter: Emitter());
+
+ factory Benchmark(String name, int size, Iterable Function(int) generate) =
+ PolyBenchmark;
+}
+
+abstract class MonoBenchmark extends Benchmark {
+ final int _repeats;
+ MonoBenchmark(String name, int size)
+ : _repeats = size == 0 ? targetSize : targetSize ~/ size,
+ super._('mono.$name', size);
+
+ @override
+ void run() {
+ for (int i = 0; i < _repeats; i++) {
+ sinkMono();
+ }
+ }
+
+ void sinkMono();
+}
+
+class PolyBenchmark extends Benchmark {
+ final Iterable Function(int) generate;
+ final List<Iterable> inputs = [];
+
+ PolyBenchmark(String name, int size, this.generate)
+ : super._('poly.$name', size);
+
+ @override
+ void setup() {
+ if (inputs.isNotEmpty) return; // Ensure setup() is idempotent.
+
+ int totalSize = 0;
+ while (totalSize < targetSize) {
+ final sample = generate(size);
+ inputs.add(sample);
+ totalSize += size == 0 ? 1 : size;
+ }
+ }
+
+ @override
+ void run() {
+ for (int i = 0; i < inputs.length; i++) {
+ sinkAll(inputs[i]);
+ }
+ }
+}
+
+/// This function is the inner loop of the benchmark.
+@pragma('dart2js:noInline')
+@pragma('vm:never-inline')
+void sinkAll(Iterable iterable) {
+ for (final value in iterable) {
+ sink = value;
+ }
+}
+
+Object? sink;
+
+class BenchmarkConstMapIntKeys1 extends MonoBenchmark {
+ BenchmarkConstMapIntKeys1() : super('const.Map.int.keys', 1);
+
+ static const _map = constMapIntInt1;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.keys) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkConstMapIntKeys2 extends MonoBenchmark {
+ BenchmarkConstMapIntKeys2() : super('const.Map.int.keys', 2);
+
+ static const _map = constMapIntInt2;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.keys) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkConstMapIntKeys100 extends MonoBenchmark {
+ BenchmarkConstMapIntKeys100() : super('const.Map.int.keys', 100);
+
+ static const _map = constMapIntInt100;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.keys) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkConstMapIntValues1 extends MonoBenchmark {
+ BenchmarkConstMapIntValues1() : super('const.Map.int.values', 1);
+
+ static const _map = constMapIntInt1;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.values) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkConstMapIntValues2 extends MonoBenchmark {
+ BenchmarkConstMapIntValues2() : super('const.Map.int.values', 2);
+
+ static const _map = constMapIntInt2;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.values) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkConstMapIntValues100 extends MonoBenchmark {
+ BenchmarkConstMapIntValues100() : super('const.Map.int.values', 100);
+
+ static const _map = constMapIntInt100;
+
+ @override
+ void sinkMono() {
+ for (final value in _map.values) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkMapIntKeys extends MonoBenchmark {
+ BenchmarkMapIntKeys(int size) : super('Map.int.keys', size) {
+ _map.addAll(generateMapIntInt(size));
+ }
+
+ final Map<int, int> _map = {};
+
+ @override
+ void sinkMono() {
+ for (final value in _map.keys) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkUpTo extends MonoBenchmark {
+ BenchmarkUpTo(int size) : super('UpTo', size);
+
+ @override
+ void sinkMono() {
+ for (final value in UpTo(size)) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkNothing extends MonoBenchmark {
+ BenchmarkNothing(int size) : super('Nothing', size);
+
+ @override
+ void sinkMono() {
+ sink = size;
+ }
+}
+
+class BenchmarkCodeUnits extends MonoBenchmark {
+ BenchmarkCodeUnits(int size)
+ : string = generateString(size),
+ super('CodeUnits', size);
+
+ final String string;
+
+ @override
+ void sinkMono() {
+ for (final value in string.codeUnits) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkListIntGrowable extends MonoBenchmark {
+ BenchmarkListIntGrowable(int size)
+ : _list = List.generate(size, (i) => i),
+ super('List.int.growable', size);
+
+ final List<int> _list;
+
+ @override
+ void sinkMono() {
+ for (final value in _list) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkListIntSystem1 extends MonoBenchmark {
+ // The List type here is not quite monomorphic. It is the choice between two
+ // 'system' Lists: a const List and a growable List. It is quite common to
+ // have growable and const lists at the same use-site (e.g. the const coming
+ // from a default argument).
+ //
+ // Ideally some combination of the class heirarchy or compiler tricks would
+ // ensure there is little cost of having this gentle polymorphism.
+ BenchmarkListIntSystem1(int size)
+ : _list1 = List.generate(size, (i) => i),
+ _list2 = generateConstListOfInt(size),
+ super('List.int.growable.and.const', size);
+
+ final List<int> _list1;
+ final List<int> _list2;
+ bool _flip = false;
+
+ @override
+ void sinkMono() {
+ _flip = !_flip;
+ final list = _flip ? _list1 : _list2;
+ for (final value in list) {
+ sink = value;
+ }
+ }
+}
+
+class BenchmarkListIntSystem2 extends MonoBenchmark {
+ // The List type here is not quite monomorphic. It is the choice between two
+ // 'system' Lists: a const List and a fixed-length List. It is quite common to
+ // have fixed-length and const lists at the same use-site (e.g. the const
+ // coming from a default argument).
+ //
+ // Ideally some combination of the class heirarchy or compiler tricks would
+ // ensure there is little cost of having this gentle polymorphism.
+ BenchmarkListIntSystem2(int size)
+ : _list1 = List.generate(size, (i) => i, growable: false),
+ _list2 = generateConstListOfInt(size),
+ super('List.int.fixed.and.const', size);
+
+ final List<int> _list1;
+ final List<int> _list2;
+ bool _flip = false;
+
+ @override
+ void sinkMono() {
+ _flip = !_flip;
+ final list = _flip ? _list1 : _list2;
+ for (final value in list) {
+ sink = value;
+ }
+ }
+}
+
+/// A simple Iterable that yields the integers 0 through `length`.
+///
+/// This Iterable serves as the minimal interesting example to serve as a
+/// baseline, and is useful in constructing other benchmark inputs.
+class UpTo extends IterableBase<int> {
+ final int _length;
+ UpTo(this._length);
+
+ @override
+ Iterator<int> get iterator => UpToIterator(_length);
+}
+
+class UpToIterator implements Iterator<int> {
+ final int _length;
+ int _position = 0;
+ int? _current;
+
+ UpToIterator(this._length);
+
+ @override
+ int get current => _current!;
+
+ @override
+ bool moveNext() {
+ if (_position < _length) {
+ _current = _position++;
+ return true;
+ }
+ _current = null;
+ return false;
+ }
+}
+
+/// A `Thing` has a type parameter which makes type tests in the Iterators
+/// potentially harder, and equality uses the type parameter, making Iterables
+/// that do lookups slower.
+class Thing<T> {
+ static int _nextIndex = 0;
+ final int _index;
+ Thing() : _index = _nextIndex++;
+
+ @override
+ int get hashCode => _index;
+
+ @override
+ bool operator ==(Object other) => other is Thing<T> && other._index == _index;
+}
+
+final thingGenerators = [
+ // TODO(48277): Use instantiated constructor tear-offs when fixed:
+ () => Thing<Set<String>>(),
+ () => Thing<Set<Duration>>(),
+ () => Thing<Set<BigInt>>(),
+ () => Thing<Queue<String>>(),
+ () => Thing<Queue<Duration>>(),
+ () => Thing<Queue<BigInt>>(),
+ () => Thing<List<String>>(),
+ () => Thing<List<Duration>>(),
+ () => Thing<List<BigInt>>(),
+];
+
+int _generateThingListState = 0;
+List<Thing<Iterable<Comparable>>> generateThingList(int n) {
+ Thing nextThing(_) {
+ final next = (_generateThingListState++).remainder(thingGenerators.length);
+ return thingGenerators[next]();
+ }
+
+ return List.from(UpTo(n).map(nextThing));
+}
+
+Map<Thing<Iterable<Comparable>>, Thing<Iterable<Comparable>>> generateThingMap(
+ int n) {
+ return Map.fromIterables(generateThingList(n), generateThingList(n));
+}
+
+Map<Thing<Iterable<Comparable>>, Thing<Iterable<Comparable>>>
+ generateThingHashMap(int n) {
+ return HashMap.fromIterables(generateThingList(n), generateThingList(n));
+}
+
+int _generateStringState = 0;
+String generateString(int n) {
+ return ((_generateStringState++).isEven ? 'x' : '\u2192') * n;
+}
+
+Map<int, int> generateMapIntInt(int n) =>
+ Map<int, int>.fromIterables(UpTo(n), UpTo(n));
+
+Map<int, int> generateIdentityMapIntInt(int n) {
+ return Map<int, int>.identity()..addAll(generateMapIntInt(n));
+}
+
+/// Run the benchmark loop on various inputs to pollute type inference and JIT
+/// caches.
+void pollute() {
+ // This iterable reads `sink` mid-loop, making it infeasible for the compiler
+ // to move the write to `sink` out of the loop.
+ sinkAll(UpTo(100).map((i) {
+ if (i > 0 && sink != i - 1) throw StateError('sink');
+ return i;
+ }));
+
+ // TODO(sra): Do we need to add anything here? There are a lot of benchmarks,
+ // so that is probably sufficient to make the necessary places polymorphic.
+}
+
+/// Command-line arguments:
+///
+/// `--0`: Run benchmarks for empty iterables.
+/// `--1`: Run benchmarks for singleton iterables.
+/// `--2`: Run benchmarks for two-element iterables.
+/// `--100`: Run benchmarks for 100-element iterables.
+///
+/// Default sizes are 1 and 100.
+///
+/// `--all`: Run all benchmark variants and sizes.
+///
+/// `foo`, `foo.bar`: a Selector.
+///
+/// Run benchmarks with name containing all the dot-separated words in the
+/// selector, so `--Set.const` will run benchmark
+/// 'Iterators.const.Set.int.N`, and `--2.UpTo` will select
+/// `Iterators.UpTo.2`. Each selector is matched independently, and if
+/// selectors are used, only benchmarks matching some selector are run.
+///
+void main(List<String> commandLineArguments) {
+ final arguments = [...commandLineArguments];
+
+ const allSizes = {0, 1, 2, 100};
+ const defaultSizes = {1, 100};
+ final allSizeWords = Set.unmodifiable(allSizes.map((size) => '$size'));
+
+ final Set<int> sizes = {};
+ final Set<String> selectors = {};
+
+ if (arguments.remove('--0')) sizes.add(0);
+ if (arguments.remove('--1')) sizes.add(1);
+ if (arguments.remove('--2')) sizes.add(2);
+ if (arguments.remove('--100')) sizes.add(100);
+
+ if (arguments.remove('--all')) {
+ sizes.addAll(allSizes);
+ }
+
+ selectors.addAll(arguments);
+
+ if (sizes.isEmpty) sizes.addAll(defaultSizes);
+ if (selectors.isEmpty) selectors.add('Iterators');
+
+ List<Benchmark> makeBenchmarksForSize(int size) {
+ return [
+ // Simple
+ BenchmarkNothing(size),
+ BenchmarkUpTo(size),
+ BenchmarkCodeUnits(size),
+ Benchmark('UpTo', size, (n) => UpTo(n)),
+ Benchmark('CodeUnits', size, (n) => generateString(n).codeUnits),
+ Benchmark('Runes', size, (n) => generateString(n).runes),
+ // ---
+ BenchmarkListIntGrowable(size),
+ BenchmarkListIntSystem1(size),
+ BenchmarkListIntSystem2(size),
+ Benchmark('List.int.growable', size,
+ (n) => List<int>.of(UpTo(n), growable: true)),
+ Benchmark('List.int.fixed', size,
+ (n) => List<int>.of(UpTo(n), growable: false)),
+ Benchmark('List.int.unmodifiable', size,
+ (n) => List<int>.unmodifiable(UpTo(n))),
+ // ---
+ Benchmark('List.Hard.growable', size, generateThingList),
+ // ---
+ Benchmark('Set.int', size, (n) => Set<int>.of(UpTo(n))),
+ Benchmark('const.Set.int', size, generateConstSetOfInt),
+ // ---
+ BenchmarkMapIntKeys(size),
+ Benchmark('Map.int.keys', size, (n) => generateMapIntInt(n).keys),
+ Benchmark('Map.int.values', size, (n) => generateMapIntInt(n).values),
+ Benchmark('Map.int.entries', size, (n) => generateMapIntInt(n).entries),
+ // ---
+ Benchmark('Map.identity.int.keys', size,
+ (n) => generateIdentityMapIntInt(n).keys),
+ Benchmark('Map.identity.int.values', size,
+ (n) => generateIdentityMapIntInt(n).values),
+ Benchmark('Map.identity.int.entries', size,
+ (n) => generateIdentityMapIntInt(n).entries),
+ // ---
+ Benchmark(
+ 'const.Map.int.keys', size, (n) => generateConstMapIntInt(n).keys),
+ Benchmark('const.Map.int.values', size,
+ (n) => generateConstMapIntInt(n).values),
+ Benchmark('const.Map.int.entries', size,
+ (n) => generateConstMapIntInt(n).entries),
+ // ---
+ Benchmark('Map.Hard.keys', size, (n) => generateThingMap(n).keys),
+ Benchmark('Map.Hard.values', size, (n) => generateThingMap(n).values),
+ // ---
+ Benchmark('HashMap.int.keys', size,
+ (n) => HashMap<int, int>.fromIterables(UpTo(n), UpTo(n)).keys),
+ Benchmark('HashMap.int.values', size,
+ (n) => HashMap<int, int>.fromIterables(UpTo(n), UpTo(n)).values),
+ Benchmark('HashMap.int.entries', size,
+ (n) => HashMap<int, int>.fromIterables(UpTo(n), UpTo(n)).entries),
+ // ---
+ Benchmark('HashMap.Hard.keys', size, (n) => generateThingHashMap(n).keys),
+ Benchmark(
+ 'HashMap.Hard.values', size, (n) => generateThingHashMap(n).values),
+ ];
+ }
+
+ final benchmarks = [
+ BenchmarkConstMapIntKeys1(),
+ BenchmarkConstMapIntKeys2(),
+ BenchmarkConstMapIntKeys100(),
+ BenchmarkConstMapIntValues1(),
+ BenchmarkConstMapIntValues2(),
+ BenchmarkConstMapIntValues100(),
+ for (final size in allSizes) ...makeBenchmarksForSize(size),
+ ];
+
+ // Select benchmarks
+ final unusedSelectors = {...selectors};
+ for (final benchmark in benchmarks) {
+ final nameWords = benchmark.name.split('.').toSet();
+ for (final selector in selectors) {
+ final selectorWords = selector.split('.').toSet();
+ if (nameWords.containsAll(selectorWords)) {
+ unusedSelectors.remove(selector);
+ if (selectorWords.any(allSizeWords.contains) ||
+ sizes.contains(benchmark.size)) {
+ benchmark.selected = true;
+ }
+ // continue matching to remove other matching selectors.
+ }
+ }
+ }
+ if (unusedSelectors.isNotEmpty) {
+ throw ArgumentError(unusedSelectors, 'selectors match no benchmark');
+ }
+
+ // Warmup all benchmarks to ensure JIT compilers see full polymorphism.
+ for (var benchmark in benchmarks) {
+ pollute();
+ benchmark.setup();
+ }
+
+ // Warm up all the benchmarks, including the non-selected ones.
+ for (int i = 0; i < 10; i++) {
+ for (var benchmark in benchmarks) {
+ pollute();
+ final marker = Object();
+ sink = marker;
+ benchmark.warmup();
+ if (benchmark.size > 0 && identical(sink, marker)) throw 'unexpected';
+ }
+ }
+
+ for (var benchmark in benchmarks) {
+ // `report` calls `setup`, but `setup` is idempotent.
+ if (benchmark.selected) {
+ benchmark.report();
+ }
+ }
+}
diff --git a/benchmarks/Iterators/dart/data.dart b/benchmarks/Iterators/dart/data.dart
new file mode 100644
index 0000000..f59c26f
--- /dev/null
+++ b/benchmarks/Iterators/dart/data.dart
@@ -0,0 +1,177 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+Map<int, int> generateConstMapIntInt(int n) {
+ return constMapIntIntTable[n] ??
+ (throw ArgumentError.value(n, 'n', 'size not supported'));
+}
+
+Set<int> generateConstSetOfInt(int n) {
+ return constSetOfIntTable[n] ??
+ (throw ArgumentError.value(n, 'n', 'size not supported'));
+}
+
+List<int> generateConstListOfInt(int n) {
+ return constListOfIntTable[n] ??
+ (throw ArgumentError.value(n, 'n', 'size not supported'));
+}
+
+const Map<int, Map<int, int>> constMapIntIntTable = {
+ 0: constMapIntInt0,
+ 1: constMapIntInt1,
+ 2: constMapIntInt2,
+ 100: constMapIntInt100
+};
+
+const Map<int, int> constMapIntInt0 = {};
+const Map<int, int> constMapIntInt1 = {0: 0};
+const Map<int, int> constMapIntInt2 = {0: 0, 1: 1};
+const Map<int, int> constMapIntInt100 = {
+ 0: 0,
+ 1: 1,
+ 2: 2,
+ 3: 3,
+ 4: 4,
+ 5: 5,
+ 6: 6,
+ 7: 7,
+ 8: 8,
+ 9: 9,
+ 10: 10,
+ 11: 11,
+ 12: 12,
+ 13: 13,
+ 14: 14,
+ 15: 15,
+ 16: 16,
+ 17: 17,
+ 18: 18,
+ 19: 19,
+ 20: 20,
+ 21: 21,
+ 22: 22,
+ 23: 23,
+ 24: 24,
+ 25: 25,
+ 26: 26,
+ 27: 27,
+ 28: 28,
+ 29: 29,
+ 30: 30,
+ 31: 31,
+ 32: 32,
+ 33: 33,
+ 34: 34,
+ 35: 35,
+ 36: 36,
+ 37: 37,
+ 38: 38,
+ 39: 39,
+ 40: 40,
+ 41: 41,
+ 42: 42,
+ 43: 43,
+ 44: 44,
+ 45: 45,
+ 46: 46,
+ 47: 47,
+ 48: 48,
+ 49: 49,
+ 50: 50,
+ 51: 51,
+ 52: 52,
+ 53: 53,
+ 54: 54,
+ 55: 55,
+ 56: 56,
+ 57: 57,
+ 58: 58,
+ 59: 59,
+ 60: 60,
+ 61: 61,
+ 62: 62,
+ 63: 63,
+ 64: 64,
+ 65: 65,
+ 66: 66,
+ 67: 67,
+ 68: 68,
+ 69: 69,
+ 70: 70,
+ 71: 71,
+ 72: 72,
+ 73: 73,
+ 74: 74,
+ 75: 75,
+ 76: 76,
+ 77: 77,
+ 78: 78,
+ 79: 79,
+ 80: 80,
+ 81: 81,
+ 82: 82,
+ 83: 83,
+ 84: 84,
+ 85: 85,
+ 86: 86,
+ 87: 87,
+ 88: 88,
+ 89: 89,
+ 90: 90,
+ 91: 91,
+ 92: 92,
+ 93: 93,
+ 94: 94,
+ 95: 95,
+ 96: 96,
+ 97: 97,
+ 98: 98,
+ 99: 99
+};
+
+const Map<int, Set<int>> constSetOfIntTable = {
+ 0: constSetOfInt0,
+ 1: constSetOfInt1,
+ 2: constSetOfInt2,
+ 100: constSetOfInt100
+};
+
+const Set<int> constSetOfInt0 = {};
+const Set<int> constSetOfInt1 = {0};
+const Set<int> constSetOfInt2 = {0, 1};
+const Set<int> constSetOfInt100 = {
+ ...{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+ ...{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
+ ...{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
+ ...{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
+ ...{40, 41, 42, 43, 44, 45, 46, 47, 48, 49},
+ ...{50, 51, 52, 53, 54, 55, 56, 57, 58, 59},
+ ...{60, 61, 62, 63, 64, 65, 66, 67, 68, 69},
+ ...{70, 71, 72, 73, 74, 75, 76, 77, 78, 79},
+ ...{80, 81, 82, 83, 84, 85, 86, 87, 88, 89},
+ ...{90, 91, 92, 93, 94, 95, 96, 97, 98, 99}
+};
+
+const Map<int, List<int>> constListOfIntTable = {
+ 0: constListOfInt0,
+ 1: constListOfInt1,
+ 2: constListOfInt2,
+ 100: constListOfInt100
+};
+
+const List<int> constListOfInt0 = [];
+const List<int> constListOfInt1 = [0];
+const List<int> constListOfInt2 = [0, 1];
+const List<int> constListOfInt100 = [
+ ...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ ...[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
+ ...[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
+ ...[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
+ ...[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
+ ...[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
+ ...[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
+ ...[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
+ ...[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
+ ...[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
+];
diff --git a/benchmarks/Iterators/dart2/Iterators.dart b/benchmarks/Iterators/dart2/Iterators.dart
new file mode 100644
index 0000000..cc03515
--- /dev/null
+++ b/benchmarks/Iterators/dart2/Iterators.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.9
+
+import '../dart/Iterators.dart' as benchmark;
+
+void main(List<String> arguments) {
+ benchmark.main(arguments);
+}
diff --git a/benchmarks/OWNERS b/benchmarks/OWNERS
new file mode 100644
index 0000000..2b67506
--- /dev/null
+++ b/benchmarks/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_ENG
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index 733b711..13583e9 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -19,7 +19,6 @@
const snapshots = <String>[
'analysis_server',
'dart2js',
- 'dart2native',
'dartanalyzer',
'dartdev',
'dartdevc',
@@ -28,7 +27,6 @@
'gen_kernel',
'kernel-service',
'kernel_worker',
- 'pub',
];
void reportFileSize(String path, String name) {
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index f207e3a..ade286d 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -21,17 +21,14 @@
const snapshots = <String>[
'analysis_server',
'dart2js',
- 'dart2native',
'dartanalyzer',
'dartdev',
'dartdevc',
- 'dartdoc',
'dds',
'frontend_server',
'gen_kernel',
'kernel-service',
'kernel_worker',
- 'pub',
];
void reportFileSize(String path, String name) {
diff --git a/build/OWNERS b/build/OWNERS
new file mode 100644
index 0000000..2b67506
--- /dev/null
+++ b/build/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_ENG
diff --git a/build/config/OWNERS b/build/config/OWNERS
deleted file mode 100644
index bd53091..0000000
--- a/build/config/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-brettw@chromium.org
-dpranke@chromium.org
-scottmg@chromium.org
-
-per-file BUILDCONFIG.gn=brettw@chromium.org
-per-file BUILDCONFIG.gn=set noparent
diff --git a/build/mac/OWNERS b/build/mac/OWNERS
deleted file mode 100644
index c56e89d..0000000
--- a/build/mac/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-mark@chromium.org
-thomasvl@chromium.org
diff --git a/build/sanitizers/OWNERS b/build/sanitizers/OWNERS
deleted file mode 100644
index 0be2be8..0000000
--- a/build/sanitizers/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-glider@chromium.org
-earthdok@chromium.org
-per-file tsan_suppressions.cc=*
-per-file lsan_suppressions.cc=*
diff --git a/build/toolchain/OWNERS b/build/toolchain/OWNERS
deleted file mode 100644
index c6cda3f..0000000
--- a/build/toolchain/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-brettw@chromium.org
-dpranke@chromium.org
-scottmg@chromium.org
diff --git a/docs/OWNERS b/docs/OWNERS
new file mode 100644
index 0000000..22a2e82
--- /dev/null
+++ b/docs/OWNERS
@@ -0,0 +1,2 @@
+file:/tools/OWNERS_FOUNDATION
+file:/tools/OWNERS_PRODUCT
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index 4ea8bda..65d85f7 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -29,7 +29,7 @@
* Must contain no static analysis **errors**.
-* Must not rely on a certain runtime **error** being thrown (in other words,
+* Must not rely on a certain runtime **error** being thrown (in other words,
a new SDK might throw fewer errors than an old SDK).
* Must access libraries via the public API (for example, must not reach into
@@ -45,6 +45,13 @@
Compatibility is only considered between stable releases (i.e. releases from the
[Dart stable channel](https://dart.dev/tools/sdk/archive#stable-channel)).
+## Breaking change implementation timing
+
+To avoid shipping features that have not been thoroughly vetted, we implement a
+policy of not including breaking changes in the final beta before a release.
+Breaking changes must be included in the beta before the final beta to be
+considered for the next stable release.
+
## Breaking change notification
Anyone wishing to make a breaking change to Dart is expected to perform the
@@ -76,7 +83,7 @@
* A request that developers may leave comments in the linked issue, if this
breaking change poses a severe problem.
-Once you have sent the announce email, please let devoncarew@ know in order
+Once you have sent the announce email, please let kevinjchisholm@ know in order
to start the review and approval process.
### Step 2: Approval
diff --git a/pkg/OWNERS b/pkg/OWNERS
new file mode 100644
index 0000000..c3abcf9
--- /dev/null
+++ b/pkg/OWNERS
@@ -0,0 +1,2 @@
+file:/tools/OWNERS_FOUNDATION #{LAST_RESORT_SUGGESTION}
+file:/tools/OWNERS_INFRA #{LAST_RESORT_SUGGESTION}
diff --git a/pkg/_fe_analyzer_shared/OWNERS b/pkg/_fe_analyzer_shared/OWNERS
new file mode 100644
index 0000000..6fd2278
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/OWNERS
@@ -0,0 +1,2 @@
+file:/tools/OWNERS_ANALYZER
+file:/tools/OWNERS_CFE
diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
index 24c5c54..310a360 100644
--- a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
+++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
@@ -19,3 +19,4 @@
- test/inference/inferred_type_arguments/data/**
- test/inference/inferred_variable_types/data/**
- test/inheritance/data/**
+ - test/macros/api/**
diff --git a/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart b/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart
new file mode 100644
index 0000000..01cc969
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart
@@ -0,0 +1,311 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+
+void main() async {
+ for (var serializationMode in [
+ SerializationMode.jsonClient,
+ SerializationMode.byteDataClient
+ ]) {
+ await withSerializationMode(serializationMode, () async {
+ await _isolateSpawnBenchmarks();
+ await _isolateSpawnUriBenchmarks();
+ await _separateProcessBenchmarks();
+ });
+ }
+}
+
+Future<void> _isolateSpawnBenchmarks() async {
+ void Function(SendPort) childIsolateFn(SerializationMode mode) =>
+ (SendPort sendPort) => withSerializationMode(mode, () {
+ var isolateReceivePort = ReceivePort();
+ isolateReceivePort.listen((data) {
+ deserialize(data);
+ var result = serialize();
+ result = result is Uint8List
+ ? TransferableTypedData.fromList([result])
+ : result;
+ sendPort.send(result);
+ });
+ sendPort.send(isolateReceivePort.sendPort);
+ });
+
+ Completer? responseCompleter;
+ late SendPort sendPort;
+
+ var receivePort = ReceivePort();
+
+ var isolate = await Isolate.spawn(
+ childIsolateFn(serializationMode), receivePort.sendPort);
+
+ final sendPortCompleter = Completer<SendPort>();
+ receivePort.listen((data) {
+ if (!sendPortCompleter.isCompleted) {
+ sendPortCompleter.complete(data);
+ } else {
+ responseCompleter!.complete(data);
+ }
+ });
+ sendPort = await sendPortCompleter.future;
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ print('Isolate.spawn + $serializationMode: ${watch.elapsed}');
+
+ receivePort.close();
+ isolate.kill();
+}
+
+Future<void> _isolateSpawnUriBenchmarks() async {
+ Completer? responseCompleter;
+ late SendPort sendPort;
+
+ var receivePort = ReceivePort();
+
+ var isolate = await Isolate.spawnUri(
+ Uri.dataFromString(childProgram(serializationMode)),
+ [],
+ receivePort.sendPort);
+
+ final sendPortCompleter = Completer<SendPort>();
+ receivePort.listen((data) {
+ if (!sendPortCompleter.isCompleted) {
+ sendPortCompleter.complete(data);
+ } else {
+ responseCompleter!.complete(data);
+ }
+ });
+ sendPort = await sendPortCompleter.future;
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ print('Isolate.spawnUri + $serializationMode: ${watch.elapsed}');
+
+ receivePort.close();
+ isolate.kill();
+}
+
+Future<void> _separateProcessBenchmarks() async {
+ Completer? responseCompleter;
+
+ var tmpDir = Directory.systemTemp.createTempSync('serialize_bench');
+ try {
+ var file = File(tmpDir.uri.resolve('main.dart').toFilePath());
+ file.writeAsStringSync(childProgram(serializationMode));
+ var process = await Process.start(Platform.resolvedExecutable, [
+ '--packages=' + (await Isolate.packageConfig)!.toFilePath(),
+ file.path,
+ ]);
+
+ var listeners = <StreamSubscription>[
+ process.stderr.listen((event) {
+ print('stderr: ${utf8.decode(event)}');
+ }),
+ process.stdout.listen((data) {
+ responseCompleter!.complete(data);
+ }),
+ ];
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ if (result is List<int>) {
+ process.stdin.add(result);
+ } else {
+ process.stdin.writeln(jsonEncode(result));
+ }
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ if (result is List<int>) {
+ process.stdin.add(result);
+ } else {
+ process.stdin.writeln(jsonEncode(result));
+ }
+ deserialize(await responseCompleter.future);
+ }
+ print('Separate process + $serializationMode: ${watch.elapsed}');
+
+ listeners.forEach((l) => l.cancel());
+ process.kill();
+ } catch (e, s) {
+ print('Error running benchmark \n$e\n\n$s');
+ } finally {
+ tmpDir.deleteSync(recursive: true);
+ }
+}
+
+String childProgram(SerializationMode mode) => '''
+ import 'dart:convert';
+ import 'dart:io';
+ import 'dart:isolate';
+ import 'dart:typed_data';
+
+ import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+
+ void main(_, [SendPort? sendPort]) {
+ var mode = $mode;
+ withSerializationMode(mode, () {
+ if (sendPort != null) {
+ var isolateReceivePort = ReceivePort();
+ isolateReceivePort.listen((data) {
+ deserialize(data);
+ var result = serialize();
+ result = result is Uint8List
+ ? TransferableTypedData.fromList([result])
+ : result;
+ sendPort.send(result);
+ });
+ sendPort.send(isolateReceivePort.sendPort);
+ } else {
+ // We allow one empty line to work around some weird data.
+ var allowEmpty = true;
+ stdin.listen((data) {
+ if (mode == SerializationMode.jsonClient || mode == SerializationMode.jsonServer) {
+ var json = utf8.decode(data).trimRight();
+ // On exit we tend to get extra empty lines sometimes?
+ if (json.isEmpty && allowEmpty) {
+ allowEmpty = false;
+ return;
+ }
+ deserialize(jsonDecode(json));
+ stdout.write(jsonEncode(serialize()));
+ } else {
+ deserialize(data);
+ stdout.add(serialize() as List<int>);
+ }
+ });
+ }
+ });
+ }
+
+ Object? serialize() {
+ var serializer = serializerFactory();
+ for (var i = 0; i < 100; i++) {
+ serializer.addInt(i * 100);
+ serializer.addString('foo' * i);
+ serializer.addBool(i % 2 == 0);
+ serializer.startList();
+ for (var j = 0; j < 10; j++) {
+ serializer.addDouble(i * 5);
+ }
+ serializer.endList();
+ serializer.addNull();
+ }
+ return serializer.result;
+ }
+
+ void deserialize(Object? result) {
+ result = result is TransferableTypedData
+ ? result.materialize().asUint8List()
+ : result;
+ var deserializer = deserializerFactory(result);
+ while (deserializer.moveNext()) {
+ deserializer
+ ..expectInt()
+ ..moveNext()
+ ..expectString()
+ ..moveNext()
+ ..expectBool()
+ ..moveNext()
+ ..expectList();
+ while (deserializer.moveNext()) {
+ deserializer.expectDouble();
+ }
+ deserializer
+ ..moveNext()
+ ..checkNull();
+ }
+ }''';
+
+Object? serialize() {
+ var serializer = serializerFactory();
+ for (var i = -50; i < 50; i++) {
+ serializer.addInt(i % 2 * 100);
+ serializer.addString('foo' * i);
+ serializer.addBool(i < 0);
+ serializer.startList();
+ for (var j = 0.0; j < 10; j++) {
+ serializer.addDouble(i * j);
+ }
+ serializer.endList();
+ serializer.addNull();
+ }
+ return serializer.result;
+}
+
+void deserialize(Object? result) {
+ result = result is TransferableTypedData
+ ? result.materialize().asUint8List()
+ : result;
+ if (serializationMode == SerializationMode.jsonClient ||
+ serializationMode == SerializationMode.jsonServer) {
+ if (result is List<int>) {
+ result = jsonDecode(utf8.decode(result));
+ }
+ }
+ var deserializer = deserializerFactory(result);
+ while (deserializer.moveNext()) {
+ deserializer
+ ..expectInt()
+ ..moveNext()
+ ..expectString()
+ ..moveNext()
+ ..expectBool()
+ ..moveNext()
+ ..expectList();
+ while (deserializer.moveNext()) {
+ deserializer.expectDouble();
+ }
+ deserializer
+ ..moveNext()
+ ..checkNull();
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
index f10269c..03669ef 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -8,11 +8,28 @@
/// as augment existing ones.
abstract class Builder {}
+/// Allows you to resolve arbitrary [Identifier]s.
+///
+/// This class will likely disappear entirely once we have a different
+/// mechanism.
+abstract class IdentifierResolver {
+ /// Returns an [Identifier] for a top level [name] in [library].
+ ///
+ /// You should only do this for libraries that are definitely in the
+ /// transitive import graph of the library you are generating code into.
+ @Deprecated(
+ 'This api should eventually be replaced with a different, safer API.')
+ Future<Identifier> resolveIdentifier(Uri library, String name);
+}
+
/// The api used by [Macro]s to contribute new type declarations to the
/// current library, and get [TypeAnnotation]s from runtime [Type] objects.
-abstract class TypeBuilder implements Builder {
+abstract class TypeBuilder implements Builder, IdentifierResolver {
/// Adds a new type declaration to the surrounding library.
- void declareType(DeclarationCode typeDeclaration);
+ ///
+ /// The [name] must match the name of the new [typeDeclaration] (this does
+ /// not include any type parameters, just the name).
+ void declareType(String name, DeclarationCode typeDeclaration);
}
/// The interface used to create [StaticType] instances, which are used to
@@ -21,21 +38,14 @@
/// This api is only available to the declaration and definition phases of
/// macro expansion.
abstract class TypeResolver {
- /// Resolves [typeAnnotation] to a [StaticType].
+ /// Instantiates a new [StaticType] for a given [type] annotation.
///
- /// Throws an error if the type annotation cannot be resolved. This should
- /// only happen in the case of incomplete or invalid programs, but macros
- /// may be asked to run in this state during the development cycle. It is
- /// helpful for users if macros provide a best effort implementation in that
- /// case or handle the error in a useful way.
- Future<StaticType> instantiateType(covariant TypeAnnotation typeAnnotation);
-
- /// Instantiates a new [StaticType] for a given [code] expression, which must
- /// be a type expression.
- ///
- /// All type identifiers in [code] must be instances of [Identifier] and not
- /// bare strings.
- Future<StaticType> instantiateCode(ExpressionCode code);
+ /// Throws an error if the [type] object contains [Identifier]s which cannot
+ /// be resolved. This should only happen in the case of incomplete or invalid
+ /// programs, but macros may be asked to run in this state during the
+ /// development cycle. It may be helpful for users if macros provide a best
+ /// effort implementation in that case or handle the error in a useful way.
+ Future<StaticType> resolve(TypeAnnotationCode type);
}
/// The api used to introspect on a [ClassDeclaration].
@@ -79,7 +89,7 @@
///
/// Can also be used to do subtype checks on types.
abstract class DeclarationBuilder
- implements Builder, TypeResolver, ClassIntrospector {
+ implements Builder, IdentifierResolver, TypeResolver, ClassIntrospector {
/// Adds a new regular declaration to the surrounding library.
///
/// Note that type declarations are not supported.
@@ -110,6 +120,7 @@
abstract class DefinitionBuilder
implements
Builder,
+ IdentifierResolver,
TypeResolver,
ClassIntrospector,
TypeDeclarationResolver {}
@@ -117,19 +128,19 @@
/// The apis used by [Macro]s that run on classes, to fill in the definitions
/// of any external declarations within that class.
abstract class ClassDefinitionBuilder implements DefinitionBuilder {
- /// Retrieve a [VariableDefinitionBuilder] for a field by [identifier].
+ /// Retrieve a [VariableDefinitionBuilder] for a field with [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a field in
/// this class.
Future<VariableDefinitionBuilder> buildField(Identifier identifier);
- /// Retrieve a [FunctionDefinitionBuilder] for a method by [identifier].
+ /// Retrieve a [FunctionDefinitionBuilder] for a method with [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a method in
/// this class.
Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier);
- /// Retrieve a [ConstructorDefinitionBuilder] for a constructor by
+ /// Retrieve a [ConstructorDefinitionBuilder] for a constructor with
/// [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a constructor
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
index e7af1bd..6563aef 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
@@ -32,18 +32,6 @@
DeclarationCode.fromParts(List<Object> parts) : super.fromParts(parts);
}
-/// A piece of code representing a syntactically valid element.
-///
-/// Should not include any trailing commas,
-class ElementCode extends Code {
- @override
- CodeKind get kind => CodeKind.element;
-
- ElementCode.fromString(String code) : super.fromString(code);
-
- ElementCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
/// A piece of code representing a syntactically valid expression.
class ExpressionCode extends Code {
@override
@@ -69,67 +57,200 @@
FunctionBodyCode.fromParts(List<Object> parts) : super.fromParts(parts);
}
-/// A piece of code identifying a named argument.
-///
-/// This should not include any trailing commas.
-class NamedArgumentCode extends Code {
- @override
- CodeKind get kind => CodeKind.namedArgument;
-
- NamedArgumentCode.fromString(String code) : super.fromString(code);
-
- NamedArgumentCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
/// A piece of code identifying a syntactically valid function parameter.
///
-/// This should not include any trailing commas, but may include modifiers
-/// such as `required`, and default values.
+/// There is no distinction here made between named and positional parameters.
///
-/// There is no distinction here made between named and positional parameters,
-/// nor between optional or required parameters. It is the job of the user to
-/// construct and combine these together in a way that creates valid parameter
-/// lists.
-class ParameterCode extends Code {
+/// It is the job of the user to construct and combine these together in a way
+/// that creates valid parameter lists.
+class ParameterCode implements Code {
+ final Code? defaultValue;
+ final List<String> keywords;
+ final String name;
+ final TypeAnnotationCode? type;
+
@override
CodeKind get kind => CodeKind.parameter;
- ParameterCode.fromString(String code) : super.fromString(code);
-
- ParameterCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
-/// A piece of code representing a syntactically valid statement.
-///
-/// Should always end with a semicolon.
-class StatementCode extends Code {
@override
- CodeKind get kind => CodeKind.statement;
+ List<Object> get parts => [
+ if (keywords.isNotEmpty) ...[
+ ...keywords.joinAsCode(' '),
+ ' ',
+ ],
+ if (type != null) ...[
+ type!,
+ ' ',
+ ],
+ name,
+ if (defaultValue != null) ...[
+ ' = ',
+ defaultValue!,
+ ]
+ ];
- StatementCode.fromString(String code) : super.fromString(code);
-
- StatementCode.fromParts(List<Object> parts) : super.fromParts(parts);
+ ParameterCode({
+ this.defaultValue,
+ this.keywords = const [],
+ required this.name,
+ this.type,
+ });
}
-extension Join<T extends Code> on List<T> {
+/// A piece of code representing a type annotation.
+abstract class TypeAnnotationCode implements Code {
+ /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+ /// of this one.
+ ///
+ /// Returns the current instance if it is already non-nullable.
+ TypeAnnotationCode get asNonNullable => this;
+
+ /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+ /// of this one.
+ ///
+ /// Returns the current instance if it is already nullable.
+ NullableTypeAnnotationCode get asNullable =>
+ new NullableTypeAnnotationCode(this);
+
+ /// Whether or not this type is nullable.
+ bool get isNullable => false;
+}
+
+/// The nullable version of an underlying type annotation.
+class NullableTypeAnnotationCode implements TypeAnnotationCode {
+ /// The underlying type that is being made nullable.
+ TypeAnnotationCode underlyingType;
+
+ @override
+ CodeKind get kind => CodeKind.nullableTypeAnnotation;
+
+ @override
+ List<Object> get parts => [...underlyingType.parts, '?'];
+
+ /// Creates a nullable [underlyingType] annotation.
+ ///
+ /// If [underlyingType] is a NullableTypeAnnotationCode, returns that
+ /// same type.
+ NullableTypeAnnotationCode(this.underlyingType);
+
+ @override
+ TypeAnnotationCode get asNonNullable => underlyingType;
+
+ @override
+ NullableTypeAnnotationCode get asNullable => this;
+
+ @override
+ bool get isNullable => true;
+}
+
+/// A piece of code representing a reference to a named type.
+class NamedTypeAnnotationCode extends TypeAnnotationCode {
+ final Identifier name;
+
+ final List<TypeAnnotationCode> typeArguments;
+
+ @override
+ CodeKind get kind => CodeKind.namedTypeAnnotation;
+
+ @override
+ List<Object> get parts => [
+ name,
+ if (typeArguments.isNotEmpty) ...[
+ '<',
+ ...typeArguments.joinAsCode(', '),
+ '>',
+ ],
+ ];
+
+ NamedTypeAnnotationCode({required this.name, this.typeArguments = const []});
+}
+
+/// A piece of code representing a function type annotation.
+class FunctionTypeAnnotationCode extends TypeAnnotationCode {
+ final List<ParameterCode> namedParameters;
+
+ final List<ParameterCode> positionalParameters;
+
+ final TypeAnnotationCode? returnType;
+
+ final List<TypeParameterCode> typeParameters;
+
+ @override
+ CodeKind get kind => CodeKind.functionTypeAnnotation;
+
+ @override
+ List<Object> get parts => [
+ if (returnType != null) returnType!,
+ ' Function',
+ if (typeParameters.isNotEmpty) ...[
+ '<',
+ ...typeParameters.joinAsCode(', '),
+ '>',
+ ],
+ '(',
+ for (ParameterCode positional in positionalParameters) ...[
+ positional,
+ ', ',
+ ],
+ if (namedParameters.isNotEmpty) ...[
+ '{',
+ for (ParameterCode named in namedParameters) ...[
+ named,
+ ', ',
+ ],
+ '}',
+ ],
+ ')',
+ ];
+
+ FunctionTypeAnnotationCode({
+ this.namedParameters = const [],
+ this.positionalParameters = const [],
+ this.returnType,
+ this.typeParameters = const [],
+ });
+}
+
+/// A piece of code representing a valid named type parameter.
+class TypeParameterCode implements Code {
+ final TypeAnnotationCode? bound;
+ final String name;
+
+ @override
+ CodeKind get kind => CodeKind.typeParameter;
+
+ @override
+ List<Object> get parts => [
+ name,
+ if (bound != null) ...[
+ ' extends ',
+ bound!,
+ ]
+ ];
+
+ TypeParameterCode({this.bound, required this.name});
+}
+
+extension Join<T extends Object> on List<T> {
/// Joins all the items in [this] with [separator], and returns
/// a new list.
- List<Code> joinAsCode(String separator) => [
+ List<Object> joinAsCode(String separator) => [
for (int i = 0; i < length - 1; i++) ...[
this[i],
- new Code.fromString(separator),
+ separator,
],
last,
];
}
enum CodeKind {
- raw,
declaration,
- element,
expression,
functionBody,
- namedArgument,
+ functionTypeAnnotation,
+ namedTypeAnnotation,
+ nullableTypeAnnotation,
parameter,
- statement,
+ raw,
+ typeParameter,
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
index 11fd6c3..c24cd91 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -24,10 +24,9 @@
/// trailing `?`)
bool get isNullable;
- /// A convenience method to get a [Code] object representation of this full
- /// type annotation, including support for generic type arguments as well as
- /// function types.
- Code get code;
+ /// A convenience method to get a [Code] object equivalent to this type
+ /// annotation.
+ TypeAnnotationCode get code;
}
/// The base class for function type declarations.
@@ -83,6 +82,9 @@
abstract class ClassMemberDeclaration implements Declaration {
/// The class that defines this method.
Identifier get definingClass;
+
+ /// Whether or not this is a static member.
+ bool get isStatic;
}
/// A declaration that defines a new type in the program.
@@ -131,6 +133,9 @@
/// Whether this function has an `external` modifier.
bool get isExternal;
+ /// Whether this function is an operator.
+ bool get isOperator;
+
/// Whether this function is actually a getter.
bool get isGetter;
@@ -173,10 +178,6 @@
/// The type of this field.
TypeAnnotation get type;
-
- /// A [ExpressionCode] object representing the initializer for this field, if
- /// present.
- ExpressionCode? get initializer;
}
/// Field introspection information.
@@ -195,13 +196,19 @@
/// parameter or an optional parameter with the `required` keyword.
bool get isRequired;
- /// A [Code] object representing the default value for this parameter, if
- /// present. Can be used to copy default values to other parameters.
- Code? get defaultValue;
+ /// A convenience method to get a `code` object equivalent to this parameter.
+ ///
+ /// Note that the original default value will not be included, as it is not a
+ /// part of this API.
+ ParameterCode get code;
}
/// Type parameter introspection information.
abstract class TypeParameterDeclaration implements Declaration {
- /// The bounds for this type parameter, if it has any.
- TypeAnnotation? get bounds;
+ /// The bound for this type parameter, if it has any.
+ TypeAnnotation? get bound;
+
+ /// A convenience method to get a `code` object equivalent to this type
+ /// parameter.
+ TypeParameterCode get code;
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index f604c80..a645eae 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -2,14 +2,24 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'executor/serialization.dart'
+ show SerializationMode, SerializationModeHelpers;
+
/// Generates a Dart program for a given set of macros, which can be compiled
/// and then passed as a precompiled kernel file to `MacroExecutor.loadMacro`.
///
/// The [macroDeclarations] is a map from library URIs to macro classes for the
/// macros supported. The macro classes are provided as a map from macro class
/// names to the names of the macro class constructors.
+///
+/// The [serializationMode] must be a client variant.
String bootstrapMacroIsolate(
- Map<String, Map<String, List<String>>> macroDeclarations) {
+ Map<String, Map<String, List<String>>> macroDeclarations,
+ SerializationMode serializationMode) {
+ if (!serializationMode.isClient) {
+ throw new ArgumentError(
+ 'Got $serializationMode but expected a client version.');
+ }
StringBuffer imports = new StringBuffer();
StringBuffer constructorEntries = new StringBuffer();
macroDeclarations
@@ -26,75 +36,119 @@
constructorEntries.writeln('},');
});
});
- return template.replaceFirst(_importMarker, imports.toString()).replaceFirst(
- _macroConstructorEntriesMarker, constructorEntries.toString());
+ return template
+ .replaceFirst(_importMarker, imports.toString())
+ .replaceFirst(
+ _macroConstructorEntriesMarker, constructorEntries.toString())
+ .replaceFirst(_modeMarker, serializationMode.asCode);
}
const String _importMarker = '{{IMPORT}}';
const String _macroConstructorEntriesMarker = '{{MACRO_CONSTRUCTOR_ENTRIES}}';
+const String _modeMarker = '{{SERIALIZATION_MODE}}';
const String template = '''
import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
import 'dart:isolate';
+import 'dart:typed_data';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/execute_macro.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/protocol.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/execute_macro.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/message_grouper.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/response_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
$_importMarker
-/// Entrypoint to be spawned with [Isolate.spawnUri].
+/// Entrypoint to be spawned with [Isolate.spawnUri] or [Process.start].
///
/// Supports the client side of the macro expansion protocol.
-void main(_, SendPort sendPort) {
- /// Local function that sends requests and returns responses using [sendPort].
- Future<Response> sendRequest(Request request) => _sendRequest(request, sendPort);
+void main(_, [SendPort? sendPort]) {
+ // Function that sends the result of a [Serializer] using either [sendPort]
+ // or [stdout].
+ void Function(Serializer) sendResult;
- withSerializationMode(SerializationMode.client, () {
- ReceivePort receivePort = new ReceivePort();
- sendPort.send(receivePort.sendPort);
+ // The stream for incoming messages, could be either a ReceivePort or stdin.
+ Stream<Object?> messageStream;
- receivePort.listen((message) async {
- var deserializer = JsonDeserializer(message as Iterable<Object?>)
- ..moveNext();
- int zoneId = deserializer.expectNum();
- deserializer..moveNext();
- var type = MessageType.values[deserializer.expectNum()];
- var serializer = JsonSerializer();
- switch (type) {
- case MessageType.instantiateMacroRequest:
- var request = new InstantiateMacroRequest.deserialize(deserializer, zoneId);
- (await _instantiateMacro(request)).serialize(serializer);
- break;
- case MessageType.executeDeclarationsPhaseRequest:
- var request = new ExecuteDeclarationsPhaseRequest.deserialize(deserializer, zoneId);
- (await _executeDeclarationsPhase(request, sendRequest)).serialize(serializer);
- break;
- case MessageType.executeDefinitionsPhaseRequest:
- var request = new ExecuteDefinitionsPhaseRequest.deserialize(deserializer, zoneId);
- (await _executeDefinitionsPhase(request, sendRequest)).serialize(serializer);
- break;
- case MessageType.executeTypesPhaseRequest:
- var request = new ExecuteTypesPhaseRequest.deserialize(deserializer, zoneId);
- (await _executeTypesPhase(request, sendRequest)).serialize(serializer);
- break;
- case MessageType.response:
- var response = new SerializableResponse.deserialize(deserializer, zoneId);
- _responseCompleters.remove(response.requestId)!.complete(response);
- return;
- default:
- throw new StateError('Unhandled event type \$type');
+ withSerializationMode($_modeMarker, () {
+ if (sendPort != null) {
+ ReceivePort receivePort = new ReceivePort();
+ messageStream = receivePort;
+ sendResult = (Serializer serializer) =>
+ _sendIsolateResult(serializer, sendPort);
+ // If using isolate communication, first send a sendPort to the parent
+ // isolate.
+ sendPort.send(receivePort.sendPort);
+ } else {
+ sendResult = _sendStdoutResult;
+ if (serializationMode == SerializationMode.byteDataClient) {
+ messageStream = MessageGrouper(stdin).messageStream;
+ } else if (serializationMode == SerializationMode.jsonClient) {
+ messageStream = stdin
+ .transform(const Utf8Decoder())
+ .transform(const LineSplitter())
+ .map((line) => jsonDecode(line)!);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode \$serializationMode for '
+ 'ProcessExecutor');
}
- sendPort.send(serializer.result);
- });
+ }
+
+ messageStream.listen((message) => _handleMessage(message, sendResult));
});
}
+void _handleMessage(
+ Object? message, void Function(Serializer) sendResult) async {
+ // Serializes `request` and send it using `sendResult`.
+ Future<Response> sendRequest(Request request) =>
+ _sendRequest(request, sendResult);
+
+ if (serializationMode == SerializationMode.byteDataClient
+ && message is TransferableTypedData) {
+ message = message.materialize().asUint8List();
+ }
+ var deserializer = deserializerFactory(message)
+ ..moveNext();
+ int zoneId = deserializer.expectInt();
+ deserializer..moveNext();
+ var type = MessageType.values[deserializer.expectInt()];
+ var serializer = serializerFactory();
+ switch (type) {
+ case MessageType.instantiateMacroRequest:
+ var request = new InstantiateMacroRequest.deserialize(deserializer, zoneId);
+ (await _instantiateMacro(request)).serialize(serializer);
+ break;
+ case MessageType.executeDeclarationsPhaseRequest:
+ var request = new ExecuteDeclarationsPhaseRequest.deserialize(deserializer, zoneId);
+ (await _executeDeclarationsPhase(request, sendRequest)).serialize(serializer);
+ break;
+ case MessageType.executeDefinitionsPhaseRequest:
+ var request = new ExecuteDefinitionsPhaseRequest.deserialize(deserializer, zoneId);
+ (await _executeDefinitionsPhase(request, sendRequest)).serialize(serializer);
+ break;
+ case MessageType.executeTypesPhaseRequest:
+ var request = new ExecuteTypesPhaseRequest.deserialize(deserializer, zoneId);
+ (await _executeTypesPhase(request, sendRequest)).serialize(serializer);
+ break;
+ case MessageType.response:
+ var response = new SerializableResponse.deserialize(deserializer, zoneId);
+ _responseCompleters.remove(response.requestId)!.complete(response);
+ return;
+ default:
+ throw new StateError('Unhandled event type \$type');
+ }
+ sendResult(serializer);
+}
+
/// Maps macro identifiers to constructors.
final _macroConstructors = <MacroClassIdentifierImpl, Map<String, Macro Function()>>{
$_macroConstructorEntriesMarker
@@ -122,7 +176,7 @@
for (MapEntry<String, Object?> entry in request.arguments.named.entries)
new Symbol(entry.key): entry.value,
}) as Macro;
- var identifier = new MacroInstanceIdentifierImpl(instance);
+ var identifier = new MacroInstanceIdentifierImpl(instance, request.instanceId);
_macroInstances[identifier] = instance;
return new SerializableResponse(
responseType: MessageType.macroInstanceIdentifier,
@@ -148,8 +202,13 @@
throw new StateError('Unrecognized macro instance \${request.macro}\\n'
'Known instances: \$_macroInstances)');
}
+ var identifierResolver = ClientIdentifierResolver(
+ sendRequest,
+ remoteInstance: request.identifierResolver,
+ serializationZoneId: request.serializationZoneId);
- var result = await executeTypesMacro(instance, request.declaration);
+ var result = await executeTypesMacro(
+ instance, request.declaration, identifierResolver);
return new SerializableResponse(
responseType: MessageType.macroExecutionResult,
response: result,
@@ -174,6 +233,10 @@
throw new StateError('Unrecognized macro instance \${request.macro}\\n'
'Known instances: \$_macroInstances)');
}
+ var identifierResolver = ClientIdentifierResolver(
+ sendRequest,
+ remoteInstance: request.identifierResolver,
+ serializationZoneId: request.serializationZoneId);
var classIntrospector = ClientClassIntrospector(
sendRequest,
remoteInstance: request.classIntrospector,
@@ -184,7 +247,8 @@
serializationZoneId: request.serializationZoneId);
var result = await executeDeclarationsMacro(
- instance, request.declaration, classIntrospector, typeResolver);
+ instance, request.declaration, identifierResolver, classIntrospector,
+ typeResolver);
return new SerializableResponse(
responseType: MessageType.macroExecutionResult,
response: result,
@@ -209,6 +273,10 @@
throw new StateError('Unrecognized macro instance \${request.macro}\\n'
'Known instances: \$_macroInstances)');
}
+ var identifierResolver = ClientIdentifierResolver(
+ sendRequest,
+ remoteInstance: request.identifierResolver,
+ serializationZoneId: request.serializationZoneId);
var typeResolver = ClientTypeResolver(
sendRequest,
remoteInstance: request.typeResolver,
@@ -223,8 +291,8 @@
serializationZoneId: request.serializationZoneId);
var result = await executeDefinitionMacro(
- instance, request.declaration, classIntrospector, typeResolver,
- typeDeclarationResolver);
+ instance, request.declaration, identifierResolver, classIntrospector,
+ typeResolver, typeDeclarationResolver);
return new SerializableResponse(
responseType: MessageType.macroExecutionResult,
response: result,
@@ -243,15 +311,50 @@
/// Holds on to response completers by request id.
final _responseCompleters = <int, Completer<Response>>{};
-/// Serializes [request], sends it to [sendPort], and sets up a [Completer] in
-/// [_responseCompleters] to handle the response.
-Future<Response> _sendRequest(Request request, SendPort sendPort) {
+/// Serializes [request], passes it to [sendResult], and sets up a [Completer]
+/// in [_responseCompleters] to handle the response.
+Future<Response> _sendRequest(
+ Request request, void Function(Serializer serializer) sendResult) {
Completer<Response> completer = Completer();
_responseCompleters[request.id] = completer;
- JsonSerializer serializer = JsonSerializer();
- serializer.addNum(request.serializationZoneId);
+ Serializer serializer = serializerFactory();
+ serializer.addInt(request.serializationZoneId);
request.serialize(serializer);
- sendPort.send(serializer.result);
+ sendResult(serializer);
return completer.future;
}
+
+/// Sends [serializer.result] to [sendPort], possibly wrapping it in a
+/// [TransferableTypedData] object.
+void _sendIsolateResult(Serializer serializer, SendPort sendPort) {
+ if (serializationMode == SerializationMode.byteDataClient) {
+ sendPort.send(
+ TransferableTypedData.fromList([serializer.result as Uint8List]));
+ } else {
+ sendPort.send(serializer.result);
+ }
+}
+
+/// Sends [serializer.result] to [stdout].
+///
+/// Serializes the result to a string if using JSON.
+void _sendStdoutResult(Serializer serializer) {
+ if (serializationMode == SerializationMode.jsonClient) {
+ stdout.writeln(jsonEncode(serializer.result));
+ } else if (serializationMode == SerializationMode.byteDataClient) {
+ Uint8List result = (serializer as ByteDataSerializer).result;
+ int length = result.lengthInBytes;
+ stdout.add([
+ length >> 24 & 0xff,
+ length >> 16 & 0xff,
+ length >> 8 & 0xff,
+ length & 0xff,
+ ]);
+ stdout.add(result);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode \$serializationMode for '
+ 'ProcessExecutor');
+ }
+}
''';
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index a4c2df3..c80c9a5 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -4,16 +4,7 @@
import 'api.dart';
import 'bootstrap.dart'; // For doc comments only.
-import 'executor_shared/serialization.dart';
-
-/// Exposes a platform specific [MacroExecutor], through a top level
-/// `Future<MacroExecutor> start()` function.
-///
-/// TODO: conditionally load isolate_mirrors_executor.dart once conditional
-/// imports of mirrors are supported in AOT (issue #48057).
-import 'fake_executor/fake_executor.dart'
- if (dart.library.isolate) 'isolated_executor/isolated_executor.dart'
- as executor_impl show start;
+import 'executor/serialization.dart';
/// The interface used by Dart language implementations, in order to load
/// and execute macros, as well as produce library augmentations from those
@@ -23,14 +14,6 @@
/// during macro discovery and expansion, and unifies how augmentation libraries
/// are produced.
abstract class MacroExecutor {
- /// Returns a platform specific [MacroExecutor]. On unsupported platforms this
- /// will be a fake executor object, which will throw an [UnsupportedError] if
- /// used.
- ///
- /// Note that some implementations will also require calls to [loadMacro]
- /// to pass a `precompiledKernelUri`.
- static Future<MacroExecutor> start() => executor_impl.start();
-
/// Invoked when an implementation discovers a new macro definition in a
/// [library] with [name], and prepares this executor to run the macro.
///
@@ -61,8 +44,8 @@
/// Runs the type phase for [macro] on a given [declaration].
///
/// Throws an exception if there is an error executing the macro.
- Future<MacroExecutionResult> executeTypesPhase(
- MacroInstanceIdentifier macro, covariant Declaration declaration);
+ Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
+ covariant Declaration declaration, IdentifierResolver identifierResolver);
/// Runs the declarations phase for [macro] on a given [declaration].
///
@@ -70,6 +53,7 @@
Future<MacroExecutionResult> executeDeclarationsPhase(
MacroInstanceIdentifier macro,
covariant Declaration declaration,
+ IdentifierResolver identifierResolver,
TypeResolver typeResolver,
ClassIntrospector classIntrospector);
@@ -79,14 +63,18 @@
Future<MacroExecutionResult> executeDefinitionsPhase(
MacroInstanceIdentifier macro,
covariant Declaration declaration,
+ IdentifierResolver identifierResolver,
TypeResolver typeResolver,
ClassIntrospector classIntrospector,
TypeDeclarationResolver typeDeclarationResolver);
/// Combines multiple [MacroExecutionResult]s into a single library
/// augmentation file, and returns a [String] representing that file.
- Future<String> buildAugmentationLibrary(
- Iterable<MacroExecutionResult> macroResults);
+ ///
+ /// The [resolveIdentifier] argument should return the import uri to be used
+ /// for that identifier.
+ String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+ ResolvedIdentifier Function(Identifier) resolveIdentifier);
/// Tell the executor to shut down and clean up any resources it may have
/// allocated.
@@ -129,7 +117,7 @@
static Object? _deserializeArg(Deserializer deserializer,
{bool alreadyMoved = false}) {
if (!alreadyMoved) deserializer.moveNext();
- _ArgumentKind kind = _ArgumentKind.values[deserializer.expectNum()];
+ _ArgumentKind kind = _ArgumentKind.values[deserializer.expectInt()];
switch (kind) {
case _ArgumentKind.nil:
return null;
@@ -139,9 +127,12 @@
case _ArgumentKind.bool:
deserializer.moveNext();
return deserializer.expectBool();
- case _ArgumentKind.num:
+ case _ArgumentKind.int:
deserializer.moveNext();
- return deserializer.expectNum();
+ return deserializer.expectInt();
+ case _ArgumentKind.double:
+ deserializer.moveNext();
+ return deserializer.expectDouble();
case _ArgumentKind.list:
deserializer.moveNext();
deserializer.expectList();
@@ -181,22 +172,26 @@
static void _serializeArg(Object? arg, Serializer serializer) {
if (arg == null) {
- serializer.addNum(_ArgumentKind.nil.index);
+ serializer.addInt(_ArgumentKind.nil.index);
} else if (arg is String) {
serializer
- ..addNum(_ArgumentKind.string.index)
+ ..addInt(_ArgumentKind.string.index)
..addString(arg);
- } else if (arg is num) {
+ } else if (arg is int) {
serializer
- ..addNum(_ArgumentKind.num.index)
- ..addNum(arg);
+ ..addInt(_ArgumentKind.int.index)
+ ..addInt(arg);
+ } else if (arg is double) {
+ serializer
+ ..addInt(_ArgumentKind.double.index)
+ ..addDouble(arg);
} else if (arg is bool) {
serializer
- ..addNum(_ArgumentKind.bool.index)
+ ..addInt(_ArgumentKind.bool.index)
..addBool(arg);
} else if (arg is List) {
serializer
- ..addNum(_ArgumentKind.list.index)
+ ..addInt(_ArgumentKind.list.index)
..startList();
for (Object? item in arg) {
_serializeArg(item, serializer);
@@ -204,7 +199,7 @@
serializer.endList();
} else if (arg is Map) {
serializer
- ..addNum(_ArgumentKind.map.index)
+ ..addInt(_ArgumentKind.map.index)
..startList();
for (MapEntry<Object?, Object?> entry in arg.entries) {
_serializeArg(entry.key, serializer);
@@ -217,6 +212,45 @@
}
}
+/// A resolved [Identifier], this is used when creating augmentation libraries
+/// to qualify identifiers where needed.
+class ResolvedIdentifier extends Identifier {
+ /// The import URI for the library that defines the member that is referenced
+ /// by this identifier.
+ ///
+ /// If this identifier is an instance member or a built-in type, like
+ /// `void`, [uri] is `null`.
+ final Uri? uri;
+
+ /// Type of identifier this is (instance, static, top level).
+ final IdentifierKind kind;
+
+ /// The unqualified name of this identifier.
+ @override
+ final String name;
+
+ /// If this is a static member, then the name of the fully qualified scope
+ /// surrounding this member. Should not contain a trailing `.`.
+ ///
+ /// Typically this would just be the name of a type.
+ final String? staticScope;
+
+ ResolvedIdentifier({
+ required this.kind,
+ required this.name,
+ required this.staticScope,
+ required this.uri,
+ });
+}
+
+/// The types of identifiers.
+enum IdentifierKind {
+ instanceMember,
+ local, // Parameters, local variables, etc.
+ staticInstanceMember,
+ topLevelMember,
+}
+
/// An opaque identifier for a macro class, retrieved by
/// [MacroExecutor.loadMacro].
///
@@ -243,12 +277,16 @@
/// All modifications are expressed in terms of library augmentation
/// declarations.
abstract class MacroExecutionResult implements Serializable {
- /// Any library imports that should be added to support the code used in
- /// the augmentations.
- Iterable<DeclarationCode> get imports;
+ /// Any augmentations that should be applied to a class as a result of
+ /// executing a macro, indexed by the name of the class.
+ Map<String, Iterable<DeclarationCode>> get classAugmentations;
- /// Any augmentations that should be applied as a result of executing a macro.
- Iterable<DeclarationCode> get augmentations;
+ /// Any augmentations that should be applied to the library as a result of
+ /// executing a macro.
+ Iterable<DeclarationCode> get libraryAugmentations;
+
+ /// The names of any new types declared in [augmentations].
+ Iterable<String> get newTypeNames;
}
/// Each of the possible types of declarations a macro can be applied to
@@ -274,4 +312,4 @@
}
/// Used for serializing and deserializing arguments.
-enum _ArgumentKind { string, bool, num, list, map, nil }
+enum _ArgumentKind { string, bool, double, int, list, map, nil }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
new file mode 100644
index 0000000..fd0b26bc
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../api.dart';
+import '../executor.dart';
+
+/// A mixin which provides a shared implementation of
+/// [MacroExecutor.buildAugmentationLibrary].
+mixin AugmentationLibraryBuilder on MacroExecutor {
+ @override
+ String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+ ResolvedIdentifier Function(Identifier) resolveIdentifier) {
+ StringBuffer importsBuffer = new StringBuffer();
+ StringBuffer directivesBuffer = new StringBuffer();
+ Map<Uri, String> importPrefixes = {};
+ int nextPrefix = 0;
+
+ // Keeps track of the last part written in `lastDirectivePart`.
+ String lastDirectivePart = '';
+ void writeDirectivePart(String part) {
+ lastDirectivePart = part;
+ directivesBuffer.write(part);
+ }
+
+ void buildCode(Code code) {
+ for (Object part in code.parts) {
+ if (part is String) {
+ writeDirectivePart(part);
+ } else if (part is Code) {
+ buildCode(part);
+ } else if (part is Identifier) {
+ ResolvedIdentifier resolved = resolveIdentifier(part);
+ String? prefix;
+ if (resolved.uri != null) {
+ prefix = importPrefixes.putIfAbsent(resolved.uri!, () {
+ String prefix = 'i${nextPrefix++}';
+ importsBuffer.writeln("import '${resolved.uri}' as $prefix;");
+ return prefix;
+ });
+ }
+ if (resolved.kind == IdentifierKind.instanceMember) {
+ // Qualify with `this.` if we don't have a receiver.
+ if (!lastDirectivePart.trimRight().endsWith('.')) {
+ writeDirectivePart('this.');
+ }
+ } else if (prefix != null) {
+ writeDirectivePart('${prefix}.');
+ }
+ if (resolved.kind == IdentifierKind.staticInstanceMember) {
+ writeDirectivePart('${resolved.staticScope!}.');
+ }
+ writeDirectivePart('${part.name}');
+ } else {
+ throw new ArgumentError(
+ 'Code objects only support String, Identifier, and Code '
+ 'instances but got $part which was not one of those.');
+ }
+ }
+ }
+
+ Map<String, List<DeclarationCode>> mergedClassResults = {};
+ for (MacroExecutionResult result in macroResults) {
+ for (DeclarationCode augmentation in result.libraryAugmentations) {
+ buildCode(augmentation);
+ directivesBuffer.writeln();
+ }
+ for (MapEntry<String, Iterable<DeclarationCode>> entry
+ in result.classAugmentations.entries) {
+ mergedClassResults.update(
+ entry.key, (value) => value..addAll(entry.value),
+ ifAbsent: () => entry.value.toList());
+ }
+ }
+ for (MapEntry<String, List<DeclarationCode>> entry
+ in mergedClassResults.entries) {
+ directivesBuffer.writeln('augment class ${entry.key} {');
+ for (DeclarationCode augmentation in entry.value) {
+ buildCode(augmentation);
+ directivesBuffer.writeln();
+ }
+ directivesBuffer.writeln('}');
+ }
+ return '$importsBuffer\n\n$directivesBuffer';
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/builder_impls.dart
new file mode 100644
index 0000000..6f522e0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/builder_impls.dart
@@ -0,0 +1,407 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
+
+import '../executor.dart';
+import '../api.dart';
+import 'response_impls.dart';
+
+class TypeBuilderBase implements IdentifierResolver {
+ /// The final result, will be built up over `augment` calls.
+ final List<DeclarationCode> _libraryAugmentations;
+
+ /// The final result, will be built up over `augment` calls.
+ final Map<String, List<DeclarationCode>> _classAugmentations;
+
+ /// The names of any new types added in [_libraryAugmentations].
+ final List<String> _newTypeNames = [];
+
+ final IdentifierResolver identifierResolver;
+
+ /// Creates and returns a [MacroExecutionResult] out of the [_augmentations]
+ /// created by this builder.
+ MacroExecutionResult get result => new MacroExecutionResultImpl(
+ classAugmentations: _classAugmentations,
+ libraryAugmentations: _libraryAugmentations,
+ newTypeNames: _newTypeNames,
+ );
+
+ TypeBuilderBase(this.identifierResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : _classAugmentations = parentClassAugmentations ?? {},
+ _libraryAugmentations = parentLibraryAugmentations ?? [];
+
+ @override
+ Future<Identifier> resolveIdentifier(Uri library, String identifier) =>
+ // ignore: deprecated_member_use_from_same_package
+ identifierResolver.resolveIdentifier(library, identifier);
+}
+
+class TypeBuilderImpl extends TypeBuilderBase implements TypeBuilder {
+ TypeBuilderImpl(IdentifierResolver identifierResolver)
+ : super(identifierResolver);
+
+ @override
+ void declareType(String name, DeclarationCode typeDeclaration) {
+ _newTypeNames.add(name);
+ _libraryAugmentations.add(typeDeclaration);
+ }
+}
+
+/// Base class for all [DeclarationBuilder]s.
+class DeclarationBuilderBase extends TypeBuilderBase
+ implements ClassIntrospector, TypeResolver {
+ final ClassIntrospector classIntrospector;
+ final TypeResolver typeResolver;
+
+ DeclarationBuilderBase(IdentifierResolver identifierResolver,
+ this.classIntrospector, this.typeResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
+ classIntrospector.constructorsOf(clazz);
+
+ @override
+ Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
+ classIntrospector.fieldsOf(clazz);
+
+ @override
+ Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
+ classIntrospector.interfacesOf(clazz);
+
+ @override
+ Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
+ classIntrospector.methodsOf(clazz);
+
+ @override
+ Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
+ classIntrospector.mixinsOf(clazz);
+
+ @override
+ Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
+ classIntrospector.superclassOf(clazz);
+
+ @override
+ Future<StaticType> resolve(TypeAnnotationCode code) =>
+ typeResolver.resolve(code);
+}
+
+class DeclarationBuilderImpl extends DeclarationBuilderBase
+ implements DeclarationBuilder {
+ DeclarationBuilderImpl(IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector, TypeResolver typeResolver)
+ : super(identifierResolver, classIntrospector, typeResolver);
+
+ @override
+ void declareInLibrary(DeclarationCode declaration) {
+ _libraryAugmentations.add(declaration);
+ }
+}
+
+class ClassMemberDeclarationBuilderImpl extends DeclarationBuilderImpl
+ implements ClassMemberDeclarationBuilder {
+ final Identifier definingClass;
+
+ ClassMemberDeclarationBuilderImpl(
+ this.definingClass,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver)
+ : super(identifierResolver, classIntrospector, typeResolver);
+
+ @override
+ void declareInClass(DeclarationCode declaration) {
+ _classAugmentations.update(
+ definingClass.name, (value) => value..add(declaration),
+ ifAbsent: () => [declaration]);
+ }
+}
+
+/// Base class for all [DefinitionBuilder]s.
+class DefinitionBuilderBase extends DeclarationBuilderBase
+ implements TypeDeclarationResolver {
+ final TypeDeclarationResolver typeDeclarationResolver;
+
+ DefinitionBuilderBase(
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ this.typeDeclarationResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver, classIntrospector, typeResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) =>
+ typeDeclarationResolver.declarationOf(identifier);
+}
+
+class ClassDefinitionBuilderImpl extends DefinitionBuilderBase
+ implements ClassDefinitionBuilder {
+ /// The declaration this is a builder for.
+ final ClassDeclaration declaration;
+
+ ClassDefinitionBuilderImpl(
+ this.declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ TypeDeclarationResolver typeDeclarationResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver, classIntrospector, typeResolver,
+ typeDeclarationResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ Future<ConstructorDefinitionBuilder> buildConstructor(
+ Identifier identifier) async {
+ ConstructorDeclaration constructor =
+ (await classIntrospector.constructorsOf(declaration))
+ .firstWhere((constructor) => constructor.identifier == identifier);
+ return new ConstructorDefinitionBuilderImpl(constructor, identifierResolver,
+ classIntrospector, typeResolver, typeDeclarationResolver,
+ parentClassAugmentations: _classAugmentations,
+ parentLibraryAugmentations: _libraryAugmentations);
+ }
+
+ @override
+ Future<VariableDefinitionBuilder> buildField(Identifier identifier) async {
+ FieldDeclaration field = (await classIntrospector.fieldsOf(declaration))
+ .firstWhere((field) => field.identifier == identifier);
+ return new VariableDefinitionBuilderImpl(field, identifierResolver,
+ classIntrospector, typeResolver, typeDeclarationResolver,
+ parentClassAugmentations: _classAugmentations,
+ parentLibraryAugmentations: _libraryAugmentations);
+ }
+
+ @override
+ Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier) async {
+ MethodDeclaration method = (await classIntrospector.methodsOf(declaration))
+ .firstWhere((method) => method.identifier == identifier);
+ return new FunctionDefinitionBuilderImpl(method, identifierResolver,
+ classIntrospector, typeResolver, typeDeclarationResolver,
+ parentClassAugmentations: _classAugmentations,
+ parentLibraryAugmentations: _libraryAugmentations);
+ }
+}
+
+/// Implementation of [FunctionDefinitionBuilder].
+class FunctionDefinitionBuilderImpl extends DefinitionBuilderBase
+ implements FunctionDefinitionBuilder {
+ final FunctionDeclaration declaration;
+
+ FunctionDefinitionBuilderImpl(
+ this.declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ TypeDeclarationResolver typeDeclarationResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver, classIntrospector, typeResolver,
+ typeDeclarationResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ void augment(FunctionBodyCode body) {
+ DeclarationCode augmentation =
+ _buildFunctionAugmentation(body, declaration);
+ if (declaration is ClassMemberDeclaration) {
+ _classAugmentations.update(
+ (declaration as ClassMemberDeclaration).definingClass.name,
+ (value) => value..add(augmentation),
+ ifAbsent: () => [augmentation]);
+ } else {
+ _libraryAugmentations.add(augmentation);
+ }
+ }
+}
+
+class ConstructorDefinitionBuilderImpl extends DefinitionBuilderBase
+ implements ConstructorDefinitionBuilder {
+ final ConstructorDeclaration declaration;
+
+ ConstructorDefinitionBuilderImpl(
+ this.declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ TypeDeclarationResolver typeDeclarationResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver, classIntrospector, typeResolver,
+ typeDeclarationResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ void augment({FunctionBodyCode? body, List<Code>? initializers}) {
+ body ??= new FunctionBodyCode.fromString('''{
+ augment super();
+ }''');
+ DeclarationCode augmentation = _buildFunctionAugmentation(body, declaration,
+ initializers: initializers);
+ _classAugmentations.update(
+ declaration.definingClass.name, (value) => value..add(augmentation),
+ ifAbsent: () => [augmentation]);
+ }
+}
+
+class VariableDefinitionBuilderImpl extends DefinitionBuilderBase
+ implements VariableDefinitionBuilder {
+ final VariableDeclaration declaration;
+
+ VariableDefinitionBuilderImpl(
+ this.declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ TypeDeclarationResolver typeDeclarationResolver,
+ {Map<String, List<DeclarationCode>>? parentClassAugmentations,
+ List<DeclarationCode>? parentLibraryAugmentations})
+ : super(identifierResolver, classIntrospector, typeResolver,
+ typeDeclarationResolver,
+ parentClassAugmentations: parentClassAugmentations,
+ parentLibraryAugmentations: parentLibraryAugmentations);
+
+ @override
+ void augment(
+ {DeclarationCode? getter,
+ DeclarationCode? setter,
+ ExpressionCode? initializer}) {
+ List<DeclarationCode> augmentations = _buildVariableAugmentations(
+ declaration,
+ getter: getter,
+ setter: setter,
+ initializer: initializer);
+ if (declaration is ClassMemberDeclaration) {
+ _classAugmentations.update(
+ (declaration as ClassMemberDeclaration).definingClass.name,
+ (value) => value..addAll(augmentations),
+ ifAbsent: () => augmentations);
+ } else {
+ _libraryAugmentations.addAll(augmentations);
+ }
+ }
+}
+
+/// Builds all the possible augmentations for a variable.
+List<DeclarationCode> _buildVariableAugmentations(
+ VariableDeclaration declaration,
+ {DeclarationCode? getter,
+ DeclarationCode? setter,
+ ExpressionCode? initializer}) {
+ List<DeclarationCode> augmentations = [];
+ if (getter != null) {
+ augmentations.add(new DeclarationCode.fromParts([
+ 'augment ',
+ if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
+ getter,
+ ]));
+ }
+ if (setter != null) {
+ augmentations.add(new DeclarationCode.fromParts([
+ 'augment ',
+ if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
+ setter,
+ ]));
+ }
+ if (initializer != null) {
+ augmentations.add(new DeclarationCode.fromParts([
+ 'augment ',
+ if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
+ if (declaration.isFinal) 'final ',
+ declaration.type.code,
+ ' ',
+ declaration.identifier,
+ ' = ',
+ initializer,
+ ';',
+ ]));
+ }
+
+ return augmentations;
+}
+
+/// Builds the code to augment a function, method, or constructor with a new
+/// body.
+///
+/// The [initializers] parameter can only be used if [declaration] is a
+/// constructor.
+DeclarationCode _buildFunctionAugmentation(
+ FunctionBodyCode body, FunctionDeclaration declaration,
+ {List<Code>? initializers}) {
+ assert(initializers == null || declaration is ConstructorDeclaration);
+
+ return new DeclarationCode.fromParts([
+ 'augment ',
+ if (declaration is ConstructorDeclaration) ...[
+ declaration.definingClass.name,
+ if (declaration.identifier.name.isNotEmpty) '.',
+ ] else ...[
+ if (declaration is MethodDeclaration && declaration.isStatic) 'static ',
+ declaration.returnType.code,
+ ' ',
+ if (declaration.isOperator) 'operator ',
+ ],
+ declaration.identifier.name,
+ if (declaration.typeParameters.isNotEmpty) ...[
+ '<',
+ for (TypeParameterDeclaration typeParam
+ in declaration.typeParameters) ...[
+ typeParam.identifier.name,
+ if (typeParam.bound != null) ...[' extends ', typeParam.bound!.code],
+ if (typeParam != declaration.typeParameters.last) ', ',
+ ],
+ '>',
+ ],
+ '(',
+ for (ParameterDeclaration positionalRequired
+ in declaration.positionalParameters.takeWhile((p) => p.isRequired)) ...[
+ positionalRequired.code,
+ ', ',
+ ],
+ if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
+ '[',
+ for (ParameterDeclaration positionalOptional
+ in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
+ positionalOptional.code,
+ ', ',
+ ],
+ ']',
+ ],
+ if (declaration.namedParameters.isNotEmpty) ...[
+ '{',
+ for (ParameterDeclaration named in declaration.namedParameters) ...[
+ named.code,
+ ', ',
+ ],
+ '}',
+ ],
+ ') ',
+ if (initializers != null && initializers.isNotEmpty) ...[
+ ' : ',
+ initializers.first,
+ for (Code initializer in initializers.skip(1)) ...[
+ ',\n',
+ initializer,
+ ],
+ ],
+ body,
+ ]);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/execute_macro.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/execute_macro.dart
new file mode 100644
index 0000000..af3224f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/execute_macro.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/builder_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+/// Runs [macro] in the types phase and returns a [MacroExecutionResult].
+Future<MacroExecutionResult> executeTypesMacro(Macro macro,
+ Declaration declaration, IdentifierResolver identifierResolver) async {
+ TypeBuilderImpl builder = new TypeBuilderImpl(identifierResolver);
+ if (declaration is FunctionDeclaration) {
+ if (macro is ConstructorTypesMacro &&
+ declaration is ConstructorDeclaration) {
+ await macro.buildTypesForConstructor(declaration, builder);
+ return builder.result;
+ } else if (macro is MethodTypesMacro && declaration is MethodDeclaration) {
+ await macro.buildTypesForMethod(declaration, builder);
+ return builder.result;
+ } else if (macro is FunctionTypesMacro) {
+ await macro.buildTypesForFunction(declaration, builder);
+ return builder.result;
+ }
+ } else if (declaration is VariableDeclaration) {
+ if (macro is FieldTypesMacro && declaration is FieldDeclaration) {
+ await macro.buildTypesForField(declaration, builder);
+ return builder.result;
+ } else if (macro is VariableTypesMacro) {
+ await macro.buildTypesForVariable(declaration, builder);
+ return builder.result;
+ }
+ } else if (macro is ClassTypesMacro && declaration is ClassDeclaration) {
+ await macro.buildTypesForClass(declaration, builder);
+ return builder.result;
+ }
+ throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+ 'macro: $macro\ndeclaration: $declaration');
+}
+
+/// Runs [macro] in the declaration phase and returns a [MacroExecutionResult].
+Future<MacroExecutionResult> executeDeclarationsMacro(
+ Macro macro,
+ Declaration declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver) async {
+ if (declaration is ClassDeclaration && macro is ClassDeclarationsMacro) {
+ ClassMemberDeclarationBuilderImpl builder =
+ new ClassMemberDeclarationBuilderImpl(declaration.identifier,
+ identifierResolver, classIntrospector, typeResolver);
+ await macro.buildDeclarationsForClass(declaration, builder);
+ return builder.result;
+ } else if (declaration is ClassMemberDeclaration) {
+ ClassMemberDeclarationBuilderImpl builder =
+ new ClassMemberDeclarationBuilderImpl(declaration.definingClass,
+ identifierResolver, classIntrospector, typeResolver);
+ if (declaration is FunctionDeclaration) {
+ if (macro is ConstructorDeclarationsMacro &&
+ declaration is ConstructorDeclaration) {
+ await macro.buildDeclarationsForConstructor(declaration, builder);
+ return builder.result;
+ } else if (macro is MethodDeclarationsMacro &&
+ declaration is MethodDeclaration) {
+ await macro.buildDeclarationsForMethod(declaration, builder);
+ return builder.result;
+ } else if (macro is FunctionDeclarationsMacro) {
+ await macro.buildDeclarationsForFunction(
+ declaration as FunctionDeclaration, builder);
+ return builder.result;
+ }
+ } else if (declaration is VariableDeclaration) {
+ if (macro is FieldDeclarationsMacro && declaration is FieldDeclaration) {
+ await macro.buildDeclarationsForField(declaration, builder);
+ return builder.result;
+ } else if (macro is VariableDeclarationsMacro) {
+ DeclarationBuilderImpl builder = new DeclarationBuilderImpl(
+ identifierResolver, classIntrospector, typeResolver);
+ await macro.buildDeclarationsForVariable(
+ declaration as VariableDeclaration, builder);
+ return builder.result;
+ }
+ }
+ } else {
+ DeclarationBuilderImpl builder = new DeclarationBuilderImpl(
+ identifierResolver, classIntrospector, typeResolver);
+ if (declaration is FunctionDeclaration &&
+ macro is FunctionDeclarationsMacro) {
+ await macro.buildDeclarationsForFunction(declaration, builder);
+ return builder.result;
+ } else if (macro is VariableDeclarationsMacro &&
+ declaration is VariableDeclaration) {
+ await macro.buildDeclarationsForVariable(declaration, builder);
+ return builder.result;
+ }
+ }
+ throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+ 'macro: $macro\ndeclaration: $declaration');
+}
+
+/// Runs [macro] in the definition phase and returns a [MacroExecutionResult].
+Future<MacroExecutionResult> executeDefinitionMacro(
+ Macro macro,
+ Declaration declaration,
+ IdentifierResolver identifierResolver,
+ ClassIntrospector classIntrospector,
+ TypeResolver typeResolver,
+ TypeDeclarationResolver typeDeclarationResolver) async {
+ if (declaration is FunctionDeclaration) {
+ if (macro is ConstructorDefinitionMacro &&
+ declaration is ConstructorDeclaration) {
+ ConstructorDefinitionBuilderImpl builder =
+ new ConstructorDefinitionBuilderImpl(declaration, identifierResolver,
+ classIntrospector, typeResolver, typeDeclarationResolver);
+ await macro.buildDefinitionForConstructor(declaration, builder);
+ return builder.result;
+ } else {
+ FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
+ declaration,
+ identifierResolver,
+ classIntrospector,
+ typeResolver,
+ typeDeclarationResolver);
+ if (macro is MethodDefinitionMacro && declaration is MethodDeclaration) {
+ await macro.buildDefinitionForMethod(declaration, builder);
+ return builder.result;
+ } else if (macro is FunctionDefinitionMacro) {
+ await macro.buildDefinitionForFunction(declaration, builder);
+ return builder.result;
+ }
+ }
+ } else if (declaration is VariableDeclaration) {
+ VariableDefinitionBuilderImpl builder = new VariableDefinitionBuilderImpl(
+ declaration,
+ identifierResolver,
+ classIntrospector,
+ typeResolver,
+ typeDeclarationResolver);
+ if (macro is FieldDefinitionMacro && declaration is FieldDeclaration) {
+ await macro.buildDefinitionForField(declaration, builder);
+ return builder.result;
+ } else if (macro is VariableDefinitionMacro) {
+ await macro.buildDefinitionForVariable(declaration, builder);
+ return builder.result;
+ }
+ } else if (macro is ClassDefinitionMacro && declaration is ClassDeclaration) {
+ ClassDefinitionBuilderImpl builder = new ClassDefinitionBuilderImpl(
+ declaration,
+ identifierResolver,
+ classIntrospector,
+ typeResolver,
+ typeDeclarationResolver);
+ await macro.buildDefinitionForClass(declaration, builder);
+ return builder.result;
+ }
+ throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+ 'macro: $macro\ndeclaration: $declaration');
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
new file mode 100644
index 0000000..940fa5a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
@@ -0,0 +1,396 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
+
+import '../api.dart';
+import '../executor/introspection_impls.dart';
+import '../executor/protocol.dart';
+import '../executor/serialization.dart';
+import '../executor.dart';
+
+/// Base implementation for macro executors which communicate with some external
+/// process to run macros.
+///
+/// Subtypes must extend this class and implement the [close] and [sendResult]
+/// apis to handle communication with the external macro program.
+abstract class ExternalMacroExecutorBase extends MacroExecutor {
+ /// The stream on which we receive messages from the external macro executor.
+ final Stream<Object> messageStream;
+
+ /// The mode to use for serialization - must be a `server` variant.
+ final SerializationMode serializationMode;
+
+ /// A map of response completers by request id.
+ final _responseCompleters = <int, Completer<Response>>{};
+
+ /// We need to know which serialization zone to deserialize objects in, so
+ /// that we read them from the correct cache. Each macro execution creates its
+ /// own zone which it stores here by ID and then responses are deserialized in
+ /// that same zone.
+ static final _serializationZones = <int, Zone>{};
+
+ /// Incrementing identifier for the serialization zone ids.
+ static int _nextSerializationZoneId = 0;
+
+ ExternalMacroExecutorBase(
+ {required this.messageStream, required this.serializationMode}) {
+ messageStream.listen((message) {
+ withSerializationMode(serializationMode, () {
+ Deserializer deserializer = deserializerFactory(message);
+ // Every object starts with a zone ID which dictates the zone in which
+ // we should deserialize the message.
+ deserializer.moveNext();
+ int zoneId = deserializer.expectInt();
+ Zone zone = _serializationZones[zoneId]!;
+ zone.run(() async {
+ deserializer.moveNext();
+ MessageType messageType =
+ MessageType.values[deserializer.expectInt()];
+ switch (messageType) {
+ case MessageType.response:
+ SerializableResponse response =
+ new SerializableResponse.deserialize(deserializer, zoneId);
+ Completer<Response>? completer =
+ _responseCompleters.remove(response.requestId);
+ if (completer == null) {
+ throw new StateError(
+ 'Got a response for an unrecognized request id '
+ '${response.requestId}');
+ }
+ completer.complete(response);
+ break;
+ case MessageType.resolveIdentifierRequest:
+ ResolveIdentifierRequest request =
+ new ResolveIdentifierRequest.deserialize(
+ deserializer, zoneId);
+ SerializableResponse response;
+ try {
+ IdentifierImpl identifier = await (request
+ .identifierResolver.instance as IdentifierResolver)
+ // ignore: deprecated_member_use_from_same_package
+ .resolveIdentifier(request.library, request.name)
+ as IdentifierImpl;
+ response = new SerializableResponse(
+ response: identifier,
+ requestId: request.id,
+ responseType: MessageType.remoteInstance,
+ serializationZoneId: zoneId);
+ } catch (error, stackTrace) {
+ response = new SerializableResponse(
+ error: '$error',
+ stackTrace: '$stackTrace',
+ requestId: request.id,
+ responseType: MessageType.error,
+ serializationZoneId: zoneId);
+ }
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.resolveTypeRequest:
+ ResolveTypeRequest request =
+ new ResolveTypeRequest.deserialize(deserializer, zoneId);
+ StaticType instance =
+ await (request.typeResolver.instance as TypeResolver)
+ .resolve(request.typeAnnotationCode);
+ SerializableResponse response = new SerializableResponse(
+ response: new RemoteInstanceImpl(
+ id: RemoteInstance.uniqueId,
+ instance: instance,
+ kind: instance is NamedStaticType
+ ? RemoteInstanceKind.namedStaticType
+ : RemoteInstanceKind.staticType),
+ requestId: request.id,
+ responseType: instance is NamedStaticType
+ ? MessageType.namedStaticType
+ : MessageType.staticType,
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.isExactlyTypeRequest:
+ IsExactlyTypeRequest request =
+ new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
+ StaticType leftType = request.leftType.instance as StaticType;
+ StaticType rightType = request.rightType.instance as StaticType;
+ SerializableResponse response = new SerializableResponse(
+ response:
+ new BooleanValue(await leftType.isExactly(rightType)),
+ requestId: request.id,
+ responseType: MessageType.boolean,
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.isSubtypeOfRequest:
+ IsSubtypeOfRequest request =
+ new IsSubtypeOfRequest.deserialize(deserializer, zoneId);
+ StaticType leftType = request.leftType.instance as StaticType;
+ StaticType rightType = request.rightType.instance as StaticType;
+ SerializableResponse response = new SerializableResponse(
+ response:
+ new BooleanValue(await leftType.isSubtypeOf(rightType)),
+ requestId: request.id,
+ responseType: MessageType.boolean,
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.declarationOfRequest:
+ DeclarationOfRequest request =
+ new DeclarationOfRequest.deserialize(deserializer, zoneId);
+ TypeDeclarationResolver resolver = request
+ .typeDeclarationResolver.instance as TypeDeclarationResolver;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.remoteInstance,
+ response: (await resolver.declarationOf(request.identifier)
+ // TODO: Consider refactoring to avoid the need for this.
+ as TypeDeclarationImpl),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.constructorsOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.declarationList,
+ response: new DeclarationList((await classIntrospector
+ .constructorsOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ .cast<ConstructorDeclarationImpl>()),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.fieldsOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.declarationList,
+ response: new DeclarationList((await classIntrospector
+ .fieldsOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ .cast<FieldDeclarationImpl>()),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.interfacesOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.declarationList,
+ response: new DeclarationList((await classIntrospector
+ .interfacesOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ .cast<ClassDeclarationImpl>()),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.methodsOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.declarationList,
+ response: new DeclarationList((await classIntrospector
+ .methodsOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ .cast<MethodDeclarationImpl>()),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.mixinsOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.declarationList,
+ response: new DeclarationList((await classIntrospector
+ .mixinsOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ .cast<ClassDeclarationImpl>()),
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ case MessageType.superclassOfRequest:
+ ClassIntrospectionRequest request =
+ new ClassIntrospectionRequest.deserialize(
+ deserializer, messageType, zoneId);
+ ClassIntrospector classIntrospector =
+ request.classIntrospector.instance as ClassIntrospector;
+ SerializableResponse response = new SerializableResponse(
+ requestId: request.id,
+ responseType: MessageType.remoteInstance,
+ response: (await classIntrospector
+ .superclassOf(request.classDeclaration))
+ // TODO: Consider refactoring to avoid the need for this.
+ as ClassDeclarationImpl?,
+ serializationZoneId: zoneId);
+ Serializer serializer = serializerFactory();
+ response.serialize(serializer);
+ sendResult(serializer);
+ break;
+ default:
+ throw new StateError('Unexpected message type $messageType');
+ }
+ });
+ });
+ });
+ }
+
+ /// These calls are handled by the higher level executor.
+ @override
+ String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+ ResolvedIdentifier Function(Identifier) resolveIdentifier) =>
+ throw new StateError('Unreachable');
+
+ @override
+ Future<MacroExecutionResult> executeDeclarationsPhase(
+ MacroInstanceIdentifier macro,
+ DeclarationImpl declaration,
+ IdentifierResolver identifierResolver,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector) =>
+ _sendRequest((zoneId) => new ExecuteDeclarationsPhaseRequest(
+ macro,
+ declaration,
+ new RemoteInstanceImpl(
+ instance: identifierResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.identifierResolver),
+ new RemoteInstanceImpl(
+ instance: typeResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.typeResolver),
+ new RemoteInstanceImpl(
+ instance: classIntrospector,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.classIntrospector),
+ serializationZoneId: zoneId));
+
+ @override
+ Future<MacroExecutionResult> executeDefinitionsPhase(
+ MacroInstanceIdentifier macro,
+ DeclarationImpl declaration,
+ IdentifierResolver identifierResolver,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector,
+ TypeDeclarationResolver typeDeclarationResolver) =>
+ _sendRequest((zoneId) => new ExecuteDefinitionsPhaseRequest(
+ macro,
+ declaration,
+ new RemoteInstanceImpl(
+ instance: identifierResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.identifierResolver),
+ new RemoteInstanceImpl(
+ instance: typeResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.typeResolver),
+ new RemoteInstanceImpl(
+ instance: classIntrospector,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.classIntrospector),
+ new RemoteInstanceImpl(
+ instance: typeDeclarationResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.typeDeclarationResolver),
+ serializationZoneId: zoneId));
+
+ @override
+ Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
+ DeclarationImpl declaration, IdentifierResolver identifierResolver) =>
+ _sendRequest((zoneId) => new ExecuteTypesPhaseRequest(
+ macro,
+ declaration,
+ new RemoteInstanceImpl(
+ instance: identifierResolver,
+ id: RemoteInstance.uniqueId,
+ kind: RemoteInstanceKind.identifierResolver),
+ serializationZoneId: zoneId));
+
+ @override
+ Future<MacroInstanceIdentifier> instantiateMacro(
+ MacroClassIdentifier macroClass,
+ String constructor,
+ Arguments arguments) =>
+ _sendRequest((zoneId) => new InstantiateMacroRequest(
+ macroClass, constructor, arguments, RemoteInstance.uniqueId,
+ serializationZoneId: zoneId));
+
+ /// These calls are handled by the higher level executor.
+ @override
+ Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+ {Uri? precompiledKernelUri}) =>
+ throw new StateError(
+ 'This executor should be wrapped in a MultiMacroExecutor which will '
+ 'handle load requests.');
+
+ /// Sends [serializer.result] to [sendPort], possibly wrapping it in a
+ /// [TransferableTypedData] object.
+ void sendResult(Serializer serializer);
+
+ /// Creates a [Request] with a given serialization zone ID, and handles the
+ /// response, casting it to the expected type or throwing the error provided.
+ Future<T> _sendRequest<T>(Request Function(int) requestFactory) =>
+ withSerializationMode(serializationMode, () async {
+ int zoneId = _nextSerializationZoneId++;
+ _serializationZones[zoneId] = Zone.current;
+ Request request = requestFactory(zoneId);
+ Serializer serializer = serializerFactory();
+ // It is our responsibility to add the zone ID header.
+ serializer.addInt(zoneId);
+ request.serialize(serializer);
+ sendResult(serializer);
+ Completer<Response> completer = new Completer<Response>();
+ _responseCompleters[request.id] = completer;
+ try {
+ Response response = await completer.future;
+ T? result = response.response as T?;
+ if (result != null) return result;
+ throw new RemoteException(
+ response.error!.toString(), response.stackTrace);
+ } finally {
+ // Clean up the zone after the request is done.
+ _serializationZones.remove(zoneId);
+ }
+ });
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart
new file mode 100644
index 0000000..857674e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/introspection_impls.dart
@@ -0,0 +1,618 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'remote_instance.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+import '../api.dart';
+
+class IdentifierImpl extends RemoteInstance implements Identifier {
+ final String name;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.identifier;
+
+ IdentifierImpl({required int id, required this.name}) : super(id);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer.addString(name);
+ }
+}
+
+abstract class TypeAnnotationImpl extends RemoteInstance
+ implements TypeAnnotation {
+ final bool isNullable;
+
+ TypeAnnotationImpl({required int id, required this.isNullable}) : super(id);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer.addBool(isNullable);
+ }
+}
+
+class NamedTypeAnnotationImpl extends TypeAnnotationImpl
+ implements NamedTypeAnnotation {
+ @override
+ TypeAnnotationCode get code {
+ NamedTypeAnnotationCode underlyingType =
+ new NamedTypeAnnotationCode(name: identifier, typeArguments: [
+ for (TypeAnnotation typeArg in typeArguments) typeArg.code,
+ ]);
+ return isNullable ? underlyingType.asNullable : underlyingType;
+ }
+
+ @override
+ final IdentifierImpl identifier;
+
+ @override
+ final List<TypeAnnotationImpl> typeArguments;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.namedTypeAnnotation;
+
+ NamedTypeAnnotationImpl({
+ required int id,
+ required bool isNullable,
+ required this.identifier,
+ required this.typeArguments,
+ }) : super(id: id, isNullable: isNullable);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ identifier.serialize(serializer);
+ serializer.startList();
+ for (TypeAnnotationImpl typeArg in typeArguments) {
+ typeArg.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+class FunctionTypeAnnotationImpl extends TypeAnnotationImpl
+ implements FunctionTypeAnnotation {
+ @override
+ TypeAnnotationCode get code {
+ FunctionTypeAnnotationCode underlyingType = new FunctionTypeAnnotationCode(
+ returnType: returnType.code,
+ typeParameters: [
+ for (TypeParameterDeclaration typeParam in typeParameters)
+ typeParam.code,
+ ],
+ positionalParameters: [
+ for (ParameterDeclaration positional in positionalParameters)
+ positional.code,
+ ],
+ namedParameters: [
+ for (ParameterDeclaration named in namedParameters) named.code,
+ ],
+ );
+ return isNullable ? underlyingType.asNullable : underlyingType;
+ }
+
+ @override
+ final List<ParameterDeclarationImpl> namedParameters;
+
+ @override
+ final List<ParameterDeclarationImpl> positionalParameters;
+
+ @override
+ final TypeAnnotationImpl returnType;
+
+ @override
+ final List<TypeParameterDeclarationImpl> typeParameters;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.functionTypeAnnotation;
+
+ FunctionTypeAnnotationImpl({
+ required int id,
+ required bool isNullable,
+ required this.namedParameters,
+ required this.positionalParameters,
+ required this.returnType,
+ required this.typeParameters,
+ }) : super(id: id, isNullable: isNullable);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ returnType.serialize(serializer);
+
+ serializer.startList();
+ for (ParameterDeclarationImpl param in positionalParameters) {
+ param.serialize(serializer);
+ }
+ serializer.endList();
+
+ serializer.startList();
+ for (ParameterDeclarationImpl param in namedParameters) {
+ param.serialize(serializer);
+ }
+ serializer.endList();
+
+ serializer.startList();
+ for (TypeParameterDeclarationImpl typeParam in typeParameters) {
+ typeParam.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+abstract class DeclarationImpl extends RemoteInstance implements Declaration {
+ final IdentifierImpl identifier;
+
+ DeclarationImpl({required int id, required this.identifier}) : super(id);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ identifier.serialize(serializer);
+ }
+}
+
+class ParameterDeclarationImpl extends DeclarationImpl
+ implements ParameterDeclaration {
+ @override
+ final bool isNamed;
+
+ @override
+ final bool isRequired;
+
+ @override
+ final TypeAnnotationImpl type;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.parameterDeclaration;
+
+ ParameterDeclarationImpl({
+ required int id,
+ required IdentifierImpl identifier,
+ required this.isNamed,
+ required this.isRequired,
+ required this.type,
+ }) : super(id: id, identifier: identifier);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer.addBool(isNamed);
+ serializer.addBool(isRequired);
+ type.serialize(serializer);
+ }
+
+ @override
+ ParameterCode get code =>
+ new ParameterCode(name: identifier.name, type: type.code, keywords: [
+ if (isNamed && isRequired) 'required',
+ ]);
+}
+
+class TypeParameterDeclarationImpl extends DeclarationImpl
+ implements TypeParameterDeclaration {
+ @override
+ final TypeAnnotationImpl? bound;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
+
+ TypeParameterDeclarationImpl({
+ required int id,
+ required IdentifierImpl identifier,
+ required this.bound,
+ }) : super(id: id, identifier: identifier);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ TypeAnnotationImpl? bound = this.bound;
+ if (bound == null) {
+ serializer.addNull();
+ } else {
+ bound.serialize(serializer);
+ }
+ }
+
+ @override
+ TypeParameterCode get code =>
+ new TypeParameterCode(name: identifier.name, bound: bound?.code);
+}
+
+class FunctionDeclarationImpl extends DeclarationImpl
+ implements FunctionDeclaration {
+ @override
+ final bool isAbstract;
+
+ @override
+ final bool isExternal;
+
+ @override
+ final bool isGetter;
+
+ @override
+ final bool isOperator;
+
+ @override
+ final bool isSetter;
+
+ @override
+ final List<ParameterDeclarationImpl> namedParameters;
+
+ @override
+ final List<ParameterDeclarationImpl> positionalParameters;
+
+ @override
+ final TypeAnnotationImpl returnType;
+
+ @override
+ final List<TypeParameterDeclarationImpl> typeParameters;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.functionDeclaration;
+
+ FunctionDeclarationImpl({
+ required int id,
+ required IdentifierImpl identifier,
+ required this.isAbstract,
+ required this.isExternal,
+ required this.isGetter,
+ required this.isOperator,
+ required this.isSetter,
+ required this.namedParameters,
+ required this.positionalParameters,
+ required this.returnType,
+ required this.typeParameters,
+ }) : super(id: id, identifier: identifier);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer
+ ..addBool(isAbstract)
+ ..addBool(isExternal)
+ ..addBool(isGetter)
+ ..addBool(isOperator)
+ ..addBool(isSetter)
+ ..startList();
+ for (ParameterDeclarationImpl named in namedParameters) {
+ named.serialize(serializer);
+ }
+ serializer
+ ..endList()
+ ..startList();
+ for (ParameterDeclarationImpl positional in positionalParameters) {
+ positional.serialize(serializer);
+ }
+ serializer.endList();
+ returnType.serialize(serializer);
+ serializer.startList();
+ for (TypeParameterDeclarationImpl param in typeParameters) {
+ param.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+class MethodDeclarationImpl extends FunctionDeclarationImpl
+ implements MethodDeclaration {
+ @override
+ final IdentifierImpl definingClass;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.methodDeclaration;
+
+ @override
+ final bool isStatic;
+
+ MethodDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required IdentifierImpl identifier,
+ // Function fields
+ required bool isAbstract,
+ required bool isExternal,
+ required bool isGetter,
+ required bool isOperator,
+ required bool isSetter,
+ required List<ParameterDeclarationImpl> namedParameters,
+ required List<ParameterDeclarationImpl> positionalParameters,
+ required TypeAnnotationImpl returnType,
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // Method fields
+ required this.definingClass,
+ required this.isStatic,
+ }) : super(
+ id: id,
+ identifier: identifier,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ isGetter: isGetter,
+ isOperator: isOperator,
+ isSetter: isSetter,
+ namedParameters: namedParameters,
+ positionalParameters: positionalParameters,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ );
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ definingClass.serialize(serializer);
+ serializer.addBool(isStatic);
+ }
+}
+
+class ConstructorDeclarationImpl extends MethodDeclarationImpl
+ implements ConstructorDeclaration {
+ @override
+ final bool isFactory;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.constructorDeclaration;
+
+ ConstructorDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required IdentifierImpl identifier,
+ // Function fields
+ required bool isAbstract,
+ required bool isExternal,
+ required bool isGetter,
+ required bool isOperator,
+ required bool isSetter,
+ required List<ParameterDeclarationImpl> namedParameters,
+ required List<ParameterDeclarationImpl> positionalParameters,
+ required TypeAnnotationImpl returnType,
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // Method fields
+ required IdentifierImpl definingClass,
+ // Constructor fields
+ required this.isFactory,
+ }) : super(
+ id: id,
+ identifier: identifier,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ isGetter: isGetter,
+ isOperator: isOperator,
+ isSetter: isSetter,
+ namedParameters: namedParameters,
+ positionalParameters: positionalParameters,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ definingClass: definingClass,
+ isStatic: true,
+ );
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer.addBool(isFactory);
+ }
+}
+
+class VariableDeclarationImpl extends DeclarationImpl
+ implements VariableDeclaration {
+ @override
+ final bool isExternal;
+
+ @override
+ final bool isFinal;
+
+ @override
+ final bool isLate;
+
+ @override
+ final TypeAnnotationImpl type;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.variableDeclaration;
+
+ VariableDeclarationImpl({
+ required int id,
+ required IdentifierImpl identifier,
+ required this.isExternal,
+ required this.isFinal,
+ required this.isLate,
+ required this.type,
+ }) : super(id: id, identifier: identifier);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer
+ ..addBool(isExternal)
+ ..addBool(isFinal)
+ ..addBool(isLate);
+ type.serialize(serializer);
+ }
+}
+
+class FieldDeclarationImpl extends VariableDeclarationImpl
+ implements FieldDeclaration {
+ @override
+ final IdentifierImpl definingClass;
+
+ @override
+ final bool isStatic;
+
+ FieldDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required IdentifierImpl identifier,
+ // Variable fields
+ required bool isExternal,
+ required bool isFinal,
+ required bool isLate,
+ required TypeAnnotationImpl type,
+ // Field fields
+ required this.definingClass,
+ required this.isStatic,
+ }) : super(
+ id: id,
+ identifier: identifier,
+ isExternal: isExternal,
+ isFinal: isFinal,
+ isLate: isLate,
+ type: type);
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.fieldDeclaration;
+
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ definingClass.serialize(serializer);
+ serializer.addBool(isStatic);
+ }
+}
+
+abstract class TypeDeclarationImpl extends DeclarationImpl
+ implements TypeDeclaration {
+ @override
+ final List<TypeParameterDeclarationImpl> typeParameters;
+
+ TypeDeclarationImpl({
+ required int id,
+ required IdentifierImpl identifier,
+ required this.typeParameters,
+ }) : super(id: id, identifier: identifier);
+
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer..startList();
+ for (TypeParameterDeclarationImpl param in typeParameters) {
+ param.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+class ClassDeclarationImpl extends TypeDeclarationImpl
+ implements ClassDeclaration {
+ @override
+ final List<TypeAnnotationImpl> interfaces;
+
+ @override
+ final bool isAbstract;
+
+ @override
+ final bool isExternal;
+
+ @override
+ final List<TypeAnnotationImpl> mixins;
+
+ @override
+ final TypeAnnotationImpl? superclass;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.classDeclaration;
+
+ ClassDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required IdentifierImpl identifier,
+ // TypeDeclaration fields
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // ClassDeclaration fields
+ required this.interfaces,
+ required this.isAbstract,
+ required this.isExternal,
+ required this.mixins,
+ required this.superclass,
+ }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ serializer.startList();
+ for (TypeAnnotationImpl interface in interfaces) {
+ interface.serialize(serializer);
+ }
+ serializer
+ ..endList()
+ ..addBool(isAbstract)
+ ..addBool(isExternal)
+ ..startList();
+ for (TypeAnnotationImpl mixin in mixins) {
+ mixin.serialize(serializer);
+ }
+ serializer..endList();
+ superclass.serializeNullable(serializer);
+ }
+}
+
+class TypeAliasDeclarationImpl extends TypeDeclarationImpl
+ implements TypeAliasDeclaration {
+ /// The type being aliased.
+ final TypeAnnotationImpl aliasedType;
+
+ @override
+ RemoteInstanceKind get kind => RemoteInstanceKind.typeAliasDeclaration;
+
+ TypeAliasDeclarationImpl({
+ // Declaration fields
+ required int id,
+ required IdentifierImpl identifier,
+ // TypeDeclaration fields
+ required List<TypeParameterDeclarationImpl> typeParameters,
+ // TypeAlias fields
+ required this.aliasedType,
+ }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
+
+ @override
+ void serialize(Serializer serializer) {
+ super.serialize(serializer);
+ // Client side we don't encode anything but the ID.
+ if (serializationMode.isClient) return;
+
+ aliasedType.serialize(serializer);
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart
new file mode 100644
index 0000000..ae15038
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/isolated_executor.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import '../executor/multi_executor.dart';
+import '../executor/executor_base.dart';
+import '../executor/serialization.dart';
+import '../executor.dart';
+
+/// Returns a [MacroExecutor] which loads macros into isolates using precompiled
+/// kernel files and communicates with that isolate using [serializationMode].
+///
+/// The [serializationMode] must be a `server` variant, and any precompiled
+/// programs must use the corresponding `client` variant.
+///
+/// This is the only public api exposed by this library.
+Future<MacroExecutor> start(SerializationMode serializationMode) async =>
+ new MultiMacroExecutor((Uri library, String name,
+ {Uri? precompiledKernelUri}) {
+ if (precompiledKernelUri == null) {
+ throw new UnsupportedError(
+ 'This environment requires a non-null `precompiledKernelUri` to be '
+ 'passed when loading macros.');
+ }
+
+ return _SingleIsolatedMacroExecutor.start(
+ library, name, precompiledKernelUri, serializationMode);
+ });
+
+/// Actual implementation of the isolate based macro executor.
+class _SingleIsolatedMacroExecutor extends ExternalMacroExecutorBase {
+ /// The send port where we should send requests.
+ final SendPort sendPort;
+
+ /// A function that should be invoked when shutting down this executor
+ /// to perform any necessary cleanup.
+ final void Function() onClose;
+
+ _SingleIsolatedMacroExecutor(
+ {required Stream<Object> messageStream,
+ required this.onClose,
+ required this.sendPort,
+ required SerializationMode serializationMode})
+ : super(
+ messageStream: messageStream, serializationMode: serializationMode);
+
+ static Future<_SingleIsolatedMacroExecutor> start(Uri library, String name,
+ Uri precompiledKernelUri, SerializationMode serializationMode) async {
+ ReceivePort receivePort = new ReceivePort();
+ Isolate isolate =
+ await Isolate.spawnUri(precompiledKernelUri, [], receivePort.sendPort);
+ Completer<SendPort> sendPortCompleter = new Completer();
+ StreamController<Object> messageStreamController =
+ new StreamController(sync: true);
+ receivePort.listen((message) {
+ if (!sendPortCompleter.isCompleted) {
+ sendPortCompleter.complete(message as SendPort);
+ } else {
+ if (serializationMode == SerializationMode.byteDataServer) {
+ message =
+ (message as TransferableTypedData).materialize().asUint8List();
+ }
+ messageStreamController.add(message);
+ }
+ }).onDone(messageStreamController.close);
+
+ return new _SingleIsolatedMacroExecutor(
+ onClose: () {
+ receivePort.close();
+ isolate.kill();
+ },
+ messageStream: messageStreamController.stream,
+ sendPort: await sendPortCompleter.future,
+ serializationMode: serializationMode);
+ }
+
+ @override
+ void close() => onClose();
+
+ /// Sends the [Serializer.result] to [sendPort], possibly wrapping it in a
+ /// [TransferableTypedData] object.
+ void sendResult(Serializer serializer) {
+ if (serializationMode == SerializationMode.byteDataServer) {
+ sendPort.send(
+ new TransferableTypedData.fromList([serializer.result as Uint8List]));
+ } else {
+ sendPort.send(serializer.result);
+ }
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/message_grouper.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/message_grouper.dart
new file mode 100644
index 0000000..7e2d390
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/message_grouper.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:math';
+import 'dart:typed_data';
+
+/// Collects messages from an input stream of bytes.
+///
+/// Each message should start with a 32 bit big endian uint indicating its size,
+/// followed by that many bytes.
+class MessageGrouper {
+ /// The input bytes stream subscription.
+ late final StreamSubscription _inputStreamSubscription;
+
+ /// The length of the current message to read, or `-1` if we are currently
+ /// reading the length.
+ int _length = -1;
+
+ /// The buffer to store the length bytes in.
+ BytesBuilder _lengthBuffer = new BytesBuilder();
+
+ /// If reading raw data, buffer for the data.
+ Uint8List _messageBuffer = new Uint8List(0);
+
+ /// The position to write the next byte in [_messageBuffer].
+ int _messagePos = 0;
+
+ late StreamController<Uint8List> _messageStreamController =
+ new StreamController<Uint8List>(onCancel: () {
+ _inputStreamSubscription.cancel();
+ });
+ Stream<Uint8List> get messageStream => _messageStreamController.stream;
+
+ MessageGrouper(Stream<List<int>> inputStream) {
+ _inputStreamSubscription = inputStream.listen(_handleBytes, onDone: cancel);
+ }
+
+ void _handleBytes(List<int> bytes, [int offset = 0]) {
+ if (_length == -1) {
+ while (_lengthBuffer.length < 4 && offset < bytes.length) {
+ _lengthBuffer.addByte(bytes[offset++]);
+ }
+ if (_lengthBuffer.length >= 4) {
+ Uint8List lengthBytes = _lengthBuffer.takeBytes();
+ _length = lengthBytes[0] << 24 |
+ lengthBytes[1] << 16 |
+ lengthBytes[2] << 8 |
+ lengthBytes[3];
+ }
+ }
+
+ // Just pass along `bytes` without a copy if we can, and reset our state
+ if (offset == 0 && bytes.length == _length && bytes is Uint8List) {
+ _length = -1;
+ _messageStreamController.add(bytes);
+ return;
+ }
+
+ // Initialize a new buffer.
+ if (_messagePos == 0) {
+ _messageBuffer = new Uint8List(_length);
+ }
+
+ // Read the data from `bytes`.
+ int lenToRead = min(_length - _messagePos, bytes.length - offset);
+ while (lenToRead-- > 0) {
+ _messageBuffer[_messagePos++] = bytes[offset++];
+ }
+
+ // If we completed a message, add it to the output stream, reset our state,
+ // and call ourselves again if we have more data to read.
+ if (_messagePos >= _length) {
+ _messageStreamController.add(_messageBuffer);
+ _length = -1;
+ _messagePos = 0;
+
+ if (offset < bytes.length) {
+ _handleBytes(bytes, offset);
+ }
+ }
+ }
+
+ /// Stop listening to the input stream for further updates, and close the
+ /// output stream.
+ void cancel() {
+ _inputStreamSubscription.cancel();
+ _messageStreamController.close();
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart
new file mode 100644
index 0000000..aa7c907
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/multi_executor.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import '../api.dart';
+import '../executor/augmentation_library.dart';
+import '../executor/introspection_impls.dart';
+import '../executor/response_impls.dart';
+import '../executor.dart';
+
+/// A [MacroExecutor] implementation which delegates most work to other
+/// executors which are spawned through a provided callback.
+class MultiMacroExecutor extends MacroExecutor with AugmentationLibraryBuilder {
+ /// Individual executors indexed by [MacroClassIdentifier] or
+ /// [MacroInstanceIdentifier].
+ final _executors = <Object, MacroExecutor>{};
+
+ /// The function to spawn an actual macro executor for a given [loadMacro]
+ /// request.
+ final Future<MacroExecutor> Function(Uri library, String name,
+ {Uri? precompiledKernelUri}) _spawnExecutor;
+
+ MultiMacroExecutor(this._spawnExecutor);
+
+ @override
+ void close() {
+ for (MacroExecutor executor in _executors.values) {
+ executor.close();
+ }
+ _executors.clear();
+ }
+
+ @override
+ Future<MacroExecutionResult> executeDeclarationsPhase(
+ MacroInstanceIdentifier macro,
+ DeclarationImpl declaration,
+ IdentifierResolver identifierResolver,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector) =>
+ _executors[macro]!.executeDeclarationsPhase(macro, declaration,
+ identifierResolver, typeResolver, classIntrospector);
+
+ @override
+ Future<MacroExecutionResult> executeDefinitionsPhase(
+ MacroInstanceIdentifier macro,
+ DeclarationImpl declaration,
+ IdentifierResolver identifierResolver,
+ TypeResolver typeResolver,
+ ClassIntrospector classIntrospector,
+ TypeDeclarationResolver typeDeclarationResolver) =>
+ _executors[macro]!.executeDefinitionsPhase(
+ macro,
+ declaration,
+ identifierResolver,
+ typeResolver,
+ classIntrospector,
+ typeDeclarationResolver);
+
+ @override
+ Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
+ DeclarationImpl declaration, IdentifierResolver identifierResolver) =>
+ _executors[macro]!
+ .executeTypesPhase(macro, declaration, identifierResolver);
+
+ @override
+ Future<MacroInstanceIdentifier> instantiateMacro(
+ MacroClassIdentifier macroClass,
+ String constructor,
+ Arguments arguments) async {
+ MacroExecutor executor = _executors[macroClass]!;
+ MacroInstanceIdentifier instance =
+ await executor.instantiateMacro(macroClass, constructor, arguments);
+ _executors[instance] = executor;
+ return instance;
+ }
+
+ @override
+ Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+ {Uri? precompiledKernelUri}) async {
+ MacroClassIdentifier identifier =
+ new MacroClassIdentifierImpl(library, name);
+ _executors.remove(identifier)?.close();
+
+ MacroExecutor executor = await _spawnExecutor(library, name,
+ precompiledKernelUri: precompiledKernelUri);
+ _executors[identifier] = executor;
+ return identifier;
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
new file mode 100644
index 0000000..ed67219
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/process_executor.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart';
+
+import '../executor/message_grouper.dart';
+import '../executor/multi_executor.dart';
+import '../executor/executor_base.dart';
+import '../executor/serialization.dart';
+import '../executor.dart';
+
+/// Returns a [MacroExecutor] which loads macros as separate processes using
+/// precompiled binaries and communicates with that program using
+/// [serializationMode].
+///
+/// The [serializationMode] must be a `server` variant, and any precompiled
+/// programs spawned must use the corresponding `client` variant.
+///
+/// This is the only public api exposed by this library.
+Future<MacroExecutor> start(SerializationMode serializationMode) async =>
+ new MultiMacroExecutor((Uri library, String name,
+ {Uri? precompiledKernelUri}) {
+ if (precompiledKernelUri == null) {
+ throw new UnsupportedError(
+ 'This environment requires a non-null `precompiledKernelUri` to be '
+ 'passed when loading macros.');
+ }
+
+ // TODO: We actually assume this is a full precompiled AOT binary, and not
+ // a kernel file. We launch it directly using `Process.start`.
+ return _SingleProcessMacroExecutor.start(
+ library, name, serializationMode, precompiledKernelUri.toFilePath());
+ });
+
+/// Actual implementation of the separate process based macro executor.
+class _SingleProcessMacroExecutor extends ExternalMacroExecutorBase {
+ /// The IOSink that writes to stdin of the external process.
+ final IOSink outSink;
+
+ /// A function that should be invoked when shutting down this executor
+ /// to perform any necessary cleanup.
+ final void Function() onClose;
+
+ _SingleProcessMacroExecutor(
+ {required Stream<Object> messageStream,
+ required this.onClose,
+ required this.outSink,
+ required SerializationMode serializationMode})
+ : super(
+ messageStream: messageStream, serializationMode: serializationMode);
+
+ static Future<_SingleProcessMacroExecutor> start(Uri library, String name,
+ SerializationMode serializationMode, String programPath) async {
+ Process process = await Process.start(programPath, []);
+ process.stderr
+ .transform(const Utf8Decoder())
+ .listen((content) => throw new RemoteException(content));
+
+ Stream<Object> messageStream;
+
+ if (serializationMode == SerializationMode.byteDataServer) {
+ messageStream = new MessageGrouper(process.stdout).messageStream;
+ } else if (serializationMode == SerializationMode.jsonServer) {
+ messageStream = process.stdout
+ .transform(const Utf8Decoder())
+ .transform(const LineSplitter())
+ .map((line) => jsonDecode(line)!);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode \$serializationMode for '
+ 'ProcessExecutor');
+ }
+
+ return new _SingleProcessMacroExecutor(
+ onClose: () {
+ process.kill();
+ },
+ messageStream: messageStream,
+ outSink: process.stdin,
+ serializationMode: serializationMode);
+ }
+
+ @override
+ void close() => onClose();
+
+ /// Sends the [Serializer.result] to [stdin].
+ ///
+ /// Json results are serialized to a `String`, and separated by newlines.
+ void sendResult(Serializer serializer) {
+ if (serializationMode == SerializationMode.jsonServer) {
+ outSink.writeln(jsonEncode(serializer.result));
+ } else if (serializationMode == SerializationMode.byteDataServer) {
+ Uint8List result = (serializer as ByteDataSerializer).result;
+ int length = result.lengthInBytes;
+ if (length > 0xffffffff) {
+ throw new StateError('Message was larger than the allowed size!');
+ }
+ outSink.add([
+ length >> 24 & 0xff,
+ length >> 16 & 0xff,
+ length >> 8 & 0xff,
+ length & 0xff
+ ]);
+ outSink.add(result);
+ } else {
+ throw new UnsupportedError(
+ 'Unsupported serialization mode $serializationMode for '
+ 'ProcessExecutor');
+ }
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart
new file mode 100644
index 0000000..73d051c6
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/protocol.dart
@@ -0,0 +1,786 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Defines the objects used for communication between the macro executor and
+/// the isolate or process doing the work of macro loading and execution.
+library _fe_analyzer_shared.src.macros.executor_shared.protocol;
+
+import 'package:meta/meta.dart';
+
+import '../executor.dart';
+import '../api.dart';
+import '../executor/response_impls.dart';
+import 'introspection_impls.dart';
+import 'remote_instance.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// Base class all requests extend, provides a unique id for each request.
+abstract class Request implements Serializable {
+ final int id;
+
+ final int serializationZoneId;
+
+ Request({int? id, required this.serializationZoneId})
+ : this.id = id ?? _next++;
+
+ /// The [serializationZoneId] is a part of the header and needs to be parsed
+ /// before deserializing objects, and then passed in here.
+ Request.deserialize(Deserializer deserializer, this.serializationZoneId)
+ : id = (deserializer..moveNext()).expectInt();
+
+ /// The [serializationZoneId] needs to be separately serialized before the
+ /// rest of the object. This is not done by the instances themselves but by
+ /// the macro implementations.
+ @mustCallSuper
+ void serialize(Serializer serializer) => serializer.addInt(id);
+
+ static int _next = 0;
+}
+
+/// A generic response object that contains either a response or an error, and
+/// a unique ID.
+class Response {
+ final Object? response;
+ final Object? error;
+ final String? stackTrace;
+ final int requestId;
+ final MessageType responseType;
+
+ Response({
+ this.response,
+ this.error,
+ this.stackTrace,
+ required this.requestId,
+ required this.responseType,
+ }) : assert(response != null || error != null),
+ assert(response == null || error == null);
+}
+
+/// A serializable [Response], contains the message type as an enum.
+class SerializableResponse implements Response, Serializable {
+ final Serializable? response;
+ final MessageType responseType;
+ final String? error;
+ final String? stackTrace;
+ final int requestId;
+ final int serializationZoneId;
+
+ SerializableResponse({
+ this.error,
+ this.stackTrace,
+ required this.requestId,
+ this.response,
+ required this.responseType,
+ required this.serializationZoneId,
+ });
+
+ /// You must first parse the [serializationZoneId] yourself, and then
+ /// call this function in that zone, and pass the ID.
+ factory SerializableResponse.deserialize(
+ Deserializer deserializer, int serializationZoneId) {
+ deserializer.moveNext();
+ MessageType responseType = MessageType.values[deserializer.expectInt()];
+ Serializable? response;
+ String? error;
+ String? stackTrace;
+ switch (responseType) {
+ case MessageType.error:
+ deserializer.moveNext();
+ error = deserializer.expectString();
+ deserializer.moveNext();
+ stackTrace = deserializer.expectNullableString();
+ break;
+ case MessageType.macroClassIdentifier:
+ response = new MacroClassIdentifierImpl.deserialize(deserializer);
+ break;
+ case MessageType.macroInstanceIdentifier:
+ response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
+ break;
+ case MessageType.macroExecutionResult:
+ response = new MacroExecutionResultImpl.deserialize(deserializer);
+ break;
+ case MessageType.staticType:
+ case MessageType.namedStaticType:
+ response = RemoteInstance.deserialize(deserializer);
+ break;
+ case MessageType.boolean:
+ response = new BooleanValue.deserialize(deserializer);
+ break;
+ case MessageType.declarationList:
+ response = new DeclarationList.deserialize(deserializer);
+ break;
+ case MessageType.remoteInstance:
+ deserializer.moveNext();
+ if (!deserializer.checkNull()) {
+ response = deserializer.expectRemoteInstance();
+ }
+ break;
+ default:
+ throw new StateError('Unexpected response type $responseType');
+ }
+
+ return new SerializableResponse(
+ responseType: responseType,
+ response: response,
+ error: error,
+ stackTrace: stackTrace,
+ requestId: (deserializer..moveNext()).expectInt(),
+ serializationZoneId: serializationZoneId);
+ }
+
+ void serialize(Serializer serializer) {
+ serializer
+ ..addInt(serializationZoneId)
+ ..addInt(MessageType.response.index)
+ ..addInt(responseType.index);
+ switch (responseType) {
+ case MessageType.error:
+ serializer.addString(error!.toString());
+ serializer.addNullableString(stackTrace);
+ break;
+ default:
+ response.serializeNullable(serializer);
+ }
+ serializer.addInt(requestId);
+ }
+}
+
+class BooleanValue implements Serializable {
+ final bool value;
+
+ BooleanValue(this.value);
+
+ BooleanValue.deserialize(Deserializer deserializer)
+ : value = (deserializer..moveNext()).expectBool();
+
+ @override
+ void serialize(Serializer serializer) => serializer..addBool(value);
+}
+
+/// A serialized list of [Declaration]s.
+class DeclarationList<T extends DeclarationImpl> implements Serializable {
+ final List<T> declarations;
+
+ DeclarationList(this.declarations);
+
+ DeclarationList.deserialize(Deserializer deserializer)
+ : declarations = [
+ for (bool hasNext = (deserializer
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNext;
+ hasNext = deserializer.moveNext())
+ deserializer.expectRemoteInstance(),
+ ];
+
+ @override
+ void serialize(Serializer serializer) {
+ serializer.startList();
+ for (DeclarationImpl declaration in declarations) {
+ declaration.serialize(serializer);
+ }
+ serializer.endList();
+ }
+}
+
+/// A request to load a macro in this isolate.
+class LoadMacroRequest extends Request {
+ final Uri library;
+ final String name;
+
+ LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ LoadMacroRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : library = Uri.parse((deserializer..moveNext()).expectString()),
+ name = (deserializer..moveNext()).expectString(),
+ super.deserialize(deserializer, serializationZoneId);
+
+ @override
+ void serialize(Serializer serializer) {
+ serializer
+ ..addInt(MessageType.loadMacroRequest.index)
+ ..addString(library.toString())
+ ..addString(name);
+ super.serialize(serializer);
+ }
+}
+
+/// A request to instantiate a macro instance.
+class InstantiateMacroRequest extends Request {
+ final MacroClassIdentifier macroClass;
+ final String constructorName;
+ final Arguments arguments;
+
+ /// The ID to assign to the identifier, this needs to come from the requesting
+ /// side so that it is unique.
+ final int instanceId;
+
+ InstantiateMacroRequest(
+ this.macroClass, this.constructorName, this.arguments, this.instanceId,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ InstantiateMacroRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
+ constructorName = (deserializer..moveNext()).expectString(),
+ arguments = new Arguments.deserialize(deserializer),
+ instanceId = (deserializer..moveNext()).expectInt(),
+ super.deserialize(deserializer, serializationZoneId);
+
+ @override
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.instantiateMacroRequest.index);
+ macroClass.serialize(serializer);
+ serializer.addString(constructorName);
+ arguments.serialize(serializer);
+ serializer.addInt(instanceId);
+ super.serialize(serializer);
+ }
+}
+
+/// A request to execute a macro on a particular declaration in the types phase.
+class ExecuteTypesPhaseRequest extends Request {
+ final MacroInstanceIdentifier macro;
+ final DeclarationImpl declaration;
+ final RemoteInstanceImpl identifierResolver;
+
+ ExecuteTypesPhaseRequest(
+ this.macro, this.declaration, this.identifierResolver,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ ExecuteTypesPhaseRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+ declaration = RemoteInstance.deserialize(deserializer),
+ identifierResolver = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.executeTypesPhaseRequest.index);
+ macro.serialize(serializer);
+ declaration.serialize(serializer);
+ identifierResolver.serialize(serializer);
+
+ super.serialize(serializer);
+ }
+}
+
+/// A request to execute a macro on a particular declaration in the definition
+/// phase.
+class ExecuteDeclarationsPhaseRequest extends Request {
+ final MacroInstanceIdentifier macro;
+ final DeclarationImpl declaration;
+
+ final RemoteInstanceImpl identifierResolver;
+ final RemoteInstanceImpl typeResolver;
+ final RemoteInstanceImpl classIntrospector;
+
+ ExecuteDeclarationsPhaseRequest(this.macro, this.declaration,
+ this.identifierResolver, this.typeResolver, this.classIntrospector,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ ExecuteDeclarationsPhaseRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+ declaration = RemoteInstance.deserialize(deserializer),
+ identifierResolver = RemoteInstance.deserialize(deserializer),
+ typeResolver = RemoteInstance.deserialize(deserializer),
+ classIntrospector = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.executeDeclarationsPhaseRequest.index);
+ macro.serialize(serializer);
+ declaration.serialize(serializer);
+ identifierResolver.serialize(serializer);
+ typeResolver.serialize(serializer);
+ classIntrospector.serialize(serializer);
+
+ super.serialize(serializer);
+ }
+}
+
+/// A request to execute a macro on a particular declaration in the definition
+/// phase.
+class ExecuteDefinitionsPhaseRequest extends Request {
+ final MacroInstanceIdentifier macro;
+ final DeclarationImpl declaration;
+
+ final RemoteInstanceImpl identifierResolver;
+ final RemoteInstanceImpl typeResolver;
+ final RemoteInstanceImpl classIntrospector;
+ final RemoteInstanceImpl typeDeclarationResolver;
+
+ ExecuteDefinitionsPhaseRequest(
+ this.macro,
+ this.declaration,
+ this.identifierResolver,
+ this.typeResolver,
+ this.classIntrospector,
+ this.typeDeclarationResolver,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ ExecuteDefinitionsPhaseRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+ declaration = RemoteInstance.deserialize(deserializer),
+ identifierResolver = RemoteInstance.deserialize(deserializer),
+ typeResolver = RemoteInstance.deserialize(deserializer),
+ classIntrospector = RemoteInstance.deserialize(deserializer),
+ typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.executeDefinitionsPhaseRequest.index);
+ macro.serialize(serializer);
+ declaration.serialize(serializer);
+ identifierResolver.serialize(serializer);
+ typeResolver.serialize(serializer);
+ classIntrospector.serialize(serializer);
+ typeDeclarationResolver.serialize(serializer);
+
+ super.serialize(serializer);
+ }
+}
+
+/// A request to create a resolved identifier.
+class ResolveIdentifierRequest extends Request {
+ final Uri library;
+ final String name;
+
+ final RemoteInstanceImpl identifierResolver;
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ ResolveIdentifierRequest(this.library, this.name, this.identifierResolver,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ ResolveIdentifierRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : library = Uri.parse((deserializer..moveNext()).expectString()),
+ name = (deserializer..moveNext()).expectString(),
+ identifierResolver = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer
+ ..addInt(MessageType.resolveIdentifierRequest.index)
+ ..addString(library.toString())
+ ..addString(name);
+ identifierResolver.serialize(serializer);
+
+ super.serialize(serializer);
+ }
+}
+
+/// A request to resolve on a type annotation code object
+class ResolveTypeRequest extends Request {
+ final TypeAnnotationCode typeAnnotationCode;
+ final RemoteInstanceImpl typeResolver;
+
+ ResolveTypeRequest(this.typeAnnotationCode, this.typeResolver,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ ResolveTypeRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : typeAnnotationCode = (deserializer..moveNext()).expectCode(),
+ typeResolver = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.resolveTypeRequest.index);
+ typeAnnotationCode.serialize(serializer);
+ typeResolver.serialize(serializer);
+ super.serialize(serializer);
+ }
+}
+
+/// A request to check if a type is exactly another type.
+class IsExactlyTypeRequest extends Request {
+ final RemoteInstanceImpl leftType;
+ final RemoteInstanceImpl rightType;
+
+ IsExactlyTypeRequest(this.leftType, this.rightType,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ IsExactlyTypeRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : leftType = RemoteInstance.deserialize(deserializer),
+ rightType = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.isExactlyTypeRequest.index);
+ leftType.serialize(serializer);
+ rightType.serialize(serializer);
+ super.serialize(serializer);
+ }
+}
+
+/// A request to check if a type is exactly another type.
+class IsSubtypeOfRequest extends Request {
+ final RemoteInstanceImpl leftType;
+ final RemoteInstanceImpl rightType;
+
+ IsSubtypeOfRequest(this.leftType, this.rightType,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ IsSubtypeOfRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : leftType = RemoteInstance.deserialize(deserializer),
+ rightType = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.isSubtypeOfRequest.index);
+ leftType.serialize(serializer);
+ rightType.serialize(serializer);
+ super.serialize(serializer);
+ }
+}
+
+/// A general request class for all requests coming from methods on the
+/// [ClassIntrospector] interface.
+class ClassIntrospectionRequest extends Request {
+ final ClassDeclarationImpl classDeclaration;
+ final RemoteInstanceImpl classIntrospector;
+ final MessageType requestKind;
+
+ ClassIntrospectionRequest(
+ this.classDeclaration, this.classIntrospector, this.requestKind,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again and it should instead be passed in here.
+ ClassIntrospectionRequest.deserialize(
+ Deserializer deserializer, this.requestKind, int serializationZoneId)
+ : classDeclaration = RemoteInstance.deserialize(deserializer),
+ classIntrospector = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ @override
+ void serialize(Serializer serializer) {
+ serializer.addInt(requestKind.index);
+ classDeclaration.serialize(serializer);
+ classIntrospector.serialize(serializer);
+ super.serialize(serializer);
+ }
+}
+
+/// A request to get a [TypeDeclaration] for a [StaticType].
+class DeclarationOfRequest extends Request {
+ final IdentifierImpl identifier;
+ final RemoteInstanceImpl typeDeclarationResolver;
+
+ DeclarationOfRequest(this.identifier, this.typeDeclarationResolver,
+ {required int serializationZoneId})
+ : super(serializationZoneId: serializationZoneId);
+
+ /// When deserializing we have already consumed the message type, so we don't
+ /// consume it again.
+ DeclarationOfRequest.deserialize(
+ Deserializer deserializer, int serializationZoneId)
+ : identifier = RemoteInstance.deserialize(deserializer),
+ typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
+ super.deserialize(deserializer, serializationZoneId);
+
+ @override
+ void serialize(Serializer serializer) {
+ serializer.addInt(MessageType.declarationOfRequest.index);
+ identifier.serialize(serializer);
+ typeDeclarationResolver.serialize(serializer);
+ super.serialize(serializer);
+ }
+}
+
+/// Client side implementation of an [IdentifierResolver], which creates a
+/// [ResolveIdentifierRequest] and passes it to a given [sendRequest] function
+/// which can return the [Response].
+class ClientIdentifierResolver implements IdentifierResolver {
+ /// The actual remote instance of this type resolver.
+ final RemoteInstanceImpl remoteInstance;
+
+ /// The ID of the zone in which to find the original type resolver.
+ final int serializationZoneId;
+
+ /// A function that can send a request and return a response using an
+ /// arbitrary communication channel.
+ final Future<Response> Function(Request request) _sendRequest;
+
+ ClientIdentifierResolver(this._sendRequest,
+ {required this.remoteInstance, required this.serializationZoneId});
+
+ @override
+ Future<Identifier> resolveIdentifier(Uri library, String name) async {
+ ResolveIdentifierRequest request = new ResolveIdentifierRequest(
+ library, name, remoteInstance,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse(await _sendRequest(request));
+ }
+}
+
+/// Client side implementation of a [TypeResolver], which creates a
+/// [ResolveTypeRequest] and passes it to a given [sendRequest] function which
+/// can return the [Response].
+class ClientTypeResolver implements TypeResolver {
+ /// The actual remote instance of this type resolver.
+ final RemoteInstanceImpl remoteInstance;
+
+ /// The ID of the zone in which to find the original type resolver.
+ final int serializationZoneId;
+
+ /// A function that can send a request and return a response using an
+ /// arbitrary communication channel.
+ final Future<Response> Function(Request request) _sendRequest;
+
+ ClientTypeResolver(this._sendRequest,
+ {required this.remoteInstance, required this.serializationZoneId});
+
+ @override
+ Future<StaticType> resolve(TypeAnnotationCode typeAnnotation) async {
+ ResolveTypeRequest request = new ResolveTypeRequest(
+ typeAnnotation, remoteInstance,
+ serializationZoneId: serializationZoneId);
+ RemoteInstanceImpl remoteType =
+ _handleResponse(await _sendRequest(request));
+ switch (remoteType.kind) {
+ case RemoteInstanceKind.namedStaticType:
+ return new ClientNamedStaticTypeImpl(_sendRequest,
+ remoteInstance: remoteType,
+ serializationZoneId: serializationZoneId);
+ case RemoteInstanceKind.staticType:
+ return new ClientStaticTypeImpl(_sendRequest,
+ remoteInstance: remoteType,
+ serializationZoneId: serializationZoneId);
+ default:
+ throw new StateError(
+ 'Expected either a StaticType or NamedStaticType but got '
+ '${remoteType.kind}');
+ }
+ }
+}
+
+class ClientStaticTypeImpl implements StaticType {
+ /// The actual remote instance of this static type.
+ final RemoteInstanceImpl remoteInstance;
+
+ final int serializationZoneId;
+
+ /// A function that can send a request and return a response using an
+ /// arbitrary communication channel.
+ final Future<Response> Function(Request request) sendRequest;
+
+ ClientStaticTypeImpl(this.sendRequest,
+ {required this.remoteInstance, required this.serializationZoneId});
+
+ @override
+ Future<bool> isExactly(ClientStaticTypeImpl other) async {
+ IsExactlyTypeRequest request = new IsExactlyTypeRequest(
+ this.remoteInstance, other.remoteInstance,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<BooleanValue>(await sendRequest(request)).value;
+ }
+
+ @override
+ Future<bool> isSubtypeOf(ClientStaticTypeImpl other) async {
+ IsSubtypeOfRequest request = new IsSubtypeOfRequest(
+ remoteInstance, other.remoteInstance,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<BooleanValue>(await sendRequest(request)).value;
+ }
+}
+
+/// Named variant of the [ClientStaticTypeImpl].
+class ClientNamedStaticTypeImpl extends ClientStaticTypeImpl
+ implements NamedStaticType {
+ ClientNamedStaticTypeImpl(
+ Future<Response> Function(Request request) sendRequest,
+ {required RemoteInstanceImpl remoteInstance,
+ required int serializationZoneId})
+ : super(sendRequest,
+ remoteInstance: remoteInstance,
+ serializationZoneId: serializationZoneId);
+}
+
+/// Client side implementation of the [ClientClassIntrospector], converts all
+/// invocations into remote RPC calls.
+class ClientClassIntrospector implements ClassIntrospector {
+ /// The actual remote instance of this class introspector.
+ final RemoteInstanceImpl remoteInstance;
+
+ /// The ID of the zone in which to find the original type resolver.
+ final int serializationZoneId;
+
+ /// A function that can send a request and return a response using an
+ /// arbitrary communication channel.
+ final Future<Response> Function(Request request) sendRequest;
+
+ ClientClassIntrospector(this.sendRequest,
+ {required this.remoteInstance, required this.serializationZoneId});
+
+ @override
+ Future<List<ConstructorDeclaration>> constructorsOf(
+ ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.constructorsOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<DeclarationList>(await sendRequest(request))
+ .declarations
+ // TODO: Refactor so we can remove this cast
+ .cast();
+ }
+
+ @override
+ Future<List<FieldDeclaration>> fieldsOf(ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.fieldsOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<DeclarationList>(await sendRequest(request))
+ .declarations
+ // TODO: Refactor so we can remove this cast
+ .cast();
+ }
+
+ @override
+ Future<List<ClassDeclaration>> interfacesOf(
+ ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.interfacesOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<DeclarationList>(await sendRequest(request))
+ .declarations
+ // TODO: Refactor so we can remove this cast
+ .cast();
+ }
+
+ @override
+ Future<List<MethodDeclaration>> methodsOf(ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.methodsOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<DeclarationList>(await sendRequest(request))
+ .declarations
+ // TODO: Refactor so we can remove this cast
+ .cast();
+ }
+
+ @override
+ Future<List<ClassDeclaration>> mixinsOf(ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.mixinsOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<DeclarationList>(await sendRequest(request))
+ .declarations
+ // TODO: Refactor so we can remove this cast
+ .cast();
+ }
+
+ @override
+ Future<ClassDeclaration?> superclassOf(ClassDeclarationImpl clazz) async {
+ ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+ clazz, remoteInstance, MessageType.superclassOfRequest,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<ClassDeclaration?>(await sendRequest(request));
+ }
+}
+
+/// Client side implementation of a [TypeDeclarationResolver], converts all
+/// invocations into remote procedure calls.
+class ClientTypeDeclarationResolver implements TypeDeclarationResolver {
+ /// The actual remote instance of this type resolver.
+ final RemoteInstanceImpl remoteInstance;
+
+ /// The ID of the zone in which to find the original type resolver.
+ final int serializationZoneId;
+
+ /// A function that can send a request and return a response using an
+ /// arbitrary communication channel.
+ final Future<Response> Function(Request request) sendRequest;
+
+ ClientTypeDeclarationResolver(this.sendRequest,
+ {required this.remoteInstance, required this.serializationZoneId});
+
+ @override
+ Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) async {
+ DeclarationOfRequest request = new DeclarationOfRequest(
+ identifier, remoteInstance,
+ serializationZoneId: serializationZoneId);
+ return _handleResponse<TypeDeclaration>(await sendRequest(request));
+ }
+}
+
+/// An exception that occurred remotely, the exception object and stack trace
+/// are serialized as [String]s and both included in the [toString] output.
+class RemoteException implements Exception {
+ final String error;
+ final String? stackTrace;
+
+ RemoteException(this.error, [this.stackTrace]);
+
+ String toString() =>
+ 'RemoteException: $error${stackTrace == null ? '' : '\n\n$stackTrace'}';
+}
+
+/// Either returns the actual response from [response], casted to [T], or throws
+/// a [RemoteException] with the given error and stack trace.
+T _handleResponse<T>(Response response) {
+ if (response.responseType == MessageType.error) {
+ throw new RemoteException(response.error!.toString(), response.stackTrace);
+ }
+ return response.response as T;
+}
+
+enum MessageType {
+ boolean,
+ constructorsOfRequest,
+ declarationOfRequest,
+ declarationList,
+ fieldsOfRequest,
+ interfacesOfRequest,
+ methodsOfRequest,
+ mixinsOfRequest,
+ superclassOfRequest,
+ error,
+ executeDeclarationsPhaseRequest,
+ executeDefinitionsPhaseRequest,
+ executeTypesPhaseRequest,
+ instantiateMacroRequest,
+ resolveIdentifierRequest,
+ resolveTypeRequest,
+ isExactlyTypeRequest,
+ isSubtypeOfRequest,
+ loadMacroRequest,
+ remoteInstance,
+ macroClassIdentifier,
+ macroInstanceIdentifier,
+ macroExecutionResult,
+ namedStaticType,
+ response,
+ staticType,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart
new file mode 100644
index 0000000..fc45704
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/remote_instance.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:meta/meta.dart';
+
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// The key used to store the remote instance cache in the current serialization
+/// zone (in server mode only).
+const Symbol remoteInstanceZoneKey = #remoteInstanceCache;
+
+/// On the server side we keep track of remote instances by their ID.
+///
+/// These are a part of the current serialization zone, which all serialization
+/// and deserialization must be done in.
+///
+/// This means the cache lifetime is that of the serialization zone it is run
+/// in.
+Map<int, RemoteInstance> get _remoteInstanceCache =>
+ Zone.current[remoteInstanceZoneKey];
+
+/// Base class for types that need to be able to be traced back to a specific
+/// instance on the server side.
+abstract class RemoteInstance implements Serializable {
+ /// The unique ID for this instance.
+ final int id;
+
+ /// The type of instance being encoded.
+ RemoteInstanceKind get kind;
+
+ /// Static, incrementing ids.
+ static int _nextId = 0;
+
+ /// Gets the next unique identifier.
+ static int get uniqueId => _nextId++;
+
+ /// On the client side [id]s are given and you should reconstruct objects with
+ /// the given ID. On the server side ids should be created using
+ /// [RemoteInstance.uniqueId].
+ RemoteInstance(this.id);
+
+ /// Retrieves a cached instance by ID.
+ static T cached<T>(int id) => _remoteInstanceCache[id] as T;
+
+ /// Deserializes an instance based on the current [serializationMode].
+ static T deserialize<T>(Deserializer deserializer) =>
+ (deserializer..moveNext()).expectRemoteInstance();
+
+ /// This method should be overridden by all subclasses, which should on their
+ /// first line call this super function.
+ ///
+ /// They should then return immediately if [serializationMode] is
+ /// [SerializationMode.client], so that only an ID is sent.
+ @mustCallSuper
+ void serialize(Serializer serializer) {
+ serializer.addInt(id);
+ // We only send the ID from the client side.
+ if (serializationMode.isClient) return;
+
+ serializer.addInt(kind.index);
+ _remoteInstanceCache[id] = this;
+ }
+
+ @override
+ bool operator ==(Object other) => other is RemoteInstance && id == other.id;
+}
+
+/// A remote instance which is just a pointer to some server side instance of
+/// a generic object.
+///
+/// The wrapped object is not serialized.
+class RemoteInstanceImpl extends RemoteInstance {
+ /// Always null on the client side, has an actual instance on the server side.
+ final Object? instance;
+
+ @override
+ final RemoteInstanceKind kind;
+
+ RemoteInstanceImpl({
+ required int id,
+ this.instance,
+ required this.kind,
+ }) : super(id);
+}
+
+// The kinds of instances.
+enum RemoteInstanceKind {
+ classDeclaration,
+ classIntrospector,
+ constructorDeclaration,
+ fieldDeclaration,
+ functionDeclaration,
+ functionTypeAnnotation,
+ identifier,
+ identifierResolver,
+ namedStaticType,
+ methodDeclaration,
+ namedTypeAnnotation,
+ parameterDeclaration,
+ staticType,
+ typeAliasDeclaration,
+ typeParameterDeclaration,
+ typeResolver,
+ typeDeclarationResolver,
+ variableDeclaration,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
new file mode 100644
index 0000000..eedc0bc
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
@@ -0,0 +1,289 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../executor.dart';
+import '../api.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// Implementation of [MacroClassIdentifier].
+class MacroClassIdentifierImpl implements MacroClassIdentifier {
+ final String id;
+
+ MacroClassIdentifierImpl(Uri library, String name) : id = '$library#$name';
+
+ MacroClassIdentifierImpl.deserialize(Deserializer deserializer)
+ : id = (deserializer..moveNext()).expectString();
+
+ void serialize(Serializer serializer) => serializer.addString(id);
+
+ operator ==(other) => other is MacroClassIdentifierImpl && id == other.id;
+
+ int get hashCode => id.hashCode;
+}
+
+/// Implementation of [MacroInstanceIdentifier].
+class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
+ /// Unique identifier for this instance, passed in from the server.
+ final int id;
+
+ /// A single int where each bit indicates whether a specific macro interface
+ /// is implemented by this macro.
+ final int _interfaces;
+
+ MacroInstanceIdentifierImpl._(this.id, this._interfaces);
+
+ factory MacroInstanceIdentifierImpl(Macro macro, int instanceId) {
+ // Build up the interfaces value, there is a bit for each declaration/phase
+ // combination (as there is an interface for each).
+ int interfaces = 0;
+ for (DeclarationKind declarationKind in DeclarationKind.values) {
+ for (Phase phase in Phase.values) {
+ int interfaceMask = _interfaceMask(declarationKind, phase);
+ switch (declarationKind) {
+ case DeclarationKind.clazz:
+ switch (phase) {
+ case Phase.types:
+ if (macro is ClassTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is ClassDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is ClassDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ case DeclarationKind.constructor:
+ switch (phase) {
+ case Phase.types:
+ if (macro is ConstructorTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is ConstructorDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is ConstructorDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ case DeclarationKind.field:
+ switch (phase) {
+ case Phase.types:
+ if (macro is FieldTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is FieldDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is FieldDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ case DeclarationKind.function:
+ switch (phase) {
+ case Phase.types:
+ if (macro is FunctionTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is FunctionDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is FunctionDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ case DeclarationKind.method:
+ switch (phase) {
+ case Phase.types:
+ if (macro is MethodTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is MethodDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is MethodDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ case DeclarationKind.variable:
+ switch (phase) {
+ case Phase.types:
+ if (macro is VariableTypesMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.declarations:
+ if (macro is VariableDeclarationsMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ case Phase.definitions:
+ if (macro is VariableDefinitionMacro) {
+ interfaces |= interfaceMask;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ return new MacroInstanceIdentifierImpl._(instanceId, interfaces);
+ }
+
+ MacroInstanceIdentifierImpl.deserialize(Deserializer deserializer)
+ : id = (deserializer..moveNext()).expectInt(),
+ _interfaces = (deserializer..moveNext()).expectInt();
+
+ void serialize(Serializer serializer) => serializer
+ ..addInt(id)
+ ..addInt(_interfaces);
+
+ operator ==(other) => other is MacroInstanceIdentifierImpl && id == other.id;
+
+ int get hashCode => id;
+
+ @override
+ bool shouldExecute(DeclarationKind declarationKind, Phase phase) {
+ int mask = _interfaceMask(declarationKind, phase);
+ if (declarationKind == DeclarationKind.method) {
+ // Apply function macros to methods.
+ mask |= _interfaceMask(DeclarationKind.function, phase);
+ } else if (declarationKind == DeclarationKind.field) {
+ // Apply variable macros to fields.
+ mask |= _interfaceMask(DeclarationKind.variable, phase);
+ }
+ return _interfaces & mask != 0x0;
+ }
+
+ @override
+ bool supportsDeclarationKind(DeclarationKind declarationKind) {
+ for (Phase phase in Phase.values) {
+ if (shouldExecute(declarationKind, phase)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// The mask for a particular interface, which is a combination of a kind of
+ /// declaration and a phase.
+ static int _interfaceMask(DeclarationKind declarationKind, Phase phase) =>
+ 0x1 << (declarationKind.index * Phase.values.length) << phase.index;
+}
+
+/// Implementation of [MacroExecutionResult].
+class MacroExecutionResultImpl implements MacroExecutionResult {
+ @override
+ final Map<String, List<DeclarationCode>> classAugmentations;
+
+ @override
+ final List<DeclarationCode> libraryAugmentations;
+
+ @override
+ final List<String> newTypeNames;
+
+ MacroExecutionResultImpl({
+ required this.classAugmentations,
+ required this.libraryAugmentations,
+ required this.newTypeNames,
+ });
+
+ factory MacroExecutionResultImpl.deserialize(Deserializer deserializer) {
+ deserializer.moveNext();
+ deserializer.expectList();
+ Map<String, List<DeclarationCode>> classAugmentations = {
+ for (bool hasNext = deserializer.moveNext();
+ hasNext;
+ hasNext = deserializer.moveNext())
+ deserializer.expectString(): [
+ for (bool hasNextCode = (deserializer
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNextCode;
+ hasNextCode = deserializer.moveNext())
+ deserializer.expectCode(),
+ ]
+ };
+
+ deserializer.moveNext();
+ deserializer.expectList();
+ List<DeclarationCode> libraryAugmentations = [
+ for (bool hasNext = deserializer.moveNext();
+ hasNext;
+ hasNext = deserializer.moveNext())
+ deserializer.expectCode()
+ ];
+ deserializer.moveNext();
+ deserializer.expectList();
+ List<String> newTypeNames = [
+ for (bool hasNext = deserializer.moveNext();
+ hasNext;
+ hasNext = deserializer.moveNext())
+ deserializer.expectString()
+ ];
+
+ return new MacroExecutionResultImpl(
+ classAugmentations: classAugmentations,
+ libraryAugmentations: libraryAugmentations,
+ newTypeNames: newTypeNames,
+ );
+ }
+
+ void serialize(Serializer serializer) {
+ serializer.startList();
+ for (String clazz in classAugmentations.keys) {
+ serializer.addString(clazz);
+ serializer.startList();
+ for (DeclarationCode augmentation in classAugmentations[clazz]!) {
+ augmentation.serialize(serializer);
+ }
+ serializer.endList();
+ }
+ serializer.endList();
+
+ serializer.startList();
+ for (DeclarationCode augmentation in libraryAugmentations) {
+ augmentation.serialize(serializer);
+ }
+ serializer.endList();
+ serializer.startList();
+ for (String name in newTypeNames) {
+ serializer.addString(name);
+ }
+ serializer.endList();
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization.dart
new file mode 100644
index 0000000..50d98fd
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization.dart
@@ -0,0 +1,629 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:typed_data';
+
+import 'remote_instance.dart';
+
+/// All serialization must be done in a serialization Zone, which tells it
+/// whether we are the client or server.
+///
+/// In [SerializationMode.server], sets up a remote instance cache to use when
+/// deserializing remote instances back to their original instance.
+T withSerializationMode<T>(
+ SerializationMode mode,
+ T Function() fn, {
+ Serializer Function()? serializerFactory,
+ Deserializer Function(Object? data)? deserializerFactory,
+}) =>
+ runZoned(fn, zoneValues: {
+ #serializationMode: mode,
+ if (!mode.isClient) remoteInstanceZoneKey: <int, RemoteInstance>{}
+ });
+
+/// Serializable interface
+abstract class Serializable {
+ /// Serializes this object using [serializer].
+ void serialize(Serializer serializer);
+}
+
+/// A push based object serialization interface.
+abstract class Serializer {
+ /// Serializes a [String].
+ void addString(String value);
+
+ /// Serializes a nullable [String].
+ void addNullableString(String? value) =>
+ value == null ? addNull() : addString(value);
+
+ /// Serializes a [double].
+ void addDouble(double value);
+
+ /// Serializes a nullable [double].
+ void addNullableDouble(double? value) =>
+ value == null ? addNull() : addDouble(value);
+
+ /// Serializes an [int].
+ void addInt(int value);
+
+ /// Serializes a nullable [int].
+ void addNullableInt(int? value) => value == null ? addNull() : addInt(value);
+
+ /// Serializes a [bool].
+ void addBool(bool value);
+
+ /// Serializes a nullable [bool].
+ void addNullableBool(bool? value) =>
+ value == null ? addNull() : addBool(value);
+
+ /// Serializes a `null` literal.
+ void addNull();
+
+ /// Used to signal the start of an arbitrary length list of items.
+ void startList();
+
+ /// Used to signal the end of an arbitrary length list of items.
+ void endList();
+
+ /// Returns the resulting serialized object.
+ Object get result;
+}
+
+/// A pull based object deserialization interface.
+///
+/// You must call [moveNext] before reading any items, and in order to advance
+/// to the next item.
+abstract class Deserializer {
+ /// Checks if the current value is a null, returns `true` if so and `false`
+ /// otherwise.
+ bool checkNull();
+
+ /// Reads the current value as a non-nullable [String].
+ bool expectBool();
+
+ /// Reads the current value as a nullable [bool].
+ bool? expectNullableBool() => checkNull() ? null : expectBool();
+
+ /// Reads the current value as a non-nullable [double].
+ double expectDouble();
+
+ /// Reads the current value as a nullable [double].
+ double? expectNullableDouble() => checkNull() ? null : expectDouble();
+
+ /// Reads the current value as a non-nullable [int].
+ int expectInt();
+
+ /// Reads the current value as a nullable [int].
+ int? expectNullableInt() => checkNull() ? null : expectInt();
+
+ /// Reads the current value as a non-nullable [String].
+ String expectString();
+
+ /// Reads the current value as a nullable [String].
+ String? expectNullableString() => checkNull() ? null : expectString();
+
+ /// Asserts that the current item is the start of a list.
+ ///
+ /// An example for how to read from a list is as follows:
+ ///
+ /// var json = JsonReader.fromString(source);
+ /// I know it's a list of strings.
+ ///
+ /// ```
+ /// var result = <String>[];
+ /// deserializer.moveNext();
+ /// deserializer.expectList();
+ /// while (json.moveNext()) {
+ /// result.add(json.expectString());
+ /// }
+ /// // Can now read later items, but need to call `moveNext` again to move
+ /// // past the list.
+ /// deserializer.moveNext();
+ /// deserializer.expectBool();
+ /// ```
+ void expectList();
+
+ /// Moves to the next item, returns `false` if there are no more items to
+ /// read.
+ ///
+ /// If inside of a list, this returns `false` when the end of the list is
+ /// reached, and moves back to the parent, but does not advance it, so another
+ /// call to `moveNext` is needed. See example in the [expectList] docs.
+ bool moveNext();
+}
+
+class JsonSerializer implements Serializer {
+ /// The full result.
+ final _result = <Object?>[];
+
+ /// A path to the current list we are modifying.
+ late List<List<Object?>> _path = [_result];
+
+ /// Returns the result as an unmodifiable [Iterable].
+ ///
+ /// Asserts that all [List] entries have not been closed with [endList].
+ @override
+ Iterable<Object?> get result {
+ assert(_path.length == 1);
+ return _result;
+ }
+
+ @override
+ void addBool(bool value) => _path.last.add(value);
+ @override
+ void addNullableBool(bool? value) => _path.last.add(value);
+
+ @override
+ void addDouble(double value) => _path.last.add(value);
+ @override
+ void addNullableDouble(double? value) => _path.last.add(value);
+
+ @override
+ void addInt(int value) => _path.last.add(value);
+ @override
+ void addNullableInt(int? value) => _path.last.add(value);
+
+ @override
+ void addString(String value) => _path.last.add(value);
+ @override
+ void addNullableString(String? value) => _path.last.add(value);
+
+ @override
+ void addNull() => _path.last.add(null);
+
+ @override
+ void startList() {
+ List<Object?> sublist = [];
+ _path.last.add(sublist);
+ _path.add(sublist);
+ }
+
+ @override
+ void endList() {
+ _path.removeLast();
+ }
+}
+
+class JsonDeserializer implements Deserializer {
+ /// The root source list to read from.
+ final Iterable<Object?> _source;
+
+ /// The path to the current iterator we are reading from.
+ late List<Iterator<Object?>> _path = [];
+
+ /// Whether we have received our first [moveNext] call.
+ bool _initialized = false;
+
+ /// Initialize this deserializer from `_source`.
+ JsonDeserializer(this._source);
+
+ @override
+ bool checkNull() => _expectValue<Object?>() == null;
+
+ @override
+ void expectList() => _path.add(_expectValue<Iterable<Object?>>().iterator);
+
+ @override
+ bool expectBool() => _expectValue();
+ @override
+ bool? expectNullableBool() => _expectValue();
+
+ @override
+ double expectDouble() => _expectValue();
+ @override
+ double? expectNullableDouble() => _expectValue();
+
+ @override
+ int expectInt() => _expectValue();
+ @override
+ int? expectNullableInt() => _expectValue();
+
+ @override
+ String expectString() => _expectValue();
+ @override
+ String? expectNullableString() => _expectValue();
+
+ /// Reads the current value and casts it to [T].
+ T _expectValue<T>() {
+ if (!_initialized) {
+ throw new StateError(
+ 'You must call `moveNext()` before reading any values.');
+ }
+ return _path.last.current as T;
+ }
+
+ @override
+ bool moveNext() {
+ if (!_initialized) {
+ _path.add(_source.iterator);
+ _initialized = true;
+ }
+
+ // Move the current iterable, if its at the end of its items remove it from
+ // the current path and return false.
+ if (!_path.last.moveNext()) {
+ _path.removeLast();
+ return false;
+ }
+
+ return true;
+ }
+}
+
+class ByteDataSerializer extends Serializer {
+ final BytesBuilder _builder = new BytesBuilder();
+
+ // Re-usable 8 byte list and view for encoding doubles.
+ final Uint8List _eightByteList = new Uint8List(8);
+ late final ByteData _eightByteListData =
+ new ByteData.sublistView(_eightByteList);
+
+ @override
+ void addBool(bool value) => _builder
+ .addByte(value ? DataKind.boolTrue.index : DataKind.boolFalse.index);
+
+ @override
+ void addDouble(double value) {
+ _eightByteListData.setFloat64(0, value);
+ _builder
+ ..addByte(DataKind.float64.index)
+ ..add(_eightByteList);
+ }
+
+ @override
+ void addNull() => _builder.addByte(DataKind.nil.index);
+
+ @override
+ void addInt(int value) {
+ if (value >= 0x0) {
+ if (value + DataKind.values.length <= 0xff) {
+ _builder..addByte(value + DataKind.values.length);
+ } else if (value <= 0xff) {
+ _builder
+ ..addByte(DataKind.uint8.index)
+ ..addByte(value);
+ } else if (value <= 0xffff) {
+ _builder
+ ..addByte(DataKind.uint16.index)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else if (value <= 0xffffffff) {
+ _builder
+ ..addByte(DataKind.uint32.index)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else {
+ _builder
+ ..addByte(DataKind.uint64.index)
+ ..addByte(value >> 56)
+ ..addByte(value >> 48)
+ ..addByte(value >> 40)
+ ..addByte(value >> 32)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ }
+ } else {
+ if (value >= -0x80) {
+ _builder
+ ..addByte(DataKind.int8.index)
+ ..addByte(value);
+ } else if (value >= -0x8000) {
+ _builder
+ ..addByte(DataKind.int16.index)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else if (value >= -0x8000000) {
+ _builder
+ ..addByte(DataKind.int32.index)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else {
+ _builder
+ ..addByte(DataKind.int64.index)
+ ..addByte(value >> 56)
+ ..addByte(value >> 48)
+ ..addByte(value >> 40)
+ ..addByte(value >> 32)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ }
+ }
+ }
+
+ @override
+ void addString(String value) {
+ for (int i = 0; i < value.length; i++) {
+ if (value.codeUnitAt(i) > 0xff) {
+ _addTwoByteString(value);
+ return;
+ }
+ }
+ _addOneByteString(value);
+ }
+
+ void _addOneByteString(String value) {
+ _builder.addByte(DataKind.oneByteString.index);
+ addInt(value.length);
+ for (int i = 0; i < value.length; i++) {
+ _builder.addByte(value.codeUnitAt(i));
+ }
+ }
+
+ void _addTwoByteString(String value) {
+ _builder.addByte(DataKind.twoByteString.index);
+ addInt(value.length);
+ for (int i = 0; i < value.length; i++) {
+ int codeUnit = value.codeUnitAt(i);
+ switch (Endian.host) {
+ case Endian.little:
+ _builder
+ ..addByte(codeUnit)
+ ..addByte(codeUnit >> 8);
+ break;
+ case Endian.big:
+ _builder
+ ..addByte(codeUnit >> 8)
+ ..addByte(codeUnit);
+ break;
+ }
+ }
+ }
+
+ @override
+ void endList() => _builder.addByte(DataKind.endList.index);
+
+ @override
+ void startList() => _builder.addByte(DataKind.startList.index);
+
+ @override
+ Uint8List get result => _builder.takeBytes();
+}
+
+class ByteDataDeserializer extends Deserializer {
+ final ByteData _bytes;
+ int _byteOffset = 0;
+ int? _byteOffsetIncrement = 0;
+
+ ByteDataDeserializer(this._bytes);
+
+ /// Reads the next [DataKind] and advances [_byteOffset].
+ DataKind _readKind([int offset = 0]) {
+ int value = _bytes.getUint8(_byteOffset + offset);
+ if (value < DataKind.values.length) {
+ return DataKind.values[value];
+ } else {
+ return DataKind.directEncodedUint8;
+ }
+ }
+
+ @override
+ bool checkNull() {
+ _byteOffsetIncrement = 1;
+ return _readKind() == DataKind.nil;
+ }
+
+ @override
+ bool expectBool() {
+ DataKind kind = _readKind();
+ _byteOffsetIncrement = 1;
+ if (kind == DataKind.boolTrue) {
+ return true;
+ } else if (kind == DataKind.boolFalse) {
+ return false;
+ } else {
+ throw new StateError('Expected a bool but found a $kind');
+ }
+ }
+
+ @override
+ double expectDouble() {
+ DataKind kind = _readKind();
+ if (kind != DataKind.float64) {
+ throw new StateError('Expected a double but found a $kind');
+ }
+ _byteOffsetIncrement = 9;
+ return _bytes.getFloat64(_byteOffset + 1);
+ }
+
+ @override
+ int expectInt() => _expectInt(0);
+
+ int _expectInt(int offset) {
+ DataKind kind = _readKind(offset);
+ if (kind == DataKind.directEncodedUint8) {
+ _byteOffsetIncrement = offset + 1;
+ return _bytes.getUint8(_byteOffset + offset) - DataKind.values.length;
+ }
+ offset += 1;
+ int result;
+ switch (kind) {
+ case DataKind.int8:
+ result = _bytes.getInt8(_byteOffset + offset);
+ _byteOffsetIncrement = 1 + offset;
+ break;
+ case DataKind.int16:
+ result = _bytes.getInt16(_byteOffset + offset);
+ _byteOffsetIncrement = 2 + offset;
+ break;
+ case DataKind.int32:
+ result = _bytes.getInt32(_byteOffset + offset);
+ _byteOffsetIncrement = 4 + offset;
+ break;
+ case DataKind.int64:
+ result = _bytes.getInt64(_byteOffset + offset);
+ _byteOffsetIncrement = 8 + offset;
+ break;
+ case DataKind.uint8:
+ result = _bytes.getUint8(_byteOffset + offset);
+ _byteOffsetIncrement = 1 + offset;
+ break;
+ case DataKind.uint16:
+ result = _bytes.getUint16(_byteOffset + offset);
+ _byteOffsetIncrement = 2 + offset;
+ break;
+ case DataKind.uint32:
+ result = _bytes.getUint32(_byteOffset + offset);
+ _byteOffsetIncrement = 4 + offset;
+ break;
+ case DataKind.uint64:
+ result = _bytes.getUint64(_byteOffset + offset);
+ _byteOffsetIncrement = 8 + offset;
+ break;
+ default:
+ throw new StateError('Expected an int but found a $kind');
+ }
+ return result;
+ }
+
+ @override
+ void expectList() {
+ DataKind kind = _readKind();
+ if (kind != DataKind.startList) {
+ throw new StateError('Expected the start to a list but found a $kind');
+ }
+ _byteOffsetIncrement = 1;
+ }
+
+ @override
+ String expectString() {
+ DataKind kind = _readKind();
+ int length = _expectInt(1);
+ int offset = _byteOffsetIncrement! + _byteOffset;
+ if (kind == DataKind.oneByteString) {
+ _byteOffsetIncrement = _byteOffsetIncrement! + length;
+ return new String.fromCharCodes(
+ _bytes.buffer.asUint8List(offset, length));
+ } else if (kind == DataKind.twoByteString) {
+ length = length * 2;
+ _byteOffsetIncrement = _byteOffsetIncrement! + length;
+ Uint8List bytes =
+ new Uint8List.fromList(_bytes.buffer.asUint8List(offset, length));
+ return new String.fromCharCodes(bytes.buffer.asUint16List());
+ } else {
+ throw new StateError('Expected a string but found a $kind');
+ }
+ }
+
+ @override
+ bool moveNext() {
+ int? increment = _byteOffsetIncrement;
+ _byteOffsetIncrement = null;
+ if (increment == null) {
+ throw new StateError("Can't move until consuming the current element");
+ }
+ _byteOffset += increment;
+ if (_byteOffset >= _bytes.lengthInBytes) {
+ return false;
+ } else if (_readKind() == DataKind.endList) {
+ // You don't explicitly consume list end markers.
+ _byteOffsetIncrement = 1;
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
+
+enum DataKind {
+ nil,
+ boolTrue,
+ boolFalse,
+ directEncodedUint8, // Encoded in the kind byte.
+ startList,
+ endList,
+ int8,
+ int16,
+ int32,
+ int64,
+ uint8,
+ uint16,
+ uint32,
+ uint64,
+ float64,
+ oneByteString,
+ twoByteString,
+}
+
+/// Must be set using `withSerializationMode` before doing any serialization or
+/// deserialization.
+SerializationMode get serializationMode {
+ SerializationMode? mode =
+ Zone.current[#serializationMode] as SerializationMode?;
+ if (mode == null) {
+ throw new StateError('No SerializationMode set, you must do all '
+ 'serialization inside a call to `withSerializationMode`.');
+ }
+ return mode;
+}
+
+/// Returns the current deserializer factory for the zone.
+Deserializer Function(Object?) get deserializerFactory {
+ switch (serializationMode) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.byteDataServer:
+ return (Object? message) => new ByteDataDeserializer(
+ new ByteData.sublistView(message as Uint8List));
+ case SerializationMode.jsonClient:
+ case SerializationMode.jsonServer:
+ return (Object? message) =>
+ new JsonDeserializer(message as Iterable<Object?>);
+ }
+}
+
+/// Returns the current serializer factory for the zone.
+Serializer Function() get serializerFactory {
+ switch (serializationMode) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.byteDataServer:
+ return () => new ByteDataSerializer();
+ case SerializationMode.jsonClient:
+ case SerializationMode.jsonServer:
+ return () => new JsonSerializer();
+ }
+}
+
+/// Some objects are serialized differently on the client side versus the server
+/// side. This indicates the different modes, as well as the format used.
+enum SerializationMode {
+ byteDataClient,
+ byteDataServer,
+ jsonServer,
+ jsonClient,
+}
+
+extension SerializationModeHelpers on SerializationMode {
+ bool get isClient {
+ switch (this) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.jsonClient:
+ return true;
+ case SerializationMode.byteDataServer:
+ case SerializationMode.jsonServer:
+ return false;
+ }
+ }
+
+ /// A stable string to write in code.
+ String get asCode {
+ switch (this) {
+ case SerializationMode.byteDataClient:
+ return 'SerializationMode.byteDataClient';
+ case SerializationMode.byteDataServer:
+ return 'SerializationMode.byteDataServer';
+ case SerializationMode.jsonClient:
+ return 'SerializationMode.jsonClient';
+ case SerializationMode.jsonServer:
+ return 'SerializationMode.jsonServer';
+ }
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
new file mode 100644
index 0000000..d039f7d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/serialization_extensions.dart
@@ -0,0 +1,401 @@
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
+
+import 'remote_instance.dart';
+import 'serialization.dart';
+import '../api.dart';
+
+extension DeserializerExtensions on Deserializer {
+ T expectRemoteInstance<T>() {
+ int id = expectInt();
+
+ // Server side we just return the cached remote instance by ID.
+ if (!serializationMode.isClient) {
+ return RemoteInstance.cached(id) as T;
+ }
+
+ moveNext();
+ RemoteInstanceKind kind = RemoteInstanceKind.values[expectInt()];
+ switch (kind) {
+ case RemoteInstanceKind.classIntrospector:
+ case RemoteInstanceKind.identifierResolver:
+ case RemoteInstanceKind.namedStaticType:
+ case RemoteInstanceKind.staticType:
+ case RemoteInstanceKind.typeDeclarationResolver:
+ case RemoteInstanceKind.typeResolver:
+ // These are simple wrappers, just pass in the kind
+ return new RemoteInstanceImpl(id: id, kind: kind) as T;
+ case RemoteInstanceKind.classDeclaration:
+ moveNext();
+ return _expectClassDeclaration(id) as T;
+ case RemoteInstanceKind.constructorDeclaration:
+ moveNext();
+ return _expectConstructorDeclaration(id) as T;
+ case RemoteInstanceKind.fieldDeclaration:
+ moveNext();
+ return _expectFieldDeclaration(id) as T;
+ case RemoteInstanceKind.functionDeclaration:
+ moveNext();
+ return _expectFunctionDeclaration(id) as T;
+ case RemoteInstanceKind.functionTypeAnnotation:
+ moveNext();
+ return _expectFunctionTypeAnnotation(id) as T;
+ case RemoteInstanceKind.identifier:
+ moveNext();
+ return _expectIdentifier(id) as T;
+ case RemoteInstanceKind.methodDeclaration:
+ moveNext();
+ return _expectMethodDeclaration(id) as T;
+ case RemoteInstanceKind.namedTypeAnnotation:
+ moveNext();
+ return _expectNamedTypeAnnotation(id) as T;
+ case RemoteInstanceKind.parameterDeclaration:
+ moveNext();
+ return _expectParameterDeclaration(id) as T;
+ case RemoteInstanceKind.typeAliasDeclaration:
+ moveNext();
+ return _expectTypeAliasDeclaration(id) as T;
+ case RemoteInstanceKind.typeParameterDeclaration:
+ moveNext();
+ return _expectTypeParameterDeclaration(id) as T;
+ case RemoteInstanceKind.variableDeclaration:
+ moveNext();
+ return _expectVariableDeclaration(id) as T;
+ }
+ }
+
+ /// Helper method to read a list of [RemoteInstance]s.
+ List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
+ expectList();
+ return [
+ for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
+ expectRemoteInstance(),
+ ];
+ }
+
+ NamedTypeAnnotation _expectNamedTypeAnnotation(int id) =>
+ new NamedTypeAnnotationImpl(
+ id: id,
+ isNullable: expectBool(),
+ identifier: RemoteInstance.deserialize(this),
+ typeArguments: (this..moveNext())._expectRemoteInstanceList(),
+ );
+
+ FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) =>
+ new FunctionTypeAnnotationImpl(
+ id: id,
+ isNullable: expectBool(),
+ returnType: RemoteInstance.deserialize(this),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ );
+
+ Identifier _expectIdentifier(int id) => new IdentifierImpl(
+ id: id,
+ name: expectString(),
+ );
+
+ ParameterDeclaration _expectParameterDeclaration(int id) =>
+ new ParameterDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isNamed: (this..moveNext()).expectBool(),
+ isRequired: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ );
+
+ TypeParameterDeclaration _expectTypeParameterDeclaration(int id) =>
+ new TypeParameterDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ bound: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+ );
+
+ FunctionDeclaration _expectFunctionDeclaration(int id) =>
+ new FunctionDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isOperator: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ );
+
+ MethodDeclaration _expectMethodDeclaration(int id) =>
+ new MethodDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isOperator: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ definingClass: RemoteInstance.deserialize(this),
+ isStatic: (this..moveNext()).expectBool(),
+ );
+
+ ConstructorDeclaration _expectConstructorDeclaration(int id) =>
+ new ConstructorDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ isGetter: (this..moveNext()).expectBool(),
+ isOperator: (this..moveNext()).expectBool(),
+ isSetter: (this..moveNext()).expectBool(),
+ namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+ positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+ returnType: RemoteInstance.deserialize(this),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ definingClass: RemoteInstance.deserialize(this),
+ // There is an extra boolean here representing the `isStatic` field
+ // which we just skip past.
+ isFactory: (this
+ ..moveNext()
+ ..expectBool()
+ ..moveNext())
+ .expectBool(),
+ );
+
+ VariableDeclaration _expectVariableDeclaration(int id) =>
+ new VariableDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isExternal: (this..moveNext()).expectBool(),
+ isFinal: (this..moveNext()).expectBool(),
+ isLate: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ );
+
+ FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ isExternal: (this..moveNext()).expectBool(),
+ isFinal: (this..moveNext()).expectBool(),
+ isLate: (this..moveNext()).expectBool(),
+ type: RemoteInstance.deserialize(this),
+ definingClass: RemoteInstance.deserialize(this),
+ isStatic: (this..moveNext()).expectBool(),
+ );
+
+ ClassDeclaration _expectClassDeclaration(int id) => new ClassDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ interfaces: (this..moveNext())._expectRemoteInstanceList(),
+ isAbstract: (this..moveNext()).expectBool(),
+ isExternal: (this..moveNext()).expectBool(),
+ mixins: (this..moveNext())._expectRemoteInstanceList(),
+ superclass:
+ (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+ );
+
+ TypeAliasDeclaration _expectTypeAliasDeclaration(int id) =>
+ new TypeAliasDeclarationImpl(
+ id: id,
+ identifier: expectRemoteInstance(),
+ typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+ aliasedType: RemoteInstance.deserialize(this),
+ );
+
+ List<String> _readStringList() => [
+ for (bool hasNext = (this
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNext;
+ hasNext = moveNext())
+ expectString(),
+ ];
+
+ List<T> _readCodeList<T extends Code>() => [
+ for (bool hasNext = (this
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNext;
+ hasNext = moveNext())
+ expectCode(),
+ ];
+
+ List<Object> _readParts() {
+ moveNext();
+ expectList();
+ List<Object> parts = [];
+ while (moveNext()) {
+ _CodePartKind partKind = _CodePartKind.values[expectInt()];
+ moveNext();
+ switch (partKind) {
+ case _CodePartKind.code:
+ parts.add(expectCode());
+ break;
+ case _CodePartKind.string:
+ parts.add(expectString());
+ break;
+ case _CodePartKind.identifier:
+ parts.add(expectRemoteInstance());
+ break;
+ }
+ }
+ return parts;
+ }
+
+ T expectCode<T extends Code>() {
+ CodeKind kind = CodeKind.values[expectInt()];
+
+ switch (kind) {
+ case CodeKind.raw:
+ return new Code.fromParts(_readParts()) as T;
+ case CodeKind.declaration:
+ return new DeclarationCode.fromParts(_readParts()) as T;
+ case CodeKind.expression:
+ return new ExpressionCode.fromParts(_readParts()) as T;
+ case CodeKind.functionBody:
+ return new FunctionBodyCode.fromParts(_readParts()) as T;
+ case CodeKind.functionTypeAnnotation:
+ return new FunctionTypeAnnotationCode(
+ namedParameters: _readCodeList(),
+ positionalParameters: _readCodeList(),
+ returnType: (this..moveNext()).expectNullableCode(),
+ typeParameters: _readCodeList()) as T;
+ case CodeKind.namedTypeAnnotation:
+ return new NamedTypeAnnotationCode(
+ name: RemoteInstance.deserialize(this),
+ typeArguments: _readCodeList()) as T;
+ case CodeKind.nullableTypeAnnotation:
+ return new NullableTypeAnnotationCode((this..moveNext()).expectCode())
+ as T;
+ case CodeKind.parameter:
+ return new ParameterCode(
+ defaultValue: (this..moveNext()).expectNullableCode(),
+ keywords: _readStringList(),
+ name: (this..moveNext()).expectString(),
+ type: (this..moveNext()).expectNullableCode()) as T;
+ case CodeKind.typeParameter:
+ return new TypeParameterCode(
+ bound: (this..moveNext()).expectNullableCode(),
+ name: (this..moveNext()).expectString()) as T;
+ }
+ }
+
+ T? expectNullableCode<T extends Code>() {
+ if (checkNull()) return null;
+ return expectCode();
+ }
+}
+
+extension SerializeNullable on Serializable? {
+ /// Either serializes a `null` literal or the object.
+ void serializeNullable(Serializer serializer) {
+ Serializable? self = this;
+ if (self == null) {
+ serializer.addNull();
+ } else {
+ self.serialize(serializer);
+ }
+ }
+}
+
+extension SerializeNullableCode on Code? {
+ /// Either serializes a `null` literal or the code object.
+ void serializeNullable(Serializer serializer) {
+ Code? self = this;
+ if (self == null) {
+ serializer.addNull();
+ } else {
+ self.serialize(serializer);
+ }
+ }
+}
+
+extension SerializeCode on Code {
+ void serialize(Serializer serializer) {
+ serializer.addInt(kind.index);
+ switch (kind) {
+ case CodeKind.namedTypeAnnotation:
+ NamedTypeAnnotationCode self = this as NamedTypeAnnotationCode;
+ (self.name as IdentifierImpl).serialize(serializer);
+ serializer.startList();
+ for (TypeAnnotationCode typeArg in self.typeArguments) {
+ typeArg.serialize(serializer);
+ }
+ serializer.endList();
+ return;
+ case CodeKind.functionTypeAnnotation:
+ FunctionTypeAnnotationCode self = this as FunctionTypeAnnotationCode;
+ serializer.startList();
+ for (ParameterCode named in self.namedParameters) {
+ named.serialize(serializer);
+ }
+ serializer
+ ..endList()
+ ..startList();
+ for (ParameterCode positional in self.positionalParameters) {
+ positional.serialize(serializer);
+ }
+ serializer..endList();
+ self.returnType.serializeNullable(serializer);
+ serializer.startList();
+ for (TypeParameterCode typeParam in self.typeParameters) {
+ typeParam.serialize(serializer);
+ }
+ serializer.endList();
+ return;
+ case CodeKind.nullableTypeAnnotation:
+ NullableTypeAnnotationCode self = this as NullableTypeAnnotationCode;
+ self.underlyingType.serialize(serializer);
+ return;
+ case CodeKind.parameter:
+ ParameterCode self = this as ParameterCode;
+ self.defaultValue.serializeNullable(serializer);
+ serializer.startList();
+ for (String keyword in self.keywords) {
+ serializer.addString(keyword);
+ }
+ serializer
+ ..endList()
+ ..addString(self.name);
+ self.type.serializeNullable(serializer);
+ return;
+ case CodeKind.typeParameter:
+ TypeParameterCode self = this as TypeParameterCode;
+ self.bound.serializeNullable(serializer);
+ serializer.addString(self.name);
+ return;
+ default:
+ serializer.startList();
+ for (Object part in parts) {
+ if (part is String) {
+ serializer
+ ..addInt(_CodePartKind.string.index)
+ ..addString(part);
+ } else if (part is Code) {
+ serializer.addInt(_CodePartKind.code.index);
+ part.serialize(serializer);
+ } else if (part is IdentifierImpl) {
+ serializer.addInt(_CodePartKind.identifier.index);
+ part.serialize(serializer);
+ } else {
+ throw new StateError('Unrecognized code part $part');
+ }
+ }
+ serializer.endList();
+ return;
+ }
+ }
+}
+
+enum _CodePartKind {
+ string,
+ code,
+ identifier,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
deleted file mode 100644
index 099c58e..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-
-import '../executor.dart';
-import '../api.dart';
-import 'response_impls.dart';
-
-class TypeBuilderBase {
- /// The final result, will be built up over `augment` calls.
- final List<DeclarationCode> _augmentations;
-
- /// Creates and returns a [MacroExecutionResult] out of the [_augmentations]
- /// created by this builder.
- MacroExecutionResult get result => new MacroExecutionResultImpl(
- augmentations: _augmentations,
- // TODO: Implement `imports`, or possibly drop it?
- imports: [],
- );
-
- TypeBuilderBase({List<DeclarationCode>? parentAugmentations})
- : _augmentations = parentAugmentations ?? [];
-}
-
-class TypeBuilderImpl extends TypeBuilderBase implements TypeBuilder {
- @override
- void declareType(DeclarationCode typeDeclaration) {
- _augmentations.add(typeDeclaration);
- }
-}
-
-/// Base class for all [DeclarationBuilder]s.
-class DeclarationBuilderBase extends TypeBuilderBase
- implements ClassIntrospector, TypeResolver {
- final ClassIntrospector classIntrospector;
- final TypeResolver typeResolver;
-
- DeclarationBuilderBase(this.classIntrospector, this.typeResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(parentAugmentations: parentAugmentations);
-
- @override
- Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
- classIntrospector.constructorsOf(clazz);
-
- @override
- Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
- classIntrospector.fieldsOf(clazz);
-
- @override
- Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
- classIntrospector.interfacesOf(clazz);
-
- @override
- Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
- classIntrospector.methodsOf(clazz);
-
- @override
- Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
- classIntrospector.mixinsOf(clazz);
-
- @override
- Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
- classIntrospector.superclassOf(clazz);
-
- @override
- Future<StaticType> instantiateCode(ExpressionCode code) =>
- typeResolver.instantiateCode(code);
-
- @override
- Future<StaticType> instantiateType(TypeAnnotation typeAnnotation) =>
- typeResolver.instantiateType(typeAnnotation);
-}
-
-class DeclarationBuilderImpl extends DeclarationBuilderBase
- implements DeclarationBuilder {
- DeclarationBuilderImpl(
- ClassIntrospector classIntrospector, TypeResolver typeResolver)
- : super(classIntrospector, typeResolver);
-
- @override
- void declareInLibrary(DeclarationCode declaration) {
- _augmentations.add(declaration);
- }
-}
-
-class ClassMemberDeclarationBuilderImpl extends DeclarationBuilderImpl
- implements ClassMemberDeclarationBuilder {
- final Identifier definingClass;
-
- ClassMemberDeclarationBuilderImpl(this.definingClass,
- ClassIntrospector classIntrospector, TypeResolver typeResolver)
- : super(classIntrospector, typeResolver);
-
- @override
- void declareInClass(DeclarationCode declaration) {
- _augmentations.add(_buildClassAugmentation(definingClass, [declaration]));
- }
-}
-
-/// Base class for all [DefinitionBuilder]s.
-class DefinitionBuilderBase extends DeclarationBuilderBase
- implements TypeDeclarationResolver {
- final TypeDeclarationResolver typeDeclarationResolver;
-
- DefinitionBuilderBase(ClassIntrospector classIntrospector,
- TypeResolver typeResolver, this.typeDeclarationResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(classIntrospector, typeResolver,
- parentAugmentations: parentAugmentations);
-
- @override
- Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) =>
- typeDeclarationResolver.declarationOf(identifier);
-}
-
-class ClassDefinitionBuilderImpl extends DefinitionBuilderBase
- implements ClassDefinitionBuilder {
- /// The declaration this is a builder for.
- final ClassDeclaration declaration;
-
- ClassDefinitionBuilderImpl(
- this.declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver,
- TypeDeclarationResolver typeDeclarationResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: parentAugmentations);
-
- @override
- Future<ConstructorDefinitionBuilder> buildConstructor(
- Identifier identifier) async {
- ConstructorDeclaration constructor =
- (await classIntrospector.constructorsOf(declaration))
- .firstWhere((constructor) => constructor.identifier == identifier);
- return new ConstructorDefinitionBuilderImpl(
- constructor, classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: _augmentations);
- }
-
- @override
- Future<VariableDefinitionBuilder> buildField(Identifier identifier) async {
- FieldDeclaration field = (await classIntrospector.fieldsOf(declaration))
- .firstWhere((field) => field.identifier == identifier);
- return new VariableDefinitionBuilderImpl(
- field, classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: _augmentations);
- }
-
- @override
- Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier) async {
- MethodDeclaration method = (await classIntrospector.methodsOf(declaration))
- .firstWhere((method) => method.identifier == identifier);
- return new FunctionDefinitionBuilderImpl(
- method, classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: _augmentations);
- }
-}
-
-/// Implementation of [FunctionDefinitionBuilder].
-class FunctionDefinitionBuilderImpl extends DefinitionBuilderBase
- implements FunctionDefinitionBuilder {
- final FunctionDeclaration declaration;
-
- FunctionDefinitionBuilderImpl(
- this.declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver,
- TypeDeclarationResolver typeDeclarationResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: parentAugmentations);
-
- @override
- void augment(FunctionBodyCode body) {
- DeclarationCode augmentation =
- _buildFunctionAugmentation(body, declaration);
- if (declaration is ClassMemberDeclaration) {
- augmentation = _buildClassAugmentation(
- (declaration as ClassMemberDeclaration).definingClass,
- [augmentation]);
- }
- _augmentations.add(augmentation);
- }
-}
-
-class ConstructorDefinitionBuilderImpl extends DefinitionBuilderBase
- implements ConstructorDefinitionBuilder {
- final ConstructorDeclaration declaration;
-
- ConstructorDefinitionBuilderImpl(
- this.declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver,
- TypeDeclarationResolver typeDeclarationResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: parentAugmentations);
-
- @override
- void augment({FunctionBodyCode? body, List<Code>? initializers}) {
- body ??= new FunctionBodyCode.fromString('''{
- augment super();
- }''');
- _augmentations.add(_buildClassAugmentation(declaration.definingClass, [
- _buildFunctionAugmentation(body, declaration, initializers: initializers)
- ]));
- }
-}
-
-class VariableDefinitionBuilderImpl extends DefinitionBuilderBase
- implements VariableDefinitionBuilder {
- final VariableDeclaration declaration;
-
- VariableDefinitionBuilderImpl(
- this.declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver,
- TypeDeclarationResolver typeDeclarationResolver,
- {List<DeclarationCode>? parentAugmentations})
- : super(classIntrospector, typeResolver, typeDeclarationResolver,
- parentAugmentations: parentAugmentations);
-
- @override
- void augment(
- {DeclarationCode? getter,
- DeclarationCode? setter,
- ExpressionCode? initializer}) {
- List<DeclarationCode> augmentations = _buildVariableAugmentations(
- declaration,
- getter: getter,
- setter: setter,
- initializer: initializer);
- if (declaration is ClassMemberDeclaration) {
- augmentations = [
- _buildClassAugmentation(
- (declaration as ClassMemberDeclaration).definingClass,
- augmentations)
- ];
- }
-
- _augmentations.addAll(augmentations);
- }
-}
-
-/// Creates an augmentation of [clazz] with member [augmentations].
-DeclarationCode _buildClassAugmentation(
- Identifier clazz, List<DeclarationCode> augmentations) =>
- new DeclarationCode.fromParts([
- 'augment class ',
- clazz,
- ' {\n',
- ...augmentations.joinAsCode('\n'),
- '\n}',
- ]);
-
-/// Builds all the possible augmentations for a variable.
-List<DeclarationCode> _buildVariableAugmentations(
- VariableDeclaration declaration,
- {DeclarationCode? getter,
- DeclarationCode? setter,
- ExpressionCode? initializer}) {
- List<DeclarationCode> augmentations = [];
- if (getter != null) {
- augmentations.add(new DeclarationCode.fromParts([
- 'augment ',
- getter,
- ]));
- }
- if (setter != null) {
- augmentations.add(new DeclarationCode.fromParts([
- 'augment ',
- setter,
- ]));
- }
- if (initializer != null) {
- augmentations.add(new DeclarationCode.fromParts([
- 'augment ',
- if (declaration.isFinal) 'final ',
- declaration.type.code,
- ' ',
- declaration.identifier,
- ' = ',
- initializer,
- ';',
- ]));
- }
-
- return augmentations;
-}
-
-/// Builds the code to augment a function, method, or constructor with a new
-/// body.
-///
-/// The [initializers] parameter can only be used if [declaration] is a
-/// constructor.
-DeclarationCode _buildFunctionAugmentation(
- FunctionBodyCode body, FunctionDeclaration declaration,
- {List<Code>? initializers}) {
- assert(initializers == null || declaration is ConstructorDeclaration);
-
- return new DeclarationCode.fromParts([
- 'augment ',
- if (declaration is ConstructorDeclaration) ...[
- declaration.definingClass,
- if (declaration.identifier.name.isNotEmpty) '.',
- ] else ...[
- declaration.returnType.code,
- ' ',
- ],
- declaration.identifier,
- if (declaration.typeParameters.isNotEmpty) ...[
- '<',
- for (TypeParameterDeclaration typeParam
- in declaration.typeParameters) ...[
- typeParam.identifier,
- if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
- if (typeParam != declaration.typeParameters.last) ', ',
- ],
- '>',
- ],
- '(',
- for (ParameterDeclaration positionalRequired
- in declaration.positionalParameters.where((p) => p.isRequired)) ...[
- new ParameterCode.fromParts([
- positionalRequired.type.code,
- ' ',
- positionalRequired.identifier,
- ]),
- ', '
- ],
- if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
- '[',
- for (ParameterDeclaration positionalOptional
- in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
- new ParameterCode.fromParts([
- positionalOptional.type.code,
- ' ',
- positionalOptional.identifier,
- ]),
- ', ',
- ],
- ']',
- ],
- if (declaration.namedParameters.isNotEmpty) ...[
- '{',
- for (ParameterDeclaration named in declaration.namedParameters) ...[
- new ParameterCode.fromParts([
- if (named.isRequired) 'required ',
- named.type.code,
- ' ',
- named.identifier,
- if (named.defaultValue != null) ...[
- ' = ',
- named.defaultValue!,
- ],
- ]),
- ', ',
- ],
- '}',
- ],
- ') ',
- if (initializers != null && initializers.isNotEmpty) ...[
- ' : ',
- initializers.first,
- for (Code initializer in initializers.skip(1)) ...[
- ',\n',
- initializer,
- ],
- ],
- body,
- ]);
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart
deleted file mode 100644
index 7488445..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/builder_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-/// Runs [macro] in the types phase and returns a [MacroExecutionResult].
-Future<MacroExecutionResult> executeTypesMacro(
- Macro macro, Declaration declaration) async {
- TypeBuilderImpl builder = new TypeBuilderImpl();
- if (declaration is FunctionDeclaration) {
- if (macro is ConstructorTypesMacro &&
- declaration is ConstructorDeclaration) {
- await macro.buildTypesForConstructor(declaration, builder);
- return builder.result;
- } else if (macro is MethodTypesMacro && declaration is MethodDeclaration) {
- await macro.buildTypesForMethod(declaration, builder);
- return builder.result;
- } else if (macro is FunctionTypesMacro) {
- await macro.buildTypesForFunction(declaration, builder);
- return builder.result;
- }
- } else if (declaration is VariableDeclaration) {
- if (macro is FieldTypesMacro && declaration is FieldDeclaration) {
- await macro.buildTypesForField(declaration, builder);
- return builder.result;
- } else if (macro is VariableTypesMacro) {
- await macro.buildTypesForVariable(declaration, builder);
- return builder.result;
- }
- } else if (macro is ClassTypesMacro && declaration is ClassDeclaration) {
- await macro.buildTypesForClass(declaration, builder);
- return builder.result;
- }
- throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
- 'macro: $macro\ndeclaration: $declaration');
-}
-
-/// Runs [macro] in the declaration phase and returns a [MacroExecutionResult].
-Future<MacroExecutionResult> executeDeclarationsMacro(
- Macro macro,
- Declaration declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver) async {
- if (declaration is ClassDeclaration && macro is ClassDeclarationsMacro) {
- ClassMemberDeclarationBuilderImpl builder =
- new ClassMemberDeclarationBuilderImpl(
- declaration.identifier, classIntrospector, typeResolver);
- await macro.buildDeclarationsForClass(declaration, builder);
- return builder.result;
- } else if (declaration is ClassMemberDeclaration) {
- ClassMemberDeclarationBuilderImpl builder =
- new ClassMemberDeclarationBuilderImpl(
- declaration.definingClass, classIntrospector, typeResolver);
- if (declaration is FunctionDeclaration) {
- if (macro is ConstructorDeclarationsMacro &&
- declaration is ConstructorDeclaration) {
- await macro.buildDeclarationsForConstructor(declaration, builder);
- return builder.result;
- } else if (macro is MethodDeclarationsMacro &&
- declaration is MethodDeclaration) {
- await macro.buildDeclarationsForMethod(declaration, builder);
- return builder.result;
- } else if (macro is FunctionDeclarationsMacro) {
- await macro.buildDeclarationsForFunction(
- declaration as FunctionDeclaration, builder);
- return builder.result;
- }
- } else if (declaration is VariableDeclaration) {
- if (macro is FieldDeclarationsMacro && declaration is FieldDeclaration) {
- await macro.buildDeclarationsForField(declaration, builder);
- return builder.result;
- } else if (macro is VariableDeclarationsMacro) {
- DeclarationBuilderImpl builder =
- new DeclarationBuilderImpl(classIntrospector, typeResolver);
- await macro.buildDeclarationsForVariable(
- declaration as VariableDeclaration, builder);
- return builder.result;
- }
- }
- } else {
- DeclarationBuilderImpl builder =
- new DeclarationBuilderImpl(classIntrospector, typeResolver);
- if (declaration is FunctionDeclaration &&
- macro is FunctionDeclarationsMacro) {
- await macro.buildDeclarationsForFunction(declaration, builder);
- return builder.result;
- } else if (macro is VariableDeclarationsMacro &&
- declaration is VariableDeclaration) {
- await macro.buildDeclarationsForVariable(declaration, builder);
- return builder.result;
- }
- }
- throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
- 'macro: $macro\ndeclaration: $declaration');
-}
-
-/// Runs [macro] in the definition phase and returns a [MacroExecutionResult].
-Future<MacroExecutionResult> executeDefinitionMacro(
- Macro macro,
- Declaration declaration,
- ClassIntrospector classIntrospector,
- TypeResolver typeResolver,
- TypeDeclarationResolver typeDeclarationResolver) async {
- if (declaration is FunctionDeclaration) {
- if (macro is ConstructorDefinitionMacro &&
- declaration is ConstructorDeclaration) {
- ConstructorDefinitionBuilderImpl builder =
- new ConstructorDefinitionBuilderImpl(declaration, classIntrospector,
- typeResolver, typeDeclarationResolver);
- await macro.buildDefinitionForConstructor(declaration, builder);
- return builder.result;
- } else {
- FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
- declaration,
- classIntrospector,
- typeResolver,
- typeDeclarationResolver);
- if (macro is MethodDefinitionMacro && declaration is MethodDeclaration) {
- await macro.buildDefinitionForMethod(declaration, builder);
- return builder.result;
- } else if (macro is FunctionDefinitionMacro) {
- await macro.buildDefinitionForFunction(declaration, builder);
- return builder.result;
- }
- }
- } else if (declaration is VariableDeclaration) {
- VariableDefinitionBuilderImpl builder = new VariableDefinitionBuilderImpl(
- declaration, classIntrospector, typeResolver, typeDeclarationResolver);
- if (macro is FieldDefinitionMacro && declaration is FieldDeclaration) {
- await macro.buildDefinitionForField(declaration, builder);
- return builder.result;
- } else if (macro is VariableDefinitionMacro) {
- await macro.buildDefinitionForVariable(declaration, builder);
- return builder.result;
- }
- } else if (macro is ClassDefinitionMacro && declaration is ClassDeclaration) {
- ClassDefinitionBuilderImpl builder = new ClassDefinitionBuilderImpl(
- declaration, classIntrospector, typeResolver, typeDeclarationResolver);
- await macro.buildDefinitionForClass(declaration, builder);
- return builder.result;
- }
- throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
- 'macro: $macro\ndeclaration: $declaration');
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
deleted file mode 100644
index 64e5e4f..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
+++ /dev/null
@@ -1,653 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'remote_instance.dart';
-import 'serialization.dart';
-import 'serialization_extensions.dart';
-import '../api.dart';
-
-class IdentifierImpl extends RemoteInstance implements Identifier {
- final String name;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.identifier;
-
- IdentifierImpl({required int id, required this.name}) : super(id);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer.addString(name);
- }
-}
-
-abstract class TypeAnnotationImpl extends RemoteInstance
- implements TypeAnnotation {
- final bool isNullable;
-
- TypeAnnotationImpl({required int id, required this.isNullable}) : super(id);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer.addBool(isNullable);
- }
-}
-
-class NamedTypeAnnotationImpl extends TypeAnnotationImpl
- implements NamedTypeAnnotation {
- @override
- Code get code => new Code.fromParts([
- identifier,
- if (typeArguments.isNotEmpty) ...[
- '<',
- typeArguments.first.code,
- for (TypeAnnotation arg in typeArguments.skip(1)) ...[', ', arg.code],
- '>',
- ],
- if (isNullable) '?',
- ]);
-
- @override
- final IdentifierImpl identifier;
-
- @override
- final List<TypeAnnotationImpl> typeArguments;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.namedTypeAnnotation;
-
- NamedTypeAnnotationImpl({
- required int id,
- required bool isNullable,
- required this.identifier,
- required this.typeArguments,
- }) : super(id: id, isNullable: isNullable);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- identifier.serialize(serializer);
- serializer.startList();
- for (TypeAnnotationImpl typeArg in typeArguments) {
- typeArg.serialize(serializer);
- }
- serializer.endList();
- }
-}
-
-class FunctionTypeAnnotationImpl extends TypeAnnotationImpl
- implements FunctionTypeAnnotation {
- @override
- Code get code => new Code.fromParts([
- returnType.code,
- 'Function',
- if (typeParameters.isNotEmpty) ...[
- '<',
- typeParameters.first.identifier.name,
- if (typeParameters.first.bounds != null) ...[
- ' extends ',
- typeParameters.first.bounds!.code,
- ],
- for (TypeParameterDeclaration arg in typeParameters.skip(1)) ...[
- ', ',
- arg.identifier.name,
- if (arg.bounds != null) ...[' extends ', arg.bounds!.code],
- ],
- '>',
- ],
- '(',
- for (ParameterDeclaration positional in positionalParameters) ...[
- positional.type.code,
- ' ${positional.identifier.name}',
- ],
- if (namedParameters.isNotEmpty) ...[
- '{',
- for (ParameterDeclaration named in namedParameters) ...[
- named.type.code,
- ' ${named.identifier.name}',
- ],
- '}',
- ],
- ')',
- if (isNullable) '?',
- ]);
-
- @override
- final List<ParameterDeclarationImpl> namedParameters;
-
- @override
- final List<ParameterDeclarationImpl> positionalParameters;
-
- @override
- final TypeAnnotationImpl returnType;
-
- @override
- final List<TypeParameterDeclarationImpl> typeParameters;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.functionTypeAnnotation;
-
- FunctionTypeAnnotationImpl({
- required int id,
- required bool isNullable,
- required this.namedParameters,
- required this.positionalParameters,
- required this.returnType,
- required this.typeParameters,
- }) : super(id: id, isNullable: isNullable);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- returnType.serialize(serializer);
-
- serializer.startList();
- for (ParameterDeclarationImpl param in positionalParameters) {
- param.serialize(serializer);
- }
- serializer.endList();
-
- serializer.startList();
- for (ParameterDeclarationImpl param in namedParameters) {
- param.serialize(serializer);
- }
- serializer.endList();
-
- serializer.startList();
- for (TypeParameterDeclarationImpl typeParam in typeParameters) {
- typeParam.serialize(serializer);
- }
- serializer.endList();
- }
-}
-
-abstract class DeclarationImpl extends RemoteInstance implements Declaration {
- final IdentifierImpl identifier;
-
- DeclarationImpl({required int id, required this.identifier}) : super(id);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- identifier.serialize(serializer);
- }
-}
-
-class ParameterDeclarationImpl extends DeclarationImpl
- implements ParameterDeclaration {
- @override
- final Code? defaultValue;
-
- @override
- final bool isNamed;
-
- @override
- final bool isRequired;
-
- @override
- final TypeAnnotationImpl type;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.parameterDeclaration;
-
- ParameterDeclarationImpl({
- required int id,
- required IdentifierImpl identifier,
- required this.defaultValue,
- required this.isNamed,
- required this.isRequired,
- required this.type,
- }) : super(id: id, identifier: identifier);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- if (defaultValue == null) {
- serializer.addNull();
- } else {
- defaultValue!.serialize(serializer);
- }
- serializer.addBool(isNamed);
- serializer.addBool(isRequired);
- type.serialize(serializer);
- }
-}
-
-class TypeParameterDeclarationImpl extends DeclarationImpl
- implements TypeParameterDeclaration {
- @override
- final TypeAnnotationImpl? bounds;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
-
- TypeParameterDeclarationImpl({
- required int id,
- required IdentifierImpl identifier,
- required this.bounds,
- }) : super(id: id, identifier: identifier);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- TypeAnnotationImpl? bounds = this.bounds;
- if (bounds == null) {
- serializer.addNull();
- } else {
- bounds.serialize(serializer);
- }
- }
-}
-
-class FunctionDeclarationImpl extends DeclarationImpl
- implements FunctionDeclaration {
- @override
- final bool isAbstract;
-
- @override
- final bool isExternal;
-
- @override
- final bool isGetter;
-
- @override
- final bool isSetter;
-
- @override
- final List<ParameterDeclarationImpl> namedParameters;
-
- @override
- final List<ParameterDeclarationImpl> positionalParameters;
-
- @override
- final TypeAnnotationImpl returnType;
-
- @override
- final List<TypeParameterDeclarationImpl> typeParameters;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.functionDeclaration;
-
- FunctionDeclarationImpl({
- required int id,
- required IdentifierImpl identifier,
- required this.isAbstract,
- required this.isExternal,
- required this.isGetter,
- required this.isSetter,
- required this.namedParameters,
- required this.positionalParameters,
- required this.returnType,
- required this.typeParameters,
- }) : super(id: id, identifier: identifier);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer
- ..addBool(isAbstract)
- ..addBool(isExternal)
- ..addBool(isGetter)
- ..addBool(isSetter)
- ..startList();
- for (ParameterDeclarationImpl named in namedParameters) {
- named.serialize(serializer);
- }
- serializer
- ..endList()
- ..startList();
- for (ParameterDeclarationImpl positional in positionalParameters) {
- positional.serialize(serializer);
- }
- serializer.endList();
- returnType.serialize(serializer);
- serializer.startList();
- for (TypeParameterDeclarationImpl param in typeParameters) {
- param.serialize(serializer);
- }
- serializer.endList();
- }
-}
-
-class MethodDeclarationImpl extends FunctionDeclarationImpl
- implements MethodDeclaration {
- @override
- final IdentifierImpl definingClass;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.methodDeclaration;
-
- MethodDeclarationImpl({
- // Declaration fields
- required int id,
- required IdentifierImpl identifier,
- // Function fields
- required bool isAbstract,
- required bool isExternal,
- required bool isGetter,
- required bool isSetter,
- required List<ParameterDeclarationImpl> namedParameters,
- required List<ParameterDeclarationImpl> positionalParameters,
- required TypeAnnotationImpl returnType,
- required List<TypeParameterDeclarationImpl> typeParameters,
- // Method fields
- required this.definingClass,
- }) : super(
- id: id,
- identifier: identifier,
- isAbstract: isAbstract,
- isExternal: isExternal,
- isGetter: isGetter,
- isSetter: isSetter,
- namedParameters: namedParameters,
- positionalParameters: positionalParameters,
- returnType: returnType,
- typeParameters: typeParameters,
- );
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- definingClass.serialize(serializer);
- }
-}
-
-class ConstructorDeclarationImpl extends MethodDeclarationImpl
- implements ConstructorDeclaration {
- @override
- final bool isFactory;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.constructorDeclaration;
-
- ConstructorDeclarationImpl({
- // Declaration fields
- required int id,
- required IdentifierImpl identifier,
- // Function fields
- required bool isAbstract,
- required bool isExternal,
- required bool isGetter,
- required bool isSetter,
- required List<ParameterDeclarationImpl> namedParameters,
- required List<ParameterDeclarationImpl> positionalParameters,
- required TypeAnnotationImpl returnType,
- required List<TypeParameterDeclarationImpl> typeParameters,
- // Method fields
- required IdentifierImpl definingClass,
- // Constructor fields
- required this.isFactory,
- }) : super(
- id: id,
- identifier: identifier,
- isAbstract: isAbstract,
- isExternal: isExternal,
- isGetter: isGetter,
- isSetter: isSetter,
- namedParameters: namedParameters,
- positionalParameters: positionalParameters,
- returnType: returnType,
- typeParameters: typeParameters,
- definingClass: definingClass,
- );
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer.addBool(isFactory);
- }
-}
-
-class VariableDeclarationImpl extends DeclarationImpl
- implements VariableDeclaration {
- @override
- final ExpressionCode? initializer;
-
- @override
- final bool isExternal;
-
- @override
- final bool isFinal;
-
- @override
- final bool isLate;
-
- @override
- final TypeAnnotationImpl type;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.variableDeclaration;
-
- VariableDeclarationImpl({
- required int id,
- required IdentifierImpl identifier,
- required this.initializer,
- required this.isExternal,
- required this.isFinal,
- required this.isLate,
- required this.type,
- }) : super(id: id, identifier: identifier);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- initializer.serializeNullable(serializer);
- serializer
- ..addBool(isExternal)
- ..addBool(isFinal)
- ..addBool(isLate);
- type.serialize(serializer);
- }
-}
-
-class FieldDeclarationImpl extends VariableDeclarationImpl
- implements FieldDeclaration {
- @override
- final IdentifierImpl definingClass;
-
- FieldDeclarationImpl({
- // Declaration fields
- required int id,
- required IdentifierImpl identifier,
- // Variable fields
- required ExpressionCode? initializer,
- required bool isExternal,
- required bool isFinal,
- required bool isLate,
- required TypeAnnotationImpl type,
- // Field fields
- required this.definingClass,
- }) : super(
- id: id,
- identifier: identifier,
- initializer: initializer,
- isExternal: isExternal,
- isFinal: isFinal,
- isLate: isLate,
- type: type);
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.fieldDeclaration;
-
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- definingClass.serialize(serializer);
- }
-}
-
-abstract class TypeDeclarationImpl extends DeclarationImpl
- implements TypeDeclaration {
- @override
- final List<TypeParameterDeclarationImpl> typeParameters;
-
- TypeDeclarationImpl({
- required int id,
- required IdentifierImpl identifier,
- required this.typeParameters,
- }) : super(id: id, identifier: identifier);
-
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer..startList();
- for (TypeParameterDeclarationImpl param in typeParameters) {
- param.serialize(serializer);
- }
- serializer.endList();
- }
-}
-
-class ClassDeclarationImpl extends TypeDeclarationImpl
- implements ClassDeclaration {
- @override
- final List<TypeAnnotationImpl> interfaces;
-
- @override
- final bool isAbstract;
-
- @override
- final bool isExternal;
-
- @override
- final List<TypeAnnotationImpl> mixins;
-
- @override
- final TypeAnnotationImpl? superclass;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.classDeclaration;
-
- ClassDeclarationImpl({
- // Declaration fields
- required int id,
- required IdentifierImpl identifier,
- // TypeDeclaration fields
- required List<TypeParameterDeclarationImpl> typeParameters,
- // ClassDeclaration fields
- required this.interfaces,
- required this.isAbstract,
- required this.isExternal,
- required this.mixins,
- required this.superclass,
- }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- serializer.startList();
- for (TypeAnnotationImpl interface in interfaces) {
- interface.serialize(serializer);
- }
- serializer
- ..endList()
- ..addBool(isAbstract)
- ..addBool(isExternal)
- ..startList();
- for (TypeAnnotationImpl mixin in mixins) {
- mixin.serialize(serializer);
- }
- serializer..endList();
- superclass.serializeNullable(serializer);
- }
-}
-
-class TypeAliasDeclarationImpl extends TypeDeclarationImpl
- implements TypeAliasDeclaration {
- /// The type being aliased.
- final TypeAnnotationImpl aliasedType;
-
- @override
- RemoteInstanceKind get kind => RemoteInstanceKind.typeAliasDeclaration;
-
- TypeAliasDeclarationImpl({
- // Declaration fields
- required int id,
- required IdentifierImpl identifier,
- // TypeDeclaration fields
- required List<TypeParameterDeclarationImpl> typeParameters,
- // TypeAlias fields
- required this.aliasedType,
- }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
-
- @override
- void serialize(Serializer serializer) {
- super.serialize(serializer);
- // Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
-
- aliasedType.serialize(serializer);
- }
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
deleted file mode 100644
index 0577fa2..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
+++ /dev/null
@@ -1,712 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Defines the objects used for communication between the macro executor and
-/// the isolate or process doing the work of macro loading and execution.
-library _fe_analyzer_shared.src.macros.executor_shared.protocol;
-
-import 'package:meta/meta.dart';
-
-import '../executor.dart';
-import '../api.dart';
-import '../executor_shared/response_impls.dart';
-import 'introspection_impls.dart';
-import 'remote_instance.dart';
-import 'serialization.dart';
-import 'serialization_extensions.dart';
-
-/// Base class all requests extend, provides a unique id for each request.
-abstract class Request implements Serializable {
- final int id;
-
- final int serializationZoneId;
-
- Request({int? id, required this.serializationZoneId})
- : this.id = id ?? _next++;
-
- /// The [serializationZoneId] is a part of the header and needs to be parsed
- /// before deserializing objects, and then passed in here.
- Request.deserialize(Deserializer deserializer, this.serializationZoneId)
- : id = (deserializer..moveNext()).expectNum();
-
- /// The [serializationZoneId] needs to be separately serialized before the
- /// rest of the object. This is not done by the instances themselves but by
- /// the macro implementations.
- @mustCallSuper
- void serialize(Serializer serializer) => serializer.addNum(id);
-
- static int _next = 0;
-}
-
-/// A generic response object that contains either a response or an error, and
-/// a unique ID.
-class Response {
- final Object? response;
- final Object? error;
- final String? stackTrace;
- final int requestId;
- final MessageType responseType;
-
- Response({
- this.response,
- this.error,
- this.stackTrace,
- required this.requestId,
- required this.responseType,
- }) : assert(response != null || error != null),
- assert(response == null || error == null);
-}
-
-/// A serializable [Response], contains the message type as an enum.
-class SerializableResponse implements Response, Serializable {
- final Serializable? response;
- final MessageType responseType;
- final String? error;
- final String? stackTrace;
- final int requestId;
- final int serializationZoneId;
-
- SerializableResponse({
- this.error,
- this.stackTrace,
- required this.requestId,
- this.response,
- required this.responseType,
- required this.serializationZoneId,
- });
-
- /// You must first parse the [serializationZoneId] yourself, and then
- /// call this function in that zone, and pass the ID.
- factory SerializableResponse.deserialize(
- Deserializer deserializer, int serializationZoneId) {
- deserializer.moveNext();
- MessageType responseType = MessageType.values[deserializer.expectNum()];
- Serializable? response;
- String? error;
- String? stackTrace;
- switch (responseType) {
- case MessageType.error:
- deserializer.moveNext();
- error = deserializer.expectString();
- deserializer.moveNext();
- stackTrace = deserializer.expectNullableString();
- break;
- case MessageType.macroClassIdentifier:
- response = new MacroClassIdentifierImpl.deserialize(deserializer);
- break;
- case MessageType.macroInstanceIdentifier:
- response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
- break;
- case MessageType.macroExecutionResult:
- response = new MacroExecutionResultImpl.deserialize(deserializer);
- break;
- case MessageType.staticType:
- case MessageType.namedStaticType:
- response = RemoteInstance.deserialize(deserializer);
- break;
- case MessageType.boolean:
- response = new BooleanValue.deserialize(deserializer);
- break;
- case MessageType.declarationList:
- response = new DeclarationList.deserialize(deserializer);
- break;
- case MessageType.remoteInstance:
- deserializer.moveNext();
- if (!deserializer.checkNull()) {
- response = deserializer.expectRemoteInstance();
- }
- break;
- default:
- throw new StateError('Unexpected response type $responseType');
- }
-
- return new SerializableResponse(
- responseType: responseType,
- response: response,
- error: error,
- stackTrace: stackTrace,
- requestId: (deserializer..moveNext()).expectNum(),
- serializationZoneId: serializationZoneId);
- }
-
- void serialize(Serializer serializer) {
- serializer
- ..addNum(serializationZoneId)
- ..addNum(MessageType.response.index)
- ..addNum(responseType.index);
- switch (responseType) {
- case MessageType.error:
- serializer.addString(error!.toString());
- serializer.addNullableString(stackTrace);
- break;
- default:
- response.serializeNullable(serializer);
- }
- serializer.addNum(requestId);
- }
-}
-
-class BooleanValue implements Serializable {
- final bool value;
-
- BooleanValue(this.value);
-
- BooleanValue.deserialize(Deserializer deserializer)
- : value = (deserializer..moveNext()).expectBool();
-
- @override
- void serialize(Serializer serializer) => serializer..addBool(value);
-}
-
-/// A serialized list of [Declaration]s.
-class DeclarationList<T extends DeclarationImpl> implements Serializable {
- final List<T> declarations;
-
- DeclarationList(this.declarations);
-
- DeclarationList.deserialize(Deserializer deserializer)
- : declarations = [
- for (bool hasNext = (deserializer
- ..moveNext()
- ..expectList())
- .moveNext();
- hasNext;
- hasNext = deserializer.moveNext())
- deserializer.expectRemoteInstance(),
- ];
-
- @override
- void serialize(Serializer serializer) {
- serializer.startList();
- for (DeclarationImpl declaration in declarations) {
- declaration.serialize(serializer);
- }
- serializer.endList();
- }
-}
-
-/// A request to load a macro in this isolate.
-class LoadMacroRequest extends Request {
- final Uri library;
- final String name;
-
- LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- LoadMacroRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : library = Uri.parse((deserializer..moveNext()).expectString()),
- name = (deserializer..moveNext()).expectString(),
- super.deserialize(deserializer, serializationZoneId);
-
- @override
- void serialize(Serializer serializer) {
- serializer
- ..addNum(MessageType.loadMacroRequest.index)
- ..addString(library.toString())
- ..addString(name);
- super.serialize(serializer);
- }
-}
-
-/// A request to instantiate a macro instance.
-class InstantiateMacroRequest extends Request {
- final MacroClassIdentifier macroClass;
- final String constructorName;
- final Arguments arguments;
-
- InstantiateMacroRequest(this.macroClass, this.constructorName, this.arguments,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- InstantiateMacroRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
- constructorName = (deserializer..moveNext()).expectString(),
- arguments = new Arguments.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- @override
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.instantiateMacroRequest.index);
- macroClass.serialize(serializer);
- serializer.addString(constructorName);
- arguments.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// A request to execute a macro on a particular declaration in the types phase.
-class ExecuteTypesPhaseRequest extends Request {
- final MacroInstanceIdentifier macro;
- final DeclarationImpl declaration;
-
- ExecuteTypesPhaseRequest(this.macro, this.declaration,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- ExecuteTypesPhaseRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
- declaration = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeTypesPhaseRequest.index);
- macro.serialize(serializer);
- declaration.serialize(serializer);
-
- super.serialize(serializer);
- }
-}
-
-/// A request to execute a macro on a particular declaration in the definition
-/// phase.
-class ExecuteDeclarationsPhaseRequest extends Request {
- final MacroInstanceIdentifier macro;
- final DeclarationImpl declaration;
-
- final RemoteInstanceImpl typeResolver;
- final RemoteInstanceImpl classIntrospector;
-
- ExecuteDeclarationsPhaseRequest(
- this.macro, this.declaration, this.typeResolver, this.classIntrospector,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- ExecuteDeclarationsPhaseRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
- declaration = RemoteInstance.deserialize(deserializer),
- typeResolver = RemoteInstance.deserialize(deserializer),
- classIntrospector = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeDeclarationsPhaseRequest.index);
- macro.serialize(serializer);
- declaration.serialize(serializer);
- typeResolver.serialize(serializer);
- classIntrospector.serialize(serializer);
-
- super.serialize(serializer);
- }
-}
-
-/// A request to execute a macro on a particular declaration in the definition
-/// phase.
-class ExecuteDefinitionsPhaseRequest extends Request {
- final MacroInstanceIdentifier macro;
- final DeclarationImpl declaration;
-
- final RemoteInstanceImpl typeResolver;
- final RemoteInstanceImpl classIntrospector;
- final RemoteInstanceImpl typeDeclarationResolver;
-
- ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
- this.typeResolver, this.classIntrospector, this.typeDeclarationResolver,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- ExecuteDefinitionsPhaseRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
- declaration = RemoteInstance.deserialize(deserializer),
- typeResolver = RemoteInstance.deserialize(deserializer),
- classIntrospector = RemoteInstance.deserialize(deserializer),
- typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeDefinitionsPhaseRequest.index);
- macro.serialize(serializer);
- declaration.serialize(serializer);
- typeResolver.serialize(serializer);
- classIntrospector.serialize(serializer);
- typeDeclarationResolver.serialize(serializer);
-
- super.serialize(serializer);
- }
-}
-
-/// A request to reflect on a type annotation
-class InstantiateTypeRequest extends Request {
- final TypeAnnotationImpl typeAnnotation;
- final RemoteInstanceImpl typeResolver;
-
- InstantiateTypeRequest(this.typeAnnotation, this.typeResolver,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- InstantiateTypeRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : typeAnnotation = RemoteInstance.deserialize(deserializer),
- typeResolver = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.instantiateTypeRequest.index);
- typeAnnotation.serialize(serializer);
- typeResolver.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// A request to check if a type is exactly another type.
-class IsExactlyTypeRequest extends Request {
- final RemoteInstanceImpl leftType;
- final RemoteInstanceImpl rightType;
-
- IsExactlyTypeRequest(this.leftType, this.rightType,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- IsExactlyTypeRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : leftType = RemoteInstance.deserialize(deserializer),
- rightType = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.isExactlyTypeRequest.index);
- leftType.serialize(serializer);
- rightType.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// A request to check if a type is exactly another type.
-class IsSubtypeOfRequest extends Request {
- final RemoteInstanceImpl leftType;
- final RemoteInstanceImpl rightType;
-
- IsSubtypeOfRequest(this.leftType, this.rightType,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- IsSubtypeOfRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : leftType = RemoteInstance.deserialize(deserializer),
- rightType = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.isSubtypeOfRequest.index);
- leftType.serialize(serializer);
- rightType.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// A general request class for all requests coming from methods on the
-/// [ClassIntrospector] interface.
-class ClassIntrospectionRequest extends Request {
- final ClassDeclarationImpl classDeclaration;
- final RemoteInstanceImpl classIntrospector;
- final MessageType requestKind;
-
- ClassIntrospectionRequest(
- this.classDeclaration, this.classIntrospector, this.requestKind,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again and it should instead be passed in here.
- ClassIntrospectionRequest.deserialize(
- Deserializer deserializer, this.requestKind, int serializationZoneId)
- : classDeclaration = RemoteInstance.deserialize(deserializer),
- classIntrospector = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- @override
- void serialize(Serializer serializer) {
- serializer.addNum(requestKind.index);
- classDeclaration.serialize(serializer);
- classIntrospector.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// A request to get a [TypeDeclaration] for a [StaticType].
-class DeclarationOfRequest extends Request {
- final IdentifierImpl identifier;
- final RemoteInstanceImpl typeDeclarationResolver;
-
- DeclarationOfRequest(this.identifier, this.typeDeclarationResolver,
- {required int serializationZoneId})
- : super(serializationZoneId: serializationZoneId);
-
- /// When deserializing we have already consumed the message type, so we don't
- /// consume it again.
- DeclarationOfRequest.deserialize(
- Deserializer deserializer, int serializationZoneId)
- : identifier = RemoteInstance.deserialize(deserializer),
- typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
- super.deserialize(deserializer, serializationZoneId);
-
- @override
- void serialize(Serializer serializer) {
- serializer.addNum(MessageType.declarationOfRequest.index);
- identifier.serialize(serializer);
- typeDeclarationResolver.serialize(serializer);
- super.serialize(serializer);
- }
-}
-
-/// Client side implementation of a [TypeResolver], which creates a
-/// [ResolveTypeRequest] and passes it to a given [sendRequest] function which
-/// can return the [Response].
-class ClientTypeResolver implements TypeResolver {
- /// The actual remote instance of this type resolver.
- final RemoteInstanceImpl remoteInstance;
-
- /// The ID of the zone in which to find the original type resolver.
- final int serializationZoneId;
-
- /// A function that can send a request and return a response using an
- /// arbitrary communication channel.
- final Future<Response> Function(Request request) _sendRequest;
-
- ClientTypeResolver(this._sendRequest,
- {required this.remoteInstance, required this.serializationZoneId});
-
- @override
- Future<StaticType> instantiateType(TypeAnnotationImpl typeAnnotation) async {
- InstantiateTypeRequest request = new InstantiateTypeRequest(
- typeAnnotation, remoteInstance,
- serializationZoneId: serializationZoneId);
- RemoteInstanceImpl remoteType =
- _handleResponse(await _sendRequest(request));
- switch (remoteType.kind) {
- case RemoteInstanceKind.namedStaticType:
- return new ClientNamedStaticTypeImpl(_sendRequest,
- remoteInstance: remoteType,
- serializationZoneId: serializationZoneId);
- case RemoteInstanceKind.staticType:
- return new ClientStaticTypeImpl(_sendRequest,
- remoteInstance: remoteType,
- serializationZoneId: serializationZoneId);
- default:
- throw new StateError(
- 'Expected either a StaticType or NamedStaticType but got '
- '${remoteType.kind}');
- }
- }
-
- @override
- Future<StaticType> instantiateCode(ExpressionCode code) {
- // TODO: implement instantiateCode
- throw new UnimplementedError();
- }
-}
-
-class ClientStaticTypeImpl implements StaticType {
- /// The actual remote instance of this static type.
- final RemoteInstanceImpl remoteInstance;
-
- final int serializationZoneId;
-
- /// A function that can send a request and return a response using an
- /// arbitrary communication channel.
- final Future<Response> Function(Request request) sendRequest;
-
- ClientStaticTypeImpl(this.sendRequest,
- {required this.remoteInstance, required this.serializationZoneId});
-
- @override
- Future<bool> isExactly(ClientStaticTypeImpl other) async {
- IsExactlyTypeRequest request = new IsExactlyTypeRequest(
- this.remoteInstance, other.remoteInstance,
- serializationZoneId: serializationZoneId);
- return _handleResponse<BooleanValue>(await sendRequest(request)).value;
- }
-
- @override
- Future<bool> isSubtypeOf(ClientStaticTypeImpl other) async {
- IsSubtypeOfRequest request = new IsSubtypeOfRequest(
- remoteInstance, other.remoteInstance,
- serializationZoneId: serializationZoneId);
- return _handleResponse<BooleanValue>(await sendRequest(request)).value;
- }
-}
-
-/// Named variant of the [ClientStaticTypeImpl].
-class ClientNamedStaticTypeImpl extends ClientStaticTypeImpl
- implements NamedStaticType {
- ClientNamedStaticTypeImpl(
- Future<Response> Function(Request request) sendRequest,
- {required RemoteInstanceImpl remoteInstance,
- required int serializationZoneId})
- : super(sendRequest,
- remoteInstance: remoteInstance,
- serializationZoneId: serializationZoneId);
-}
-
-/// Client side implementation of the [ClientClassIntrospector], converts all
-/// invocations into remote RPC calls.
-class ClientClassIntrospector implements ClassIntrospector {
- /// The actual remote instance of this class introspector.
- final RemoteInstanceImpl remoteInstance;
-
- /// The ID of the zone in which to find the original type resolver.
- final int serializationZoneId;
-
- /// A function that can send a request and return a response using an
- /// arbitrary communication channel.
- final Future<Response> Function(Request request) sendRequest;
-
- ClientClassIntrospector(this.sendRequest,
- {required this.remoteInstance, required this.serializationZoneId});
-
- @override
- Future<List<ConstructorDeclaration>> constructorsOf(
- ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.constructorsOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<DeclarationList>(await sendRequest(request))
- .declarations
- // TODO: Refactor so we can remove this cast
- .cast();
- }
-
- @override
- Future<List<FieldDeclaration>> fieldsOf(ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.fieldsOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<DeclarationList>(await sendRequest(request))
- .declarations
- // TODO: Refactor so we can remove this cast
- .cast();
- }
-
- @override
- Future<List<ClassDeclaration>> interfacesOf(
- ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.interfacesOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<DeclarationList>(await sendRequest(request))
- .declarations
- // TODO: Refactor so we can remove this cast
- .cast();
- }
-
- @override
- Future<List<MethodDeclaration>> methodsOf(ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.methodsOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<DeclarationList>(await sendRequest(request))
- .declarations
- // TODO: Refactor so we can remove this cast
- .cast();
- }
-
- @override
- Future<List<ClassDeclaration>> mixinsOf(ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.mixinsOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<DeclarationList>(await sendRequest(request))
- .declarations
- // TODO: Refactor so we can remove this cast
- .cast();
- }
-
- @override
- Future<ClassDeclaration?> superclassOf(ClassDeclarationImpl clazz) async {
- ClassIntrospectionRequest request = new ClassIntrospectionRequest(
- clazz, remoteInstance, MessageType.superclassOfRequest,
- serializationZoneId: serializationZoneId);
- return _handleResponse<ClassDeclaration?>(await sendRequest(request));
- }
-}
-
-/// Client side implementation of a [TypeDeclarationResolver], converts all
-/// invocations into remote procedure calls.
-class ClientTypeDeclarationResolver implements TypeDeclarationResolver {
- /// The actual remote instance of this type resolver.
- final RemoteInstanceImpl remoteInstance;
-
- /// The ID of the zone in which to find the original type resolver.
- final int serializationZoneId;
-
- /// A function that can send a request and return a response using an
- /// arbitrary communication channel.
- final Future<Response> Function(Request request) sendRequest;
-
- ClientTypeDeclarationResolver(this.sendRequest,
- {required this.remoteInstance, required this.serializationZoneId});
-
- @override
- Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) async {
- DeclarationOfRequest request = new DeclarationOfRequest(
- identifier, remoteInstance,
- serializationZoneId: serializationZoneId);
- return _handleResponse<TypeDeclaration>(await sendRequest(request));
- }
-}
-
-/// An exception that occurred remotely, the exception object and stack trace
-/// are serialized as [String]s and both included in the [toString] output.
-class RemoteException implements Exception {
- final String error;
- final String? stackTrace;
-
- RemoteException(this.error, [this.stackTrace]);
-
- String toString() =>
- 'RemoteException: $error${stackTrace == null ? '' : '\n\n$stackTrace'}';
-}
-
-/// Either returns the actual response from [response], casted to [T], or throws
-/// a [RemoteException] with the given error and stack trace.
-T _handleResponse<T>(Response response) {
- if (response.responseType == MessageType.error) {
- throw new RemoteException(response.error!.toString(), response.stackTrace);
- }
- return response.response as T;
-}
-
-enum MessageType {
- boolean,
- constructorsOfRequest,
- declarationOfRequest,
- declarationList,
- fieldsOfRequest,
- interfacesOfRequest,
- methodsOfRequest,
- mixinsOfRequest,
- superclassOfRequest,
- error,
- executeDeclarationsPhaseRequest,
- executeDefinitionsPhaseRequest,
- executeTypesPhaseRequest,
- instantiateMacroRequest,
- instantiateTypeRequest,
- isExactlyTypeRequest,
- isSubtypeOfRequest,
- loadMacroRequest,
- remoteInstance,
- macroClassIdentifier,
- macroInstanceIdentifier,
- macroExecutionResult,
- namedStaticType,
- response,
- staticType,
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
deleted file mode 100644
index 7ba94f8..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:meta/meta.dart';
-
-import 'serialization.dart';
-import 'serialization_extensions.dart';
-
-/// The key used to store the remote instance cache in the current serialization
-/// zone (in server mode only).
-const Symbol remoteInstanceZoneKey = #remoteInstanceCache;
-
-/// On the server side we keep track of remote instances by their ID.
-///
-/// These are a part of the current serialization zone, which all serialization
-/// and deserialization must be done in.
-///
-/// This means the cache lifetime is that of the serialization zone it is run
-/// in.
-Map<int, RemoteInstance> get _remoteInstanceCache =>
- Zone.current[remoteInstanceZoneKey];
-
-/// Base class for types that need to be able to be traced back to a specific
-/// instance on the server side.
-abstract class RemoteInstance implements Serializable {
- /// The unique ID for this instance.
- final int id;
-
- /// The type of instance being encoded.
- RemoteInstanceKind get kind;
-
- /// Static, incrementing ids.
- static int _nextId = 0;
-
- /// Gets the next unique identifier.
- static int get uniqueId => _nextId++;
-
- /// On the client side [id]s are given and you should reconstruct objects with
- /// the given ID. On the server side ids should be created using
- /// [RemoteInstance.uniqueId].
- RemoteInstance(this.id);
-
- /// Retrieves a cached instance by ID.
- static T cached<T>(int id) => _remoteInstanceCache[id] as T;
-
- /// Deserializes an instance based on the current [serializationMode].
- static T deserialize<T>(Deserializer deserializer) =>
- (deserializer..moveNext()).expectRemoteInstance();
-
- /// This method should be overridden by all subclasses, which should on their
- /// first line call this super function.
- ///
- /// They should then return immediately if [serializationMode] is
- /// [SerializationMode.client], so that only an ID is sent.
- @mustCallSuper
- void serialize(Serializer serializer) {
- serializer.addNum(id);
- switch (serializationMode) {
- case SerializationMode.client:
- // We only send the ID from the client side.
- return;
- case SerializationMode.server:
- serializer.addNum(kind.index);
- _remoteInstanceCache[id] = this;
- return;
- }
- }
-
- @override
- bool operator ==(Object other) => other is RemoteInstance && id == other.id;
-}
-
-/// A remote instance which is just a pointer to some server side instance of
-/// a generic object.
-///
-/// The wrapped object is not serialized.
-class RemoteInstanceImpl extends RemoteInstance {
- /// Always null on the client side, has an actual instance on the server side.
- final Object? instance;
-
- @override
- final RemoteInstanceKind kind;
-
- RemoteInstanceImpl({
- required int id,
- this.instance,
- required this.kind,
- }) : super(id);
-}
-
-// The kinds of instances.
-enum RemoteInstanceKind {
- classDeclaration,
- classIntrospector,
- constructorDeclaration,
- fieldDeclaration,
- functionDeclaration,
- functionTypeAnnotation,
- identifier,
- namedStaticType,
- methodDeclaration,
- namedTypeAnnotation,
- parameterDeclaration,
- staticType,
- typeAliasDeclaration,
- typeParameterDeclaration,
- typeResolver,
- typeDeclarationResolver,
- variableDeclaration,
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
deleted file mode 100644
index eb4e5ae..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../executor.dart';
-import '../api.dart';
-import 'serialization.dart';
-import 'serialization_extensions.dart';
-
-/// Implementation of [MacroClassIdentifier].
-class MacroClassIdentifierImpl implements MacroClassIdentifier {
- final String id;
-
- MacroClassIdentifierImpl(Uri library, String name) : id = '$library#$name';
-
- MacroClassIdentifierImpl.deserialize(Deserializer deserializer)
- : id = (deserializer..moveNext()).expectString();
-
- void serialize(Serializer serializer) => serializer.addString(id);
-
- operator ==(other) => other is MacroClassIdentifierImpl && id == other.id;
-
- int get hashCode => id.hashCode;
-}
-
-/// Implementation of [MacroInstanceIdentifier].
-class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
- /// A single int where each bit indicates whether a specific macro interface
- /// is implemented by this macro.
- final int _interfaces;
-
- static int _next = 0;
-
- final int id;
-
- MacroInstanceIdentifierImpl._(this._interfaces) : id = _next++;
-
- factory MacroInstanceIdentifierImpl(Macro macro) {
- // Build up the interfaces value, there is a bit for each declaration/phase
- // combination (as there is an interface for each).
- int interfaces = 0;
- for (DeclarationKind declarationKind in DeclarationKind.values) {
- for (Phase phase in Phase.values) {
- int interfaceMask = _interfaceMask(declarationKind, phase);
- switch (declarationKind) {
- case DeclarationKind.clazz:
- switch (phase) {
- case Phase.types:
- if (macro is ClassTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is ClassDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is ClassDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- case DeclarationKind.constructor:
- switch (phase) {
- case Phase.types:
- if (macro is ConstructorTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is ConstructorDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is ConstructorDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- case DeclarationKind.field:
- switch (phase) {
- case Phase.types:
- if (macro is FieldTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is FieldDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is FieldDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- case DeclarationKind.function:
- switch (phase) {
- case Phase.types:
- if (macro is FunctionTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is FunctionDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is FunctionDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- case DeclarationKind.method:
- switch (phase) {
- case Phase.types:
- if (macro is MethodTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is MethodDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is MethodDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- case DeclarationKind.variable:
- switch (phase) {
- case Phase.types:
- if (macro is VariableTypesMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.declarations:
- if (macro is VariableDeclarationsMacro) {
- interfaces |= interfaceMask;
- }
- break;
- case Phase.definitions:
- if (macro is VariableDefinitionMacro) {
- interfaces |= interfaceMask;
- }
- break;
- }
- break;
- }
- }
- }
-
- return new MacroInstanceIdentifierImpl._(interfaces);
- }
-
- MacroInstanceIdentifierImpl.deserialize(Deserializer deserializer)
- : id = (deserializer..moveNext()).expectNum(),
- _interfaces = (deserializer..moveNext()).expectNum();
-
- void serialize(Serializer serializer) => serializer
- ..addNum(id)
- ..addNum(_interfaces);
-
- operator ==(other) => other is MacroInstanceIdentifierImpl && id == other.id;
-
- int get hashCode => id;
-
- @override
- bool shouldExecute(DeclarationKind declarationKind, Phase phase) {
- int mask = _interfaceMask(declarationKind, phase);
- if (declarationKind == DeclarationKind.method) {
- // Apply function macros to methods.
- mask |= _interfaceMask(DeclarationKind.function, phase);
- } else if (declarationKind == DeclarationKind.field) {
- // Apply variable macros to fields.
- mask |= _interfaceMask(DeclarationKind.variable, phase);
- }
- return _interfaces & mask != 0x0;
- }
-
- @override
- bool supportsDeclarationKind(DeclarationKind declarationKind) {
- for (Phase phase in Phase.values) {
- if (shouldExecute(declarationKind, phase)) {
- return true;
- }
- }
- return false;
- }
-
- /// The mask for a particular interface, which is a combination of a kind of
- /// declaration and a phase.
- static int _interfaceMask(DeclarationKind declarationKind, Phase phase) =>
- 0x1 << (declarationKind.index * Phase.values.length) << phase.index;
-}
-
-/// Implementation of [MacroExecutionResult].
-class MacroExecutionResultImpl implements MacroExecutionResult {
- @override
- final List<DeclarationCode> augmentations;
-
- @override
- final List<DeclarationCode> imports;
-
- MacroExecutionResultImpl({
- required this.augmentations,
- required this.imports,
- });
-
- factory MacroExecutionResultImpl.deserialize(Deserializer deserializer) {
- deserializer.moveNext();
- deserializer.expectList();
- List<DeclarationCode> augmentations = [
- for (bool hasNext = deserializer.moveNext();
- hasNext;
- hasNext = deserializer.moveNext())
- deserializer.expectCode()
- ];
- deserializer.moveNext();
- deserializer.expectList();
- List<DeclarationCode> imports = [
- for (bool hasNext = deserializer.moveNext();
- hasNext;
- hasNext = deserializer.moveNext())
- deserializer.expectCode()
- ];
-
- return new MacroExecutionResultImpl(
- augmentations: augmentations,
- imports: imports,
- );
- }
-
- void serialize(Serializer serializer) {
- serializer.startList();
- for (DeclarationCode augmentation in augmentations) {
- augmentation.serialize(serializer);
- }
- serializer.endList();
- serializer.startList();
- for (DeclarationCode import in imports) {
- import.serialize(serializer);
- }
- serializer.endList();
- }
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
deleted file mode 100644
index 89bbf59..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'remote_instance.dart';
-
-/// All serialization must be done in a serialization Zone, which tells it
-/// whether we are the client or server.
-///
-/// In [SerializationMode.server], sets up a remote instance cache to use when
-/// deserializing remote instances back to their original instance.
-T withSerializationMode<T>(SerializationMode mode, T Function() fn) =>
- runZoned(fn, zoneValues: {
- #serializationMode: mode,
- if (mode == SerializationMode.server)
- remoteInstanceZoneKey: <int, RemoteInstance>{}
- });
-
-/// Serializable interface
-abstract class Serializable {
- /// Serializes this object using [serializer].
- void serialize(Serializer serializer);
-}
-
-/// A push based object serialization interface.
-abstract class Serializer {
- /// Serializes a [String].
- void addString(String value);
-
- /// Serializes a nullable [String].
- void addNullableString(String? value);
-
- /// Serializes a [num].
- void addNum(num value);
-
- /// Serializes a nullable [num].
- void addNullableNum(num? value);
-
- /// Serializes a [bool].
- void addBool(bool value);
-
- /// Serializes a nullable [bool].
- void addNullableBool(bool? value);
-
- /// Serializes a `null` literal.
- void addNull();
-
- /// Used to signal the start of an arbitrary length list of items.
- void startList();
-
- /// Used to signal the end of an arbitrary length list of items.
- void endList();
-}
-
-/// A pull based object deserialization interface.
-///
-/// You must call [moveNext] before reading any items, and in order to advance
-/// to the next item.
-abstract class Deserializer {
- /// Checks if the current value is a null, returns `true` if so and `false`
- /// otherwise.
- bool checkNull();
-
- /// Reads the current value as a non-nullable [String].
- bool expectBool();
-
- /// Reads the current value as a nullable [bool].
- bool? expectNullableBool();
-
- /// Reads the current value as a non-nullable [String].
- T expectNum<T extends num>();
-
- /// Reads the current value as a nullable [num].
- num? expectNullableNum();
-
- /// Reads the current value as a non-nullable [String].
- String expectString();
-
- /// Reads the current value as a nullable [String].
- String? expectNullableString();
-
- /// Asserts that the current item is the start of a list.
- ///
- /// An example for how to read from a list is as follows:
- ///
- /// var json = JsonReader.fromString(source);
- /// I know it's a list of strings.
- ///
- /// ```
- /// var result = <String>[];
- /// deserializer.moveNext();
- /// deserializer.expectList();
- /// while (json.moveNext()) {
- /// result.add(json.expectString());
- /// }
- /// // Can now read later items, but need to call `moveNext` again to move
- /// // past the list.
- /// deserializer.moveNext();
- /// deserializer.expectBool();
- /// ```
- void expectList();
-
- /// Moves to the next item, returns `false` if there are no more items to
- /// read.
- ///
- /// If inside of a list, this returns `false` when the end of the list is
- /// reached, and moves back to the parent, but does not advance it, so another
- /// call to `moveNext` is needed. See example in the [expectList] docs.
- bool moveNext();
-}
-
-class JsonSerializer implements Serializer {
- /// The full result.
- final _result = <Object?>[];
-
- /// A path to the current list we are modifying.
- late List<List<Object?>> _path = [_result];
-
- /// Returns the result as an unmodifiable [Iterable].
- ///
- /// Asserts that all [List] entries have not been closed with [endList].
- Iterable<Object?> get result {
- assert(_path.length == 1);
- return _result;
- }
-
- @override
- void addBool(bool value) => _path.last.add(value);
- @override
- void addNullableBool(bool? value) => _path.last.add(value);
-
- @override
- void addNum(num value) => _path.last.add(value);
- @override
- void addNullableNum(num? value) => _path.last.add(value);
-
- @override
- void addString(String value) => _path.last.add(value);
- @override
- void addNullableString(String? value) => _path.last.add(value);
-
- @override
- void addNull() => _path.last.add(null);
-
- @override
- void startList() {
- List<Object?> sublist = [];
- _path.last.add(sublist);
- _path.add(sublist);
- }
-
- @override
- void endList() {
- _path.removeLast();
- }
-}
-
-class JsonDeserializer implements Deserializer {
- /// The root source list to read from.
- final Iterable<Object?> _source;
-
- /// The path to the current iterator we are reading from.
- late List<Iterator<Object?>> _path = [];
-
- /// Whether we have received our first [moveNext] call.
- bool _initialized = false;
-
- /// Initialize this deserializer from `_source`.
- JsonDeserializer(this._source);
-
- @override
- bool checkNull() => _expectValue<Object?>() == null;
-
- @override
- void expectList() => _path.add(_expectValue<Iterable<Object?>>().iterator);
-
- @override
- bool expectBool() => _expectValue();
- @override
- bool? expectNullableBool() => _expectValue();
-
- @override
- T expectNum<T extends num>() => _expectValue();
- @override
- num? expectNullableNum() => _expectValue();
-
- @override
- String expectString() => _expectValue();
- @override
- String? expectNullableString() => _expectValue();
-
- /// Reads the current value and casts it to [T].
- T _expectValue<T>() {
- if (!_initialized) {
- throw new StateError(
- 'You must call `moveNext()` before reading any values.');
- }
- return _path.last.current as T;
- }
-
- @override
- bool moveNext() {
- if (!_initialized) {
- _path.add(_source.iterator);
- _initialized = true;
- }
-
- // Move the current iterable, if its at the end of its items remove it from
- // the current path and return false.
- if (!_path.last.moveNext()) {
- _path.removeLast();
- return false;
- }
-
- return true;
- }
-}
-
-/// Must be set using `withSerializationMode` before doing any serialization or
-/// deserialization.
-SerializationMode get serializationMode {
- SerializationMode? mode =
- Zone.current[#serializationMode] as SerializationMode?;
- if (mode == null) {
- throw new StateError('No SerializationMode set, you must do all '
- 'serialization inside a call to `withSerializationMode`.');
- }
- return mode;
-}
-
-/// Some objects are serialized differently on the client side versus the server
-/// side. This indicates the different modes.
-enum SerializationMode {
- server,
- client,
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
deleted file mode 100644
index ff8a0b2..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
+++ /dev/null
@@ -1,299 +0,0 @@
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-
-import 'remote_instance.dart';
-import 'serialization.dart';
-import '../api.dart';
-
-extension DeserializerExtensions on Deserializer {
- T expectRemoteInstance<T>() {
- int id = expectNum();
- switch (serializationMode) {
- case SerializationMode.client:
- moveNext();
- RemoteInstanceKind kind = RemoteInstanceKind.values[expectNum()];
- switch (kind) {
- case RemoteInstanceKind.classIntrospector:
- case RemoteInstanceKind.namedStaticType:
- case RemoteInstanceKind.staticType:
- case RemoteInstanceKind.typeDeclarationResolver:
- case RemoteInstanceKind.typeResolver:
- // These are simple wrappers, just pass in the kind
- return new RemoteInstanceImpl(id: id, kind: kind) as T;
- case RemoteInstanceKind.classDeclaration:
- moveNext();
- return _expectClassDeclaration(id) as T;
- case RemoteInstanceKind.constructorDeclaration:
- moveNext();
- return _expectConstructorDeclaration(id) as T;
- case RemoteInstanceKind.fieldDeclaration:
- moveNext();
- return _expectFieldDeclaration(id) as T;
- case RemoteInstanceKind.functionDeclaration:
- moveNext();
- return _expectFunctionDeclaration(id) as T;
- case RemoteInstanceKind.functionTypeAnnotation:
- moveNext();
- return _expectFunctionTypeAnnotation(id) as T;
- case RemoteInstanceKind.identifier:
- moveNext();
- return _expectIdentifier(id) as T;
- case RemoteInstanceKind.methodDeclaration:
- moveNext();
- return _expectMethodDeclaration(id) as T;
- case RemoteInstanceKind.namedTypeAnnotation:
- moveNext();
- return _expectNamedTypeAnnotation(id) as T;
- case RemoteInstanceKind.parameterDeclaration:
- moveNext();
- return _expectParameterDeclaration(id) as T;
- case RemoteInstanceKind.typeAliasDeclaration:
- moveNext();
- return _expectTypeAliasDeclaration(id) as T;
- case RemoteInstanceKind.typeParameterDeclaration:
- moveNext();
- return _expectTypeParameterDeclaration(id) as T;
- case RemoteInstanceKind.variableDeclaration:
- moveNext();
- return _expectVariableDeclaration(id) as T;
- }
- case SerializationMode.server:
- return RemoteInstance.cached(id) as T;
- }
- }
-
- /// Helper method to read a list of [RemoteInstance]s.
- List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
- expectList();
- return [
- for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
- expectRemoteInstance(),
- ];
- }
-
- NamedTypeAnnotation _expectNamedTypeAnnotation(int id) =>
- new NamedTypeAnnotationImpl(
- id: id,
- isNullable: expectBool(),
- identifier: RemoteInstance.deserialize(this),
- typeArguments: (this..moveNext())._expectRemoteInstanceList(),
- );
-
- FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) =>
- new FunctionTypeAnnotationImpl(
- id: id,
- isNullable: expectBool(),
- returnType: RemoteInstance.deserialize(this),
- positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
- namedParameters: (this..moveNext())._expectRemoteInstanceList(),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- );
-
- Identifier _expectIdentifier(int id) => new IdentifierImpl(
- id: id,
- name: expectString(),
- );
-
- ParameterDeclaration _expectParameterDeclaration(int id) =>
- new ParameterDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- defaultValue: (this..moveNext()).checkNull() ? null : expectCode(),
- isNamed: (this..moveNext()).expectBool(),
- isRequired: (this..moveNext()).expectBool(),
- type: RemoteInstance.deserialize(this),
- );
-
- TypeParameterDeclaration _expectTypeParameterDeclaration(int id) =>
- new TypeParameterDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- bounds: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
- );
-
- FunctionDeclaration _expectFunctionDeclaration(int id) =>
- new FunctionDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- isAbstract: (this..moveNext()).expectBool(),
- isExternal: (this..moveNext()).expectBool(),
- isGetter: (this..moveNext()).expectBool(),
- isSetter: (this..moveNext()).expectBool(),
- namedParameters: (this..moveNext())._expectRemoteInstanceList(),
- positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
- returnType: RemoteInstance.deserialize(this),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- );
-
- MethodDeclaration _expectMethodDeclaration(int id) =>
- new MethodDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- isAbstract: (this..moveNext()).expectBool(),
- isExternal: (this..moveNext()).expectBool(),
- isGetter: (this..moveNext()).expectBool(),
- isSetter: (this..moveNext()).expectBool(),
- namedParameters: (this..moveNext())._expectRemoteInstanceList(),
- positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
- returnType: RemoteInstance.deserialize(this),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- definingClass: RemoteInstance.deserialize(this),
- );
-
- ConstructorDeclaration _expectConstructorDeclaration(int id) =>
- new ConstructorDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- isAbstract: (this..moveNext()).expectBool(),
- isExternal: (this..moveNext()).expectBool(),
- isGetter: (this..moveNext()).expectBool(),
- isSetter: (this..moveNext()).expectBool(),
- namedParameters: (this..moveNext())._expectRemoteInstanceList(),
- positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
- returnType: RemoteInstance.deserialize(this),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- definingClass: RemoteInstance.deserialize(this),
- isFactory: (this..moveNext()).expectBool(),
- );
-
- VariableDeclaration _expectVariableDeclaration(int id) =>
- new VariableDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- initializer: (this..moveNext()).expectNullableCode(),
- isExternal: (this..moveNext()).expectBool(),
- isFinal: (this..moveNext()).expectBool(),
- isLate: (this..moveNext()).expectBool(),
- type: RemoteInstance.deserialize(this),
- );
-
- FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- initializer: (this..moveNext()).expectNullableCode(),
- isExternal: (this..moveNext()).expectBool(),
- isFinal: (this..moveNext()).expectBool(),
- isLate: (this..moveNext()).expectBool(),
- type: RemoteInstance.deserialize(this),
- definingClass: RemoteInstance.deserialize(this),
- );
-
- ClassDeclaration _expectClassDeclaration(int id) => new ClassDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- interfaces: (this..moveNext())._expectRemoteInstanceList(),
- isAbstract: (this..moveNext()).expectBool(),
- isExternal: (this..moveNext()).expectBool(),
- mixins: (this..moveNext())._expectRemoteInstanceList(),
- superclass:
- (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
- );
-
- TypeAliasDeclaration _expectTypeAliasDeclaration(int id) =>
- new TypeAliasDeclarationImpl(
- id: id,
- identifier: expectRemoteInstance(),
- typeParameters: (this..moveNext())._expectRemoteInstanceList(),
- aliasedType: RemoteInstance.deserialize(this),
- );
-
- T expectCode<T extends Code>() {
- CodeKind kind = CodeKind.values[expectNum()];
- moveNext();
- expectList();
- List<Object> parts = [];
- while (moveNext()) {
- CodePartKind partKind = CodePartKind.values[expectNum()];
- moveNext();
- switch (partKind) {
- case CodePartKind.code:
- parts.add(expectCode());
- break;
- case CodePartKind.string:
- parts.add(expectString());
- break;
- case CodePartKind.identifier:
- parts.add(expectRemoteInstance());
- break;
- }
- }
-
- switch (kind) {
- case CodeKind.raw:
- return new Code.fromParts(parts) as T;
- case CodeKind.declaration:
- return new DeclarationCode.fromParts(parts) as T;
- case CodeKind.element:
- return new ElementCode.fromParts(parts) as T;
- case CodeKind.expression:
- return new ExpressionCode.fromParts(parts) as T;
- case CodeKind.functionBody:
- return new FunctionBodyCode.fromParts(parts) as T;
- case CodeKind.namedArgument:
- return new NamedArgumentCode.fromParts(parts) as T;
- case CodeKind.parameter:
- return new ParameterCode.fromParts(parts) as T;
- case CodeKind.statement:
- return new StatementCode.fromParts(parts) as T;
- }
- }
-
- T? expectNullableCode<T extends Code>() {
- if (checkNull()) return null;
- return expectCode();
- }
-}
-
-extension SerializeNullable on Serializable? {
- /// Either serializes a `null` literal or the object.
- void serializeNullable(Serializer serializer) {
- Serializable? self = this;
- if (self == null) {
- serializer.addNull();
- } else {
- self.serialize(serializer);
- }
- }
-}
-
-extension SerializeNullableCode on Code? {
- /// Either serializes a `null` literal or the code object.
- void serializeNullable(Serializer serializer) {
- Code? self = this;
- if (self == null) {
- serializer.addNull();
- } else {
- self.serialize(serializer);
- }
- }
-}
-
-extension SerializeCode on Code {
- void serialize(Serializer serializer) {
- serializer
- ..addNum(kind.index)
- ..startList();
- for (Object part in parts) {
- if (part is String) {
- serializer
- ..addNum(CodePartKind.string.index)
- ..addString(part);
- } else if (part is Code) {
- serializer.addNum(CodePartKind.code.index);
- part.serialize(serializer);
- } else if (part is IdentifierImpl) {
- serializer.addNum(CodePartKind.identifier.index);
- part.serialize(serializer);
- } else {
- throw new StateError('Unrecognized code part $part');
- }
- }
- serializer.endList();
- }
-}
-
-enum CodePartKind {
- string,
- code,
- identifier,
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart
deleted file mode 100644
index 9bfd0a7..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../executor.dart';
-
-/// The only public api exposed by this library, returns a [_FakeMacroExecutor].
-Future<MacroExecutor> start() async => new _FakeMacroExecutor();
-
-/// A [MacroExecutor] implementation which throws an [UnsupportedError] in all
-/// methods.
-class _FakeMacroExecutor implements MacroExecutor {
- @override
- dynamic noSuchMethod(Invocation invocation) {
- throw new UnsupportedError(
- 'Macro expansion is not supported on this platform.');
- }
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
deleted file mode 100644
index 797ffb8..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:mirrors';
-
-import 'isolate_mirrors_impl.dart';
-import '../executor_shared/introspection_impls.dart';
-import '../executor_shared/protocol.dart';
-import '../executor_shared/remote_instance.dart';
-import '../executor.dart';
-import '../api.dart';
-
-/// Returns an instance of [_IsolateMirrorMacroExecutor].
-///
-/// This is the only public api exposed by this library.
-Future<MacroExecutor> start() => _IsolateMirrorMacroExecutor.start();
-
-/// A [MacroExecutor] implementation which relies on [IsolateMirror.loadUri]
-/// in order to load macros libraries.
-///
-/// All actual work happens in a separate [Isolate], and this class serves as
-/// a bridge between that isolate and the language frontends.
-class _IsolateMirrorMacroExecutor implements MacroExecutor {
- /// The actual isolate doing macro loading and execution.
- final Isolate _macroIsolate;
-
- /// The channel used to send requests to the [_macroIsolate].
- final SendPort _sendPort;
-
- /// The stream of responses from the [_macroIsolate].
- final Stream<Response> _responseStream;
-
- /// A map of response completers by request id.
- final _responseCompleters = <int, Completer<Response>>{};
-
- /// A function that should be invoked when shutting down this executor
- /// to perform any necessary cleanup.
- final void Function() _onClose;
-
- _IsolateMirrorMacroExecutor._(
- this._macroIsolate, this._sendPort, this._responseStream, this._onClose) {
- _responseStream.listen((event) {
- Completer<Response>? completer =
- _responseCompleters.remove(event.requestId);
- if (completer == null) {
- throw new StateError(
- 'Got a response for an unrecognized request id ${event.requestId}');
- }
- completer.complete(event);
- });
- }
-
- /// Initialize an [IsolateMirrorMacroExecutor] and return it once ready.
- ///
- /// Spawns the macro isolate and sets up a communication channel.
- static Future<MacroExecutor> start() async {
- ReceivePort receivePort = new ReceivePort();
- Completer<SendPort> sendPortCompleter = new Completer<SendPort>();
- StreamController<Response> responseStreamController =
- new StreamController<Response>(sync: true);
- receivePort.listen((message) {
- if (!sendPortCompleter.isCompleted) {
- sendPortCompleter.complete(message as SendPort);
- } else {
- responseStreamController.add(message as Response);
- }
- }).onDone(responseStreamController.close);
- Isolate macroIsolate = await Isolate.spawn(spawn, receivePort.sendPort);
-
- return new _IsolateMirrorMacroExecutor._(
- macroIsolate,
- await sendPortCompleter.future,
- responseStreamController.stream,
- receivePort.close);
- }
-
- @override
- Future<String> buildAugmentationLibrary(
- Iterable<MacroExecutionResult> macroResults) {
- // TODO: implement buildAugmentationLibrary
- throw new UnimplementedError();
- }
-
- @override
- void close() {
- _onClose();
- _macroIsolate.kill();
- }
-
- @override
- Future<MacroExecutionResult> executeDeclarationsPhase(
- MacroInstanceIdentifier macro,
- Declaration declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector) {
- // TODO: implement executeDeclarationsPhase
- throw new UnimplementedError();
- }
-
- @override
- Future<MacroExecutionResult> executeDefinitionsPhase(
- MacroInstanceIdentifier macro,
- DeclarationImpl declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector,
- TypeDeclarationResolver typeDeclarationResolver) =>
- _sendRequest(new ExecuteDefinitionsPhaseRequest(
- macro,
- declaration,
- new RemoteInstanceImpl(
- instance: typeResolver,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.typeResolver),
- new RemoteInstanceImpl(
- instance: classIntrospector,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.classIntrospector),
- new RemoteInstanceImpl(
- instance: typeDeclarationResolver,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.typeDeclarationResolver),
- // Serialization zones are not necessary in this executor.
- serializationZoneId: -1));
-
- @override
- Future<MacroExecutionResult> executeTypesPhase(
- MacroInstanceIdentifier macro, Declaration declaration) {
- // TODO: implement executeTypesPhase
- throw new UnimplementedError();
- }
-
- @override
- Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) =>
- _sendRequest(
- new InstantiateMacroRequest(macroClass, constructor, arguments,
- // Serialization zones are not necessary in this executor.
- serializationZoneId: -1));
-
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) {
- if (precompiledKernelUri != null) {
- // TODO: Implement support?
- throw new UnsupportedError(
- 'The IsolateMirrorsExecutor does not support precompiled dill files');
- }
- return _sendRequest(new LoadMacroRequest(library, name,
- // Serialization zones are not necessary in this executor.
- serializationZoneId: -1));
- }
-
- /// Sends a request and returns the response, casting it to the expected
- /// type.
- Future<T> _sendRequest<T>(Request request) async {
- _sendPort.send(request);
- Completer<Response> completer = new Completer<Response>();
- _responseCompleters[request.id] = completer;
- Response response = await completer.future;
- T? result = response.response as T?;
- if (result != null) return result;
- throw response.error!;
- }
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
deleted file mode 100644
index 4c435f6..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:mirrors';
-
-import '../executor_shared/builder_impls.dart';
-import '../executor_shared/introspection_impls.dart';
-import '../executor_shared/response_impls.dart';
-import '../executor_shared/protocol.dart';
-import '../api.dart';
-
-/// Spawns a new isolate for loading and executing macros.
-void spawn(SendPort sendPort) {
- ReceivePort receivePort = new ReceivePort();
- sendPort.send(receivePort.sendPort);
- receivePort.listen((message) async {
- Response response;
- if (message is LoadMacroRequest) {
- response = await _loadMacro(message);
- } else if (message is InstantiateMacroRequest) {
- response = await _instantiateMacro(message);
- } else if (message is ExecuteDefinitionsPhaseRequest) {
- response = await _executeDefinitionsPhase(message);
- } else {
- throw new StateError('Unrecognized event type $message');
- }
- sendPort.send(response);
- });
-}
-
-/// Maps macro identifiers to class mirrors.
-final _macroClasses = <MacroClassIdentifierImpl, ClassMirror>{};
-
-/// Handles [LoadMacroRequest]s.
-Future<Response> _loadMacro(LoadMacroRequest request) async {
- try {
- MacroClassIdentifierImpl identifier =
- new MacroClassIdentifierImpl(request.library, request.name);
- if (_macroClasses.containsKey(identifier)) {
- throw new UnsupportedError(
- 'Reloading macros is not supported by this implementation');
- }
- LibraryMirror libMirror =
- await currentMirrorSystem().isolate.loadUri(request.library);
- ClassMirror macroClass =
- libMirror.declarations[new Symbol(request.name)] as ClassMirror;
- _macroClasses[identifier] = macroClass;
- return new Response(
- response: identifier,
- requestId: request.id,
- responseType: MessageType.macroClassIdentifier);
- } catch (e) {
- return new Response(
- error: e, requestId: request.id, responseType: MessageType.error);
- }
-}
-
-/// Maps macro instance identifiers to instances.
-final _macroInstances = <MacroInstanceIdentifierImpl, Macro>{};
-
-/// Handles [InstantiateMacroRequest]s.
-Future<Response> _instantiateMacro(InstantiateMacroRequest request) async {
- try {
- ClassMirror? clazz = _macroClasses[request.macroClass];
- if (clazz == null) {
- throw new ArgumentError('Unrecognized macro class ${request.macroClass}');
- }
- Macro instance = clazz.newInstance(
- new Symbol(request.constructorName), request.arguments.positional, {
- for (MapEntry<String, Object?> entry in request.arguments.named.entries)
- new Symbol(entry.key): entry.value,
- }).reflectee as Macro;
- MacroInstanceIdentifierImpl identifier =
- new MacroInstanceIdentifierImpl(instance);
- _macroInstances[identifier] = instance;
- return new Response(
- response: identifier,
- requestId: request.id,
- responseType: MessageType.macroInstanceIdentifier);
- } catch (e) {
- return new Response(
- error: e, requestId: request.id, responseType: MessageType.error);
- }
-}
-
-Future<Response> _executeDefinitionsPhase(
- ExecuteDefinitionsPhaseRequest request) async {
- try {
- Macro? instance = _macroInstances[request.macro];
- if (instance == null) {
- throw new StateError('Unrecognized macro instance ${request.macro}\n'
- 'Known instances: $_macroInstances)');
- }
- DeclarationImpl declaration = request.declaration;
- if (instance is FunctionDefinitionMacro &&
- declaration is FunctionDeclarationImpl) {
- FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
- declaration,
- request.classIntrospector.instance as ClassIntrospector,
- request.typeResolver.instance as TypeResolver,
- request.typeDeclarationResolver.instance as TypeDeclarationResolver);
- await instance.buildDefinitionForFunction(declaration, builder);
- return new Response(
- response: builder.result,
- requestId: request.id,
- responseType: MessageType.macroExecutionResult);
- } else if (instance is MethodDefinitionMacro &&
- declaration is MethodDeclarationImpl) {
- FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
- declaration,
- request.classIntrospector.instance as ClassIntrospector,
- request.typeResolver.instance as TypeResolver,
- request.typeDeclarationResolver.instance as TypeDeclarationResolver);
- await instance.buildDefinitionForMethod(declaration, builder);
- return new SerializableResponse(
- responseType: MessageType.macroExecutionResult,
- response: builder.result,
- requestId: request.id,
- serializationZoneId: request.serializationZoneId);
- } else {
- throw new UnsupportedError(
- 'Only Method and Function Definition Macros are supported currently');
- }
- } catch (e) {
- return new Response(
- error: e, requestId: request.id, responseType: MessageType.error);
- }
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
deleted file mode 100644
index cfe6602..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
+++ /dev/null
@@ -1,466 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:isolate';
-
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
-
-import '../api.dart';
-import '../executor_shared/introspection_impls.dart';
-import '../executor_shared/protocol.dart';
-import '../executor_shared/response_impls.dart';
-import '../executor_shared/serialization.dart';
-import '../executor.dart';
-
-/// Returns an instance of [_IsolatedMacroExecutor].
-///
-/// This is the only public api exposed by this library.
-Future<MacroExecutor> start() async => new _IsolatedMacroExecutor();
-
-/// A [MacroExecutor] implementation which spawns a separate isolate for each
-/// macro that is loaded. Each of these is wrapped in its own
-/// [_SingleIsolatedMacroExecutor] which requests are delegated to.
-///
-/// This implementation requires precompiled kernel files when loading macros,
-/// (you must pass a `precompiledKernelUri` to [loadMacro]).
-///
-/// Spawned isolates are not ran in the same isolate group, so objects are
-/// serialized between isolates.
-class _IsolatedMacroExecutor implements MacroExecutor {
- /// Individual executors indexed by [MacroClassIdentifier] or
- /// [MacroInstanceIdentifier].
- final _executors = <Object, _SingleIsolatedMacroExecutor>{};
-
- @override
- Future<String> buildAugmentationLibrary(
- Iterable<MacroExecutionResult> macroResults) {
- // TODO: implement buildAugmentationLibrary
- throw new UnimplementedError();
- }
-
- @override
- void close() {
- for (_SingleIsolatedMacroExecutor executor in _executors.values) {
- executor.close();
- }
- }
-
- @override
- Future<MacroExecutionResult> executeDeclarationsPhase(
- MacroInstanceIdentifier macro,
- DeclarationImpl declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector) =>
- _executors[macro]!.executeDeclarationsPhase(
- macro, declaration, typeResolver, classIntrospector);
-
- @override
- Future<MacroExecutionResult> executeDefinitionsPhase(
- MacroInstanceIdentifier macro,
- DeclarationImpl declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector,
- TypeDeclarationResolver typeDeclarationResolver) =>
- _executors[macro]!.executeDefinitionsPhase(macro, declaration,
- typeResolver, classIntrospector, typeDeclarationResolver);
-
- @override
- Future<MacroExecutionResult> executeTypesPhase(
- MacroInstanceIdentifier macro, DeclarationImpl declaration) =>
- _executors[macro]!.executeTypesPhase(macro, declaration);
-
- @override
- Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) async {
- _SingleIsolatedMacroExecutor executor = _executors[macroClass]!;
- MacroInstanceIdentifier instance =
- await executor.instantiateMacro(macroClass, constructor, arguments);
- _executors[instance] = executor;
- return instance;
- }
-
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) async {
- if (precompiledKernelUri == null) {
- throw new UnsupportedError(
- 'This environment requires a non-null `precompiledKernelUri` to be '
- 'passed when loading macros.');
- }
- MacroClassIdentifier identifier =
- new MacroClassIdentifierImpl(library, name);
- _executors.remove(identifier)?.close();
-
- _SingleIsolatedMacroExecutor executor =
- await _SingleIsolatedMacroExecutor.start(
- library, name, precompiledKernelUri);
- _executors[identifier] = executor;
- return identifier;
- }
-}
-
-class _SingleIsolatedMacroExecutor extends MacroExecutor {
- /// The stream on which we receive responses.
- final Stream<Object> messageStream;
-
- /// The send port where we should send requests.
- final SendPort sendPort;
-
- /// A function that should be invoked when shutting down this executor
- /// to perform any necessary cleanup.
- final void Function() onClose;
-
- /// A map of response completers by request id.
- final responseCompleters = <int, Completer<Response>>{};
-
- /// We need to know which serialization zone to deserialize objects in, so
- /// that we read them from the correct cache. Each request creates its own
- /// zone which it stores here by ID and then responses are deserialized in
- /// the same zone.
- static final serializationZones = <int, Zone>{};
-
- /// Incrementing identifier for the serialization zone ids.
- static int _nextSerializationZoneId = 0;
-
- _SingleIsolatedMacroExecutor(
- {required this.onClose,
- required this.messageStream,
- required this.sendPort}) {
- messageStream.listen((message) {
- withSerializationMode(SerializationMode.server, () {
- JsonDeserializer deserializer =
- new JsonDeserializer(message as List<Object?>);
- // Every object starts with a zone ID which dictates the zone in which
- // we should deserialize the message.
- deserializer.moveNext();
- int zoneId = deserializer.expectNum();
- Zone zone = serializationZones[zoneId]!;
- zone.run(() async {
- deserializer.moveNext();
- MessageType messageType =
- MessageType.values[deserializer.expectNum()];
- switch (messageType) {
- case MessageType.response:
- SerializableResponse response =
- new SerializableResponse.deserialize(deserializer, zoneId);
- Completer<Response>? completer =
- responseCompleters.remove(response.requestId);
- if (completer == null) {
- throw new StateError(
- 'Got a response for an unrecognized request id '
- '${response.requestId}');
- }
- completer.complete(response);
- break;
- case MessageType.instantiateTypeRequest:
- InstantiateTypeRequest request =
- new InstantiateTypeRequest.deserialize(deserializer, zoneId);
- StaticType instance =
- await (request.typeResolver.instance as TypeResolver)
- .instantiateType(request.typeAnnotation);
- SerializableResponse response = new SerializableResponse(
- response: new RemoteInstanceImpl(
- id: RemoteInstance.uniqueId,
- instance: instance,
- kind: instance is NamedStaticType
- ? RemoteInstanceKind.namedStaticType
- : RemoteInstanceKind.staticType),
- requestId: request.id,
- responseType: instance is NamedStaticType
- ? MessageType.namedStaticType
- : MessageType.staticType,
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.isExactlyTypeRequest:
- IsExactlyTypeRequest request =
- new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
- StaticType leftType = request.leftType.instance as StaticType;
- StaticType rightType = request.rightType.instance as StaticType;
- SerializableResponse response = new SerializableResponse(
- response:
- new BooleanValue(await leftType.isExactly(rightType)),
- requestId: request.id,
- responseType: MessageType.boolean,
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.isSubtypeOfRequest:
- IsSubtypeOfRequest request =
- new IsSubtypeOfRequest.deserialize(deserializer, zoneId);
- StaticType leftType = request.leftType.instance as StaticType;
- StaticType rightType = request.rightType.instance as StaticType;
- SerializableResponse response = new SerializableResponse(
- response:
- new BooleanValue(await leftType.isSubtypeOf(rightType)),
- requestId: request.id,
- responseType: MessageType.boolean,
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.declarationOfRequest:
- DeclarationOfRequest request =
- new DeclarationOfRequest.deserialize(deserializer, zoneId);
- TypeDeclarationResolver resolver = request
- .typeDeclarationResolver.instance as TypeDeclarationResolver;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.remoteInstance,
- response: (await resolver.declarationOf(request.identifier)
- // TODO: Consider refactoring to avoid the need for this.
- as TypeDeclarationImpl),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.constructorsOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.declarationList,
- response: new DeclarationList((await classIntrospector
- .constructorsOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- .cast<ConstructorDeclarationImpl>()),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.fieldsOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.declarationList,
- response: new DeclarationList((await classIntrospector
- .fieldsOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- .cast<FieldDeclarationImpl>()),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.interfacesOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.declarationList,
- response: new DeclarationList((await classIntrospector
- .interfacesOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- .cast<ClassDeclarationImpl>()),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.methodsOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.declarationList,
- response: new DeclarationList((await classIntrospector
- .methodsOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- .cast<MethodDeclarationImpl>()),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.mixinsOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.declarationList,
- response: new DeclarationList((await classIntrospector
- .mixinsOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- .cast<ClassDeclarationImpl>()),
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- case MessageType.superclassOfRequest:
- ClassIntrospectionRequest request =
- new ClassIntrospectionRequest.deserialize(
- deserializer, messageType, zoneId);
- ClassIntrospector classIntrospector =
- request.classIntrospector.instance as ClassIntrospector;
- SerializableResponse response = new SerializableResponse(
- requestId: request.id,
- responseType: MessageType.remoteInstance,
- response: (await classIntrospector
- .superclassOf(request.classDeclaration))
- // TODO: Consider refactoring to avoid the need for this.
- as ClassDeclarationImpl?,
- serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
- response.serialize(serializer);
- sendPort.send(serializer.result);
- break;
- default:
- throw new StateError('Unexpected message type $messageType');
- }
- });
- });
- });
- }
-
- static Future<_SingleIsolatedMacroExecutor> start(
- Uri library, String name, Uri precompiledKernelUri) async {
- ReceivePort receivePort = new ReceivePort();
- Isolate isolate =
- await Isolate.spawnUri(precompiledKernelUri, [], receivePort.sendPort);
- Completer<SendPort> sendPortCompleter = new Completer();
- StreamController<Object> messageStreamController =
- new StreamController(sync: true);
- receivePort.listen((message) {
- if (!sendPortCompleter.isCompleted) {
- sendPortCompleter.complete(message as SendPort);
- } else {
- messageStreamController.add(message);
- }
- }).onDone(messageStreamController.close);
-
- return new _SingleIsolatedMacroExecutor(
- onClose: () {
- receivePort.close();
- isolate.kill();
- },
- messageStream: messageStreamController.stream,
- sendPort: await sendPortCompleter.future);
- }
-
- @override
- void close() => onClose();
-
- /// These calls are handled by the higher level executor.
- @override
- Future<String> buildAugmentationLibrary(
- Iterable<MacroExecutionResult> macroResults) =>
- throw new StateError('Unreachable');
-
- @override
- Future<MacroExecutionResult> executeDeclarationsPhase(
- MacroInstanceIdentifier macro,
- DeclarationImpl declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector) =>
- _sendRequest((zoneId) => new ExecuteDeclarationsPhaseRequest(
- macro,
- declaration,
- new RemoteInstanceImpl(
- instance: typeResolver,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.typeResolver),
- new RemoteInstanceImpl(
- instance: classIntrospector,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.classIntrospector),
- serializationZoneId: zoneId));
-
- @override
- Future<MacroExecutionResult> executeDefinitionsPhase(
- MacroInstanceIdentifier macro,
- DeclarationImpl declaration,
- TypeResolver typeResolver,
- ClassIntrospector classIntrospector,
- TypeDeclarationResolver typeDeclarationResolver) =>
- _sendRequest((zoneId) => new ExecuteDefinitionsPhaseRequest(
- macro,
- declaration,
- new RemoteInstanceImpl(
- instance: typeResolver,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.typeResolver),
- new RemoteInstanceImpl(
- instance: classIntrospector,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.classIntrospector),
- new RemoteInstanceImpl(
- instance: typeDeclarationResolver,
- id: RemoteInstance.uniqueId,
- kind: RemoteInstanceKind.typeDeclarationResolver),
- serializationZoneId: zoneId));
-
- @override
- Future<MacroExecutionResult> executeTypesPhase(
- MacroInstanceIdentifier macro, DeclarationImpl declaration) =>
- _sendRequest((zoneId) => new ExecuteTypesPhaseRequest(macro, declaration,
- serializationZoneId: zoneId));
-
- @override
- Future<MacroInstanceIdentifier> instantiateMacro(
- MacroClassIdentifier macroClass,
- String constructor,
- Arguments arguments) =>
- _sendRequest((zoneId) => new InstantiateMacroRequest(
- macroClass, constructor, arguments,
- serializationZoneId: zoneId));
-
- /// These calls are handled by the higher level executor.
- @override
- Future<MacroClassIdentifier> loadMacro(Uri library, String name,
- {Uri? precompiledKernelUri}) =>
- throw new StateError('Unreachable');
-
- /// Creates a [Request] with a given serialization zone ID, and handles the
- /// response, casting it to the expected type or throwing the error provided.
- Future<T> _sendRequest<T>(Request Function(int) requestFactory) =>
- withSerializationMode(SerializationMode.server, () async {
- int zoneId = _nextSerializationZoneId++;
- serializationZones[zoneId] = Zone.current;
- Request request = requestFactory(zoneId);
- JsonSerializer serializer = new JsonSerializer();
- // It is our responsibility to add the zone ID header.
- serializer.addNum(zoneId);
- request.serialize(serializer);
- sendPort.send(serializer.result);
- Completer<Response> completer = new Completer<Response>();
- responseCompleters[request.id] = completer;
- try {
- Response response = await completer.future;
- T? result = response.response as T?;
- if (result != null) return result;
- throw new RemoteException(
- response.error!.toString(), response.stackTrace);
- } finally {
- // Clean up the zone after the request is done.
- serializationZones.remove(zoneId);
- }
- });
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 027c7bb..a9ec81e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1902,15 +1902,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeContinueLabelNotTarget = messageContinueLabelNotTarget;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageContinueLabelNotTarget = const MessageCode(
- "ContinueLabelNotTarget",
- analyzerCodes: <String>["LABEL_UNDEFINED"],
- problemMessage: r"""Target of continue must be a label.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeContinueOutsideOfLoop = messageContinueOutsideOfLoop;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2770,6 +2761,33 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumConstructorSuperInitializer =
+ messageEnumConstructorSuperInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumConstructorSuperInitializer = const MessageCode(
+ "EnumConstructorSuperInitializer",
+ problemMessage: r"""Enum constructors can't contain super-initializers.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumConstructorTearoff = messageEnumConstructorTearoff;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumConstructorTearoff = const MessageCode(
+ "EnumConstructorTearoff",
+ problemMessage: r"""Enum constructors can't be torn off.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumContainsValuesDeclaration =
+ messageEnumContainsValuesDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumContainsValuesDeclaration = const MessageCode(
+ "EnumContainsValuesDeclaration",
+ problemMessage:
+ r"""Enums can't contain declarations of members with the name 'values'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeEnumDeclarationEmpty = messageEnumDeclarationEmpty;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2799,6 +2817,41 @@
r"""Missing arguments in enum constructor invocation.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumFactoryRedirectsToConstructor =
+ messageEnumFactoryRedirectsToConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumFactoryRedirectsToConstructor = const MessageCode(
+ "EnumFactoryRedirectsToConstructor",
+ problemMessage:
+ r"""Enum factory constructors can't redirect to generative constructors.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+ templateEnumImplementerContainsValuesDeclaration =
+ const Template<Message Function(String name)>(
+ problemMessageTemplate:
+ r"""'#name' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.""",
+ withArguments: _withArgumentsEnumImplementerContainsValuesDeclaration);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+ codeEnumImplementerContainsValuesDeclaration =
+ const Code<Message Function(String name)>(
+ "EnumImplementerContainsValuesDeclaration",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsEnumImplementerContainsValuesDeclaration(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeEnumImplementerContainsValuesDeclaration,
+ problemMessage:
+ """'${name}' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeEnumInClass = messageEnumInClass;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2817,6 +2870,15 @@
problemMessage: r"""Enums can't be instantiated.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumNonConstConstructor = messageEnumNonConstConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumNonConstConstructor = const MessageCode(
+ "EnumNonConstConstructor",
+ problemMessage:
+ r"""Generative enum constructors must be marked as 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateEnumSupertypeOfNonAbstractClass =
const Template<Message Function(String name)>(
@@ -6940,6 +7002,34 @@
problemMessage: r"""'loadLibrary' takes no arguments.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateMacroClassNotDeclaredMacro = const Template<
+ Message Function(String name)>(
+ problemMessageTemplate:
+ r"""Non-abstract class '#name' implements 'Macro' but isn't declared as a macro class.""",
+ correctionMessageTemplate: r"""Try adding the 'macro' class modifier.""",
+ withArguments: _withArgumentsMacroClassNotDeclaredMacro);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeMacroClassNotDeclaredMacro =
+ const Code<Message Function(String name)>(
+ "MacroClassNotDeclaredMacro",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMacroClassNotDeclaredMacro(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeMacroClassNotDeclaredMacro,
+ problemMessage:
+ """Non-abstract class '${name}' implements 'Macro' but isn't declared as a macro class.""",
+ correctionMessage: """Try adding the 'macro' class modifier.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMainNotFunctionDeclaration =
messageMainNotFunctionDeclaration;
@@ -7378,6 +7468,37 @@
problemMessage: r"""Can't have more than one 'super' initializer.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String string,
+ String
+ string2)> templateMultipleClauses = const Template<
+ Message Function(String string, String string2)>(
+ problemMessageTemplate:
+ r"""Each '#string' definition can have at most one '#string2' clause.""",
+ correctionMessageTemplate:
+ r"""Try combining all of the '#string2' clauses into a single clause.""",
+ withArguments: _withArgumentsMultipleClauses);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+ codeMultipleClauses =
+ const Code<Message Function(String string, String string2)>(
+ "MultipleClauses",
+ index: 121);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMultipleClauses(String string, String string2) {
+ if (string.isEmpty) throw 'No string provided';
+ if (string2.isEmpty) throw 'No string provided';
+ return new Message(codeMultipleClauses,
+ problemMessage:
+ """Each '${string}' definition can have at most one '${string2}' clause.""",
+ correctionMessage: """Try combining all of the '${string2}' clauses into a single clause.""",
+ arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMultipleExtends = messageMultipleExtends;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7685,6 +7806,46 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateNonAugmentationClassMemberConflict = const Template<
+ Message Function(String name)>(
+ problemMessageTemplate:
+ r"""Member '#name' conflicts with an existing member of the same name in the augmented class.""",
+ correctionMessageTemplate:
+ r"""Try changing the name to an existing member or adding an 'augment' modifier.""",
+ withArguments: _withArgumentsNonAugmentationClassMemberConflict);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+ codeNonAugmentationClassMemberConflict =
+ const Code<Message Function(String name)>(
+ "NonAugmentationClassMemberConflict",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonAugmentationClassMemberConflict(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeNonAugmentationClassMemberConflict,
+ problemMessage:
+ """Member '${name}' conflicts with an existing member of the same name in the augmented class.""",
+ correctionMessage: """Try changing the name to an existing member or adding an 'augment' modifier.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonAugmentationClassMemberConflictCause =
+ messageNonAugmentationClassMemberConflictCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonAugmentationClassMemberConflictCause =
+ const MessageCode("NonAugmentationClassMemberConflictCause",
+ severity: Severity.context,
+ problemMessage: r"""This is the existing member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeNonConstConstructor = messageNonConstConstructor;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8271,6 +8432,37 @@
correctionMessage: r"""Try removing the type parameters.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String string,
+ String
+ string2)> templateOutOfOrderClauses = const Template<
+ Message Function(String string, String string2)>(
+ problemMessageTemplate:
+ r"""The '#string' clause must come before the '#string2' clause.""",
+ correctionMessageTemplate:
+ r"""Try moving the '#string' clause before the '#string2' clause.""",
+ withArguments: _withArgumentsOutOfOrderClauses);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+ codeOutOfOrderClauses =
+ const Code<Message Function(String string, String string2)>(
+ "OutOfOrderClauses",
+ index: 122);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOutOfOrderClauses(String string, String string2) {
+ if (string.isEmpty) throw 'No string provided';
+ if (string2.isEmpty) throw 'No string provided';
+ return new Message(codeOutOfOrderClauses,
+ problemMessage:
+ """The '${string}' clause must come before the '${string2}' clause.""",
+ correctionMessage: """Try moving the '${string}' clause before the '${string2}' clause.""",
+ arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)> templateOverriddenMethodCause =
const Template<Message Function(String name)>(
problemMessageTemplate: r"""This is the overridden method ('#name').""",
@@ -10225,6 +10417,44 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeUnexpectedTokens = messageUnexpectedTokens;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageUnexpectedTokens = const MessageCode(
+ "UnexpectedTokens",
+ index: 123,
+ problemMessage: r"""Unexpected tokens.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateUnmatchedAugmentationClassMember = const Template<
+ Message Function(String name)>(
+ problemMessageTemplate:
+ r"""Augmentation member '#name' doesn't match a member in the augmented class.""",
+ correctionMessageTemplate:
+ r"""Try changing the name to an existing member or removing the 'augment' modifier.""",
+ withArguments: _withArgumentsUnmatchedAugmentationClassMember);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeUnmatchedAugmentationClassMember =
+ const Code<Message Function(String name)>(
+ "UnmatchedAugmentationClassMember",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnmatchedAugmentationClassMember(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeUnmatchedAugmentationClassMember,
+ problemMessage:
+ """Augmentation member '${name}' doesn't match a member in the augmented class.""",
+ correctionMessage: """Try changing the name to an existing member or removing the 'augment' modifier.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String string, Token token)>
templateUnmatchedToken =
const Template<Message Function(String string, Token token)>(
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index 9741d8c..cf3476b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -61,9 +61,10 @@
}
@override
- void beginClassDeclaration(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {
- listener?.beginClassDeclaration(begin, abstractToken, macroToken, name);
+ void beginClassDeclaration(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
+ listener?.beginClassDeclaration(
+ begin, abstractToken, macroToken, augmentToken, name);
}
@override
@@ -318,19 +319,21 @@
@override
void beginMethod(
DeclarationKind declarationKind,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
Token? varFinalOrConst,
Token? getOrSet,
Token name) {
- listener?.beginMethod(declarationKind, externalToken, staticToken,
- covariantToken, varFinalOrConst, getOrSet, name);
+ listener?.beginMethod(declarationKind, augmentToken, externalToken,
+ staticToken, covariantToken, varFinalOrConst, getOrSet, name);
}
@override
- void beginMixinDeclaration(Token mixinKeyword, Token name) {
- listener?.beginMixinDeclaration(mixinKeyword, name);
+ void beginMixinDeclaration(
+ Token? augmentToken, Token mixinKeyword, Token name) {
+ listener?.beginMixinDeclaration(augmentToken, mixinKeyword, name);
}
@override
@@ -339,10 +342,10 @@
}
@override
- void beginNamedMixinApplication(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {
+ void beginNamedMixinApplication(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
listener?.beginNamedMixinApplication(
- begin, abstractToken, macroToken, name);
+ begin, abstractToken, macroToken, augmentToken, name);
}
@override
@@ -416,8 +419,9 @@
}
@override
- void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
- listener?.beginTopLevelMethod(lastConsumed, externalToken);
+ void beginTopLevelMethod(
+ Token lastConsumed, Token? augmentToken, Token? externalToken) {
+ listener?.beginTopLevelMethod(lastConsumed, augmentToken, externalToken);
}
@override
@@ -545,6 +549,7 @@
@override
void endClassFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -555,6 +560,7 @@
Token endToken) {
listener?.endClassFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -673,6 +679,7 @@
@override
void endEnumFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -683,6 +690,7 @@
Token endToken) {
listener?.endClassFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -728,6 +736,7 @@
@override
void endExtensionFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -738,6 +747,7 @@
Token endToken) {
listener?.endExtensionFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -883,8 +893,8 @@
}
@override
- void endImport(Token importKeyword, Token? semicolon) {
- listener?.endImport(importKeyword, semicolon);
+ void endImport(Token importKeyword, Token? augmentToken, Token? semicolon) {
+ listener?.endImport(importKeyword, augmentToken, semicolon);
}
@override
@@ -976,6 +986,7 @@
@override
void endMixinFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -986,6 +997,7 @@
Token endToken) {
listener?.endMixinFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -1095,14 +1107,23 @@
void beginFields(
DeclarationKind declarationKind,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
Token? lateToken,
Token? varFinalOrConst,
Token lastConsumed) {
- listener?.beginFields(declarationKind, abstractToken, externalToken,
- staticToken, covariantToken, lateToken, varFinalOrConst, lastConsumed);
+ listener?.beginFields(
+ declarationKind,
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ lastConsumed);
}
@override
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
index 6e4c96b..4621543 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -124,8 +124,12 @@
}
// Recovery
- if (isOneOfOrEof(identifier, followingValues) ||
- looksLikeStartOfNextTopLevelDeclaration(identifier)) {
+ if (isOneOfOrEof(identifier, followingValues)) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: codes.templateExpectedIdentifier.withArguments(identifier));
+ } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) &&
+ (identifier.next == null ||
+ !isOneOfOrEof(identifier.next!, followingValues))) {
identifier = parser.insertSyntheticIdentifier(token, this,
message: codes.templateExpectedIdentifier.withArguments(identifier));
} else {
@@ -603,8 +607,12 @@
isOneOfOrEof(identifier.next!, followingValues)) {
parser.reportRecoverableErrorWithToken(
identifier, codes.templateBuiltInIdentifierInDeclaration);
- } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
- isOneOfOrEof(identifier, followingValues)) {
+ } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) &&
+ (identifier.next == null ||
+ !isOneOfOrEof(identifier.next!, followingValues))) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: codes.templateExpectedIdentifier.withArguments(identifier));
+ } else if (isOneOfOrEof(identifier, followingValues)) {
identifier = parser.insertSyntheticIdentifier(token, this,
message: codes.templateExpectedIdentifier.withArguments(identifier));
} else {
@@ -802,8 +810,12 @@
}
// Recovery
- if (isOneOfOrEof(identifier, followingValues) ||
- looksLikeStartOfNextTopLevelDeclaration(identifier)) {
+ if (isOneOfOrEof(identifier, followingValues)) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: codes.templateExpectedIdentifier.withArguments(identifier));
+ } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) &&
+ (identifier.next == null ||
+ !isOneOfOrEof(identifier.next!, followingValues))) {
identifier = parser.insertSyntheticIdentifier(token, this,
message: codes.templateExpectedIdentifier.withArguments(identifier));
} else {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 2f5e2a4..d31bac8b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -126,8 +126,8 @@
/// (or extraneous modifiers in the case of recovery) preceding [name].
///
/// At this point we have parsed the name and type parameter declarations.
- void beginClassDeclaration(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {}
+ void beginClassDeclaration(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {}
/// Handle an extends clause in a class declaration. Substructures:
/// - supertype (may be a mixin application)
@@ -186,7 +186,8 @@
}
/// Handle the beginning of a mixin declaration.
- void beginMixinDeclaration(Token mixinKeyword, Token name) {}
+ void beginMixinDeclaration(
+ Token? augmentToken, Token mixinKeyword, Token name) {}
/// Handle an on clause in a mixin declaration. Substructures:
/// - implemented types
@@ -436,6 +437,7 @@
/// Started by [beginFields].
void endClassFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -456,6 +458,7 @@
/// Started by [beginFields].
void endMixinFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -465,8 +468,17 @@
Token beginToken,
Token endToken) {
// TODO(danrubel): push implementation into subclasses
- endClassFields(abstractToken, externalToken, staticToken, covariantToken,
- lateToken, varFinalOrConst, count, beginToken, endToken);
+ endClassFields(
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ count,
+ beginToken,
+ endToken);
}
/// Handle the end of a extension field declaration. Substructures:
@@ -478,6 +490,7 @@
/// Started by [beginFields].
void endExtensionFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -487,8 +500,17 @@
Token beginToken,
Token endToken) {
// TODO(danrubel): push implementation into subclasses
- endClassFields(abstractToken, externalToken, staticToken, covariantToken,
- lateToken, varFinalOrConst, count, beginToken, endToken);
+ endClassFields(
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ count,
+ beginToken,
+ endToken);
}
/// Handle the end of an enum field declaration. Substructures:
@@ -500,6 +522,7 @@
/// Started by [beginFields].
void endEnumFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -508,8 +531,17 @@
int count,
Token beginToken,
Token endToken) {
- endClassFields(abstractToken, externalToken, staticToken, covariantToken,
- lateToken, varFinalOrConst, count, beginToken, endToken);
+ endClassFields(
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ count,
+ beginToken,
+ endToken);
}
/// Handle the end of an enum method declaration. Substructures:
@@ -720,8 +752,8 @@
/// (or extraneous modifiers in the case of recovery) preceding [name].
///
/// At this point we have parsed the name and type parameter declarations.
- void beginNamedMixinApplication(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {}
+ void beginNamedMixinApplication(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {}
/// Handle a named mixin application with clause (e.g. "A with B, C").
/// Substructures:
@@ -801,7 +833,7 @@
/// - conditional uris
/// - prefix identifier
/// - combinators
- void endImport(Token importKeyword, Token? semicolon) {
+ void endImport(Token importKeyword, Token? augmentToken, Token? semicolon) {
logEvent("Import");
}
@@ -977,6 +1009,7 @@
/// [endMixinMethod].
void beginMethod(
DeclarationKind declarationKind,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -1249,6 +1282,7 @@
void beginFields(
DeclarationKind declarationKind,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -1276,7 +1310,8 @@
logEvent("TopLevelFields");
}
- void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {}
+ void beginTopLevelMethod(
+ Token lastConsumed, Token? augmentToken, Token? externalToken) {}
/// Handle the end of a top level method. Substructures:
/// - metadata
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
index a062b38..99e4582 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
@@ -34,9 +34,10 @@
/// This class is used to parse modifiers in most locations where modifiers
/// can occur, but does not call handleModifier or handleModifiers.
-class ModifierRecoveryContext {
+class ModifierContext {
final Parser parser;
Token? abstractToken;
+ Token? augmentToken;
Token? constToken;
Token? covariantToken;
Token? externalToken;
@@ -47,12 +48,9 @@
Token? varToken;
// Set `true` when parsing modifiers after the `factory` token.
- bool afterFactory = false;
+ bool _afterFactory = false;
- // TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
- // with this class.
-
- ModifierRecoveryContext(this.parser);
+ ModifierContext(this.parser);
set staticOrCovariant(Token? staticOrCovariant) {
if (staticOrCovariant == null) {
@@ -94,9 +92,76 @@
}
}
+ /// Parse modifiers for class declarations.
+ Token parseClassModifiers(Token token, Token keyword) {
+ token = _parseModifiers(token);
+ if (constToken != null) {
+ reportTopLevelModifierError(constToken!, keyword);
+ }
+ if (externalToken != null) {
+ reportTopLevelModifierError(externalToken!, keyword);
+ }
+ reportExtraneousModifier(covariantToken);
+ reportExtraneousModifier(finalToken);
+ reportExtraneousModifier(lateToken);
+ reportExtraneousModifier(requiredToken);
+ reportExtraneousModifier(staticToken);
+ reportExtraneousModifier(varToken);
+ return token;
+ }
+
+ /// Parse modifiers for enum declarations.
+ Token parseEnumModifiers(Token token, Token keyword) {
+ token = _parseModifiers(token);
+ reportTopLevelModifierError(constToken, keyword);
+ reportTopLevelModifierError(externalToken, keyword);
+ reportExtraneousModifier(abstractToken);
+ // TODO(johnniwinther): Should we support 'augment' on enums.
+ reportExtraneousModifier(augmentToken);
+ reportExtraneousModifier(covariantToken);
+ reportExtraneousModifier(finalToken);
+ reportExtraneousModifier(lateToken);
+ reportExtraneousModifier(requiredToken);
+ reportExtraneousModifier(staticToken);
+ reportExtraneousModifier(varToken);
+ return token;
+ }
+
+ /// Parse modifiers for mixin declarations.
+ Token parseMixinModifiers(Token token, Token keyword) {
+ token = _parseModifiers(token);
+ reportTopLevelModifierError(constToken, keyword);
+ reportTopLevelModifierError(externalToken, keyword);
+ reportExtraneousModifier(abstractToken);
+ reportExtraneousModifier(covariantToken);
+ reportExtraneousModifier(finalToken);
+ reportExtraneousModifier(lateToken);
+ reportExtraneousModifier(requiredToken);
+ reportExtraneousModifier(staticToken);
+ reportExtraneousModifier(varToken);
+ return token;
+ }
+
+ /// Parse modifiers for library, import, export, part (of) directives and
+ /// typedef and extension declarations.
+ Token parseTopLevelKeywordModifiers(Token token, Token keyword) {
+ token = _parseModifiers(token);
+ reportTopLevelModifierError(constToken, keyword);
+ reportTopLevelModifierError(externalToken, keyword);
+ reportExtraneousModifier(abstractToken);
+ reportExtraneousModifier(augmentToken);
+ reportExtraneousModifier(covariantToken);
+ reportExtraneousModifier(finalToken);
+ reportExtraneousModifier(lateToken);
+ reportExtraneousModifier(requiredToken);
+ reportExtraneousModifier(staticToken);
+ reportExtraneousModifier(varToken);
+ return token;
+ }
+
/// Parse modifiers for class methods and fields.
Token parseClassMemberModifiers(Token token) {
- token = parseModifiers(token);
+ token = _parseModifiers(token);
reportExtraneousModifier(requiredToken);
return token;
}
@@ -104,7 +169,7 @@
/// Parse modifiers for formal parameters.
Token parseFormalParameterModifiers(
Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
- token = parseModifiers(token);
+ token = _parseModifiers(token);
if (parameterKind != FormalParameterKind.optionalNamed) {
reportExtraneousModifier(requiredToken);
@@ -133,8 +198,8 @@
/// Parse modifiers after the `factory` token.
Token parseModifiersAfterFactory(Token token) {
- afterFactory = true;
- token = parseModifiers(token);
+ _afterFactory = true;
+ token = _parseModifiers(token);
if (abstractToken != null) {
parser.reportRecoverableError(
abstractToken!, codes.messageAbstractClassMember);
@@ -145,8 +210,8 @@
}
/// Parse modifiers for top level functions and fields.
- Token parseTopLevelModifiers(Token token) {
- token = parseModifiers(token);
+ Token parseTopLevelMemberModifiers(Token token) {
+ token = _parseModifiers(token);
reportExtraneousModifier(abstractToken);
reportExtraneousModifier(covariantToken);
reportExtraneousModifier(requiredToken);
@@ -156,7 +221,7 @@
/// Parse modifiers for variable declarations.
Token parseVariableDeclarationModifiers(Token token) {
- token = parseModifiers(token);
+ token = _parseModifiers(token);
reportExtraneousModifier(abstractToken);
reportExtraneousModifier(covariantToken);
reportExtraneousModifier(externalToken);
@@ -176,34 +241,36 @@
/// `static` or `covariant`. The first non-null parameter of
/// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
/// in that order, and the others ignored.
- Token parseModifiers(Token token) {
+ Token _parseModifiers(Token token) {
// Process invalid and out-of-order modifiers
Token next = token.next!;
while (true) {
final String? value = next.stringValue;
if (isModifier(next)) {
if (identical('abstract', value)) {
- token = parseAbstract(token);
+ token = _parseAbstract(token);
+ } else if (identical('augment', value)) {
+ token = _parseAugment(token);
} else if (identical('const', value)) {
- token = parseConst(token);
+ token = _parseConst(token);
} else if (identical('covariant', value)) {
- token = parseCovariant(token);
+ token = _parseCovariant(token);
} else if (identical('external', value)) {
- token = parseExternal(token);
+ token = _parseExternal(token);
} else if (identical('final', value)) {
- token = parseFinal(token);
+ token = _parseFinal(token);
} else if (identical('late', value)) {
- token = parseLate(token);
+ token = _parseLate(token);
} else if (identical('required', value)) {
- token = parseRequired(token);
+ token = _parseRequired(token);
} else if (identical('static', value)) {
- token = parseStatic(token);
+ token = _parseStatic(token);
} else if (identical('var', value)) {
- token = parseVar(token);
+ token = _parseVar(token);
} else {
throw 'Internal Error: Unhandled modifier: $value';
}
- } else if (afterFactory && identical('factory', value)) {
+ } else if (_afterFactory && identical('factory', value)) {
parser.reportRecoverableErrorWithToken(
next, codes.templateDuplicatedModifier);
token = next;
@@ -215,7 +282,7 @@
return token;
}
- Token parseAbstract(Token token) {
+ Token _parseAbstract(Token token) {
Token next = token.next!;
assert(optional('abstract', next));
if (abstractToken == null) {
@@ -235,13 +302,45 @@
return next;
}
- Token parseConst(Token token) {
+ Token _parseAugment(Token token) {
+ Token next = token.next!;
+ assert(optional('augment', next));
+ if (augmentToken == null) {
+ augmentToken = next;
+
+ if (varFinalOrConst != null) {
+ reportModifierOutOfOrder(next, varFinalOrConst!.lexeme);
+ } else if (abstractToken != null) {
+ reportModifierOutOfOrder(next, abstractToken!.lexeme);
+ } else if (constToken != null) {
+ reportModifierOutOfOrder(next, constToken!.lexeme);
+ } else if (covariantToken != null) {
+ reportModifierOutOfOrder(next, covariantToken!.lexeme);
+ } else if (finalToken != null) {
+ reportModifierOutOfOrder(next, finalToken!.lexeme);
+ } else if (lateToken != null) {
+ reportModifierOutOfOrder(next, lateToken!.lexeme);
+ } else if (staticToken != null) {
+ reportModifierOutOfOrder(next, staticToken!.lexeme);
+ } else if (externalToken != null) {
+ reportConflictingModifiers(next, externalToken!);
+ }
+ return next;
+ }
+
+ // Recovery
+ parser.reportRecoverableErrorWithToken(
+ next, codes.templateDuplicatedModifier);
+ return next;
+ }
+
+ Token _parseConst(Token token) {
Token next = token.next!;
assert(optional('const', next));
if (varFinalOrConst == null && covariantToken == null) {
constToken = next;
- if (afterFactory) {
+ if (_afterFactory) {
reportModifierOutOfOrder(next, 'factory');
} else if (lateToken != null) {
reportConflictingModifiers(next, lateToken!);
@@ -265,13 +364,13 @@
return next;
}
- Token parseCovariant(Token token) {
+ Token _parseCovariant(Token token) {
Token next = token.next!;
assert(optional('covariant', next));
if (constToken == null &&
covariantToken == null &&
staticToken == null &&
- !afterFactory) {
+ !_afterFactory) {
covariantToken = next;
if (varToken != null) {
@@ -288,7 +387,7 @@
if (covariantToken != null) {
parser.reportRecoverableErrorWithToken(
next, codes.templateDuplicatedModifier);
- } else if (afterFactory) {
+ } else if (_afterFactory) {
reportExtraneousModifier(next);
} else if (constToken != null) {
reportConflictingModifiers(next, constToken!);
@@ -300,13 +399,13 @@
return next;
}
- Token parseExternal(Token token) {
+ Token _parseExternal(Token token) {
Token next = token.next!;
assert(optional('external', next));
if (externalToken == null) {
externalToken = next;
- if (afterFactory) {
+ if (_afterFactory) {
reportModifierOutOfOrder(next, 'factory');
} else if (constToken != null) {
reportModifierOutOfOrder(next, constToken!.lexeme);
@@ -318,6 +417,8 @@
reportModifierOutOfOrder(next, varFinalOrConst!.lexeme);
} else if (covariantToken != null) {
reportModifierOutOfOrder(next, covariantToken!.lexeme);
+ } else if (augmentToken != null) {
+ reportConflictingModifiers(next, augmentToken!);
}
return next;
}
@@ -328,10 +429,10 @@
return next;
}
- Token parseFinal(Token token) {
+ Token _parseFinal(Token token) {
Token next = token.next!;
assert(optional('final', next));
- if (varFinalOrConst == null && !afterFactory) {
+ if (varFinalOrConst == null && !_afterFactory) {
finalToken = next;
return next;
}
@@ -340,7 +441,7 @@
if (finalToken != null) {
parser.reportRecoverableErrorWithToken(
next, codes.templateDuplicatedModifier);
- } else if (afterFactory) {
+ } else if (_afterFactory) {
reportExtraneousModifier(next);
} else if (constToken != null) {
parser.reportRecoverableError(next, codes.messageConstAndFinal);
@@ -354,7 +455,7 @@
return next;
}
- Token parseLate(Token token) {
+ Token _parseLate(Token token) {
Token next = token.next!;
assert(optional('late', next));
if (lateToken == null) {
@@ -376,7 +477,7 @@
return next;
}
- Token parseRequired(Token token) {
+ Token _parseRequired(Token token) {
Token next = token.next!;
assert(optional('required', next));
if (requiredToken == null) {
@@ -400,10 +501,10 @@
return next;
}
- Token parseStatic(Token token) {
+ Token _parseStatic(Token token) {
Token next = token.next!;
assert(optional('static', next));
- if (covariantToken == null && staticToken == null && !afterFactory) {
+ if (covariantToken == null && staticToken == null && !_afterFactory) {
staticToken = next;
if (constToken != null) {
@@ -424,7 +525,7 @@
} else if (staticToken != null) {
parser.reportRecoverableErrorWithToken(
next, codes.templateDuplicatedModifier);
- } else if (afterFactory) {
+ } else if (_afterFactory) {
reportExtraneousModifier(next);
} else {
throw 'Internal Error: Unhandled recovery: $next';
@@ -432,10 +533,10 @@
return next;
}
- Token parseVar(Token token) {
+ Token _parseVar(Token token) {
Token next = token.next!;
assert(optional('var', next));
- if (varFinalOrConst == null && !afterFactory) {
+ if (varFinalOrConst == null && !_afterFactory) {
varToken = next;
return next;
}
@@ -444,7 +545,7 @@
if (varToken != null) {
parser.reportRecoverableErrorWithToken(
next, codes.templateDuplicatedModifier);
- } else if (afterFactory) {
+ } else if (_afterFactory) {
reportExtraneousModifier(next);
} else if (constToken != null) {
reportConflictingModifiers(next, constToken!);
@@ -470,6 +571,30 @@
}
}
+ // Report an error for the given modifier preceding a top level keyword
+ // such as `import` or `class`.
+ void reportTopLevelModifierError(Token? modifier, Token afterModifiers) {
+ if (modifier != null) {
+ if (optional('const', modifier) && optional('class', afterModifiers)) {
+ parser.reportRecoverableError(modifier, codes.messageConstClass);
+ } else if (optional('external', modifier)) {
+ if (optional('class', afterModifiers)) {
+ parser.reportRecoverableError(modifier, codes.messageExternalClass);
+ } else if (optional('enum', afterModifiers)) {
+ parser.reportRecoverableError(modifier, codes.messageExternalEnum);
+ } else if (optional('typedef', afterModifiers)) {
+ parser.reportRecoverableError(modifier, codes.messageExternalTypedef);
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ modifier, codes.templateExtraneousModifier);
+ }
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ modifier, codes.templateExtraneousModifier);
+ }
+ }
+ }
+
void reportExtraneousModifierInExtension(Token? modifier) {
if (modifier != null) {
parser.reportRecoverableErrorWithToken(
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index a441a40..b8da52c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -76,6 +76,9 @@
looksLikeExpressionStart,
okNextValueInFormalParameter;
+import 'identifier_context_impl.dart'
+ show looksLikeStartOfNextTopLevelDeclaration;
+
import 'listener.dart' show Listener;
import 'literal_entry_info.dart'
@@ -89,7 +92,7 @@
import 'member_kind.dart' show MemberKind;
-import 'modifier_context.dart' show ModifierRecoveryContext, isModifier;
+import 'modifier_context.dart' show ModifierContext, isModifier;
import 'recovery_listeners.dart'
show
@@ -549,55 +552,6 @@
return parseInvalidTopLevelDeclaration(token);
}
- /// Parse the modifiers before the `class` keyword.
- /// Return the first `abstract` modifier or `null` if not found.
- Token? parseClassDeclarationModifiers(Token start, Token keyword) {
- Token modifier = start.next!;
- while (modifier != keyword) {
- if (optional('abstract', modifier)) {
- parseTopLevelKeywordModifiers(modifier, keyword);
- return modifier;
- } else {
- // Recovery
- reportTopLevelModifierError(modifier, keyword);
- }
- modifier = modifier.next!;
- }
- return null;
- }
-
- /// Report errors on any modifiers before the specified keyword.
- void parseTopLevelKeywordModifiers(Token start, Token keyword) {
- Token modifier = start.next!;
- while (modifier != keyword) {
- // Recovery
- reportTopLevelModifierError(modifier, keyword);
- modifier = modifier.next!;
- }
- }
-
- // Report an error for the given modifier preceding a top level keyword
- // such as `import` or `class`.
- void reportTopLevelModifierError(Token modifier, Token afterModifiers) {
- if (optional('const', modifier) && optional('class', afterModifiers)) {
- reportRecoverableError(modifier, codes.messageConstClass);
- } else if (optional('external', modifier)) {
- if (optional('class', afterModifiers)) {
- reportRecoverableError(modifier, codes.messageExternalClass);
- } else if (optional('enum', afterModifiers)) {
- reportRecoverableError(modifier, codes.messageExternalEnum);
- } else if (optional('typedef', afterModifiers)) {
- reportRecoverableError(modifier, codes.messageExternalTypedef);
- } else {
- reportRecoverableErrorWithToken(
- modifier, codes.templateExtraneousModifier);
- }
- } else {
- reportRecoverableErrorWithToken(
- modifier, codes.templateExtraneousModifier);
- }
- }
-
/// Parse any top-level declaration that begins with a keyword.
/// [start] is the token before any modifiers preceding [keyword].
Token parseTopLevelKeywordDeclaration(Token start, Token keyword,
@@ -606,13 +560,16 @@
final String? value = keyword.stringValue;
if (identical(value, 'class')) {
directiveState?.checkDeclaration();
- Token? abstractToken =
- parseClassDeclarationModifiers(start, macroToken ?? keyword);
+ ModifierContext context = new ModifierContext(this);
+ context.parseClassModifiers(start, keyword);
+ Token? abstractToken = context.abstractToken;
+ Token? augmentToken = context.augmentToken;
return parseClassOrNamedMixinApplication(
- abstractToken, macroToken, keyword);
+ abstractToken, macroToken, augmentToken, keyword);
} else if (identical(value, 'enum')) {
directiveState?.checkDeclaration();
- parseTopLevelKeywordModifiers(start, keyword);
+ ModifierContext context = new ModifierContext(this);
+ context.parseEnumModifiers(start, keyword);
return parseEnum(keyword);
} else {
// The remaining top level keywords are built-in keywords
@@ -636,25 +593,32 @@
directiveState?.checkDeclaration();
return parseTopLevelMemberImpl(start);
} else {
- parseTopLevelKeywordModifiers(start, keyword);
+ ModifierContext context = new ModifierContext(this);
if (identical(value, 'import')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
directiveState?.checkImport(this, keyword);
return parseImport(keyword);
} else if (identical(value, 'export')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
directiveState?.checkExport(this, keyword);
return parseExport(keyword);
} else if (identical(value, 'typedef')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
directiveState?.checkDeclaration();
return parseTypedef(keyword);
} else if (identical(value, 'mixin')) {
+ context.parseMixinModifiers(start, keyword);
directiveState?.checkDeclaration();
- return parseMixin(keyword);
+ return parseMixin(context.augmentToken, keyword);
} else if (identical(value, 'extension')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
directiveState?.checkDeclaration();
return parseExtension(keyword);
} else if (identical(value, 'part')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
return parsePartOrPartOf(keyword, directiveState);
} else if (identical(value, 'library')) {
+ context.parseTopLevelKeywordModifiers(start, keyword);
directiveState?.checkLibrary(this, keyword);
return parseLibraryName(keyword);
}
@@ -715,17 +679,22 @@
assert(optional('import', importKeyword));
listener.beginUncategorizedTopLevelDeclaration(importKeyword);
listener.beginImport(importKeyword);
- Token token = ensureLiteralString(importKeyword);
+ Token start = importKeyword;
+ Token? augmentToken;
+ if (start.next!.isIdentifier && start.next!.lexeme == 'augment') {
+ start = augmentToken = start.next!;
+ }
+ Token token = ensureLiteralString(start);
Token uri = token;
token = parseConditionalUriStar(token);
token = parseImportPrefixOpt(token);
token = parseCombinatorStar(token).next!;
if (optional(';', token)) {
- listener.endImport(importKeyword, token);
+ listener.endImport(importKeyword, augmentToken, token);
return token;
} else {
// Recovery
- listener.endImport(importKeyword, /* semicolon = */ null);
+ listener.endImport(importKeyword, augmentToken, /* semicolon = */ null);
return parseImportRecovery(uri);
}
}
@@ -1585,7 +1554,7 @@
if (isModifier(next)) {
// Recovery
- ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+ ModifierContext context = new ModifierContext(this)
..covariantToken = covariantToken
..requiredToken = requiredToken
..varFinalOrConst = varFinalOrConst;
@@ -2044,11 +2013,140 @@
token = computeTypeParamOrArg(
token, /* inDeclaration = */ true, /* allowsVariance = */ true)
.parseVariables(token, this);
+ List<String> lookForNext = const ['{', 'with', 'implements'];
+ if (!isOneOf(token.next!, lookForNext)) {
+ // Recovery: Possible unexpected tokens before any clauses.
+ Token? skipToken = recoverySmallLookAheadSkipTokens(token, lookForNext);
+ if (skipToken != null) {
+ token = skipToken;
+ }
+ }
+
+ Token beforeWith = token;
token = parseEnumWithClauseOpt(token);
+
+ while (!isOneOf(token.next!, const ['{', 'implements'])) {
+ // Recovery: Skip unexpected tokens and more with clauses.
+ // Note that if we find a "with" we've seen one already (otherwise the
+ // parseEnumWithClauseOpt call above would have found this 'with').
+ Token? skipToken = recoveryEnumWith(token,
+ codes.templateMultipleClauses.withArguments("enum", "with")) ??
+ recoverySmallLookAheadSkipTokens(token, lookForNext);
+
+ if (skipToken != null) {
+ // Skipped tokens.
+ token = skipToken;
+ } else {
+ break;
+ }
+ }
+
token = parseClassOrMixinOrEnumImplementsOpt(token);
+
+ bool? hasWithClauses;
+ while (!optional('{', token.next!)) {
+ if (hasWithClauses == null) {
+ hasWithClauses = optional('with', beforeWith.next!);
+ }
+
+ // Recovery: Skip unexpected tokens and more with/implements clauses.
+ Token? skipToken = recoveryEnumWith(
+ token,
+ hasWithClauses
+ ? codes.templateMultipleClauses.withArguments("enum", "with")
+ : codes.templateOutOfOrderClauses
+ .withArguments("with", "implements"));
+ if (skipToken != null) {
+ hasWithClauses = true;
+ }
+ if (skipToken == null) {
+ // Note that if we find a "implements" we've seen one already (otherwise
+ // the parseClassOrMixinOrEnumImplementsOpt call above would have found
+ // this 'implements').
+ skipToken = recoveryEnumImplements(token,
+ codes.templateMultipleClauses.withArguments("enum", "implements"));
+ }
+ if (skipToken == null) {
+ skipToken = recoverySmallLookAheadSkipTokens(token, lookForNext);
+ }
+
+ if (skipToken != null) {
+ // Skipped tokens.
+ token = skipToken;
+ } else {
+ break;
+ }
+ }
+
return token;
}
+ Token? recoveryEnumWith(Token token, codes.Message message) {
+ if (optional('with', token.next!)) {
+ reportRecoverableError(token.next!, message);
+ Listener originalListener = listener;
+ listener = new NullListener();
+ token = parseEnumWithClauseOpt(token);
+ listener = originalListener;
+ return token;
+ }
+ return null;
+ }
+
+ Token? recoveryEnumImplements(Token token, codes.Message message) {
+ if (optional('implements', token.next!)) {
+ reportRecoverableError(token.next!, message);
+ Listener originalListener = listener;
+ listener = new NullListener();
+ token = parseClassOrMixinOrEnumImplementsOpt(token);
+ listener = originalListener;
+ return token;
+ }
+ return null;
+ }
+
+ /// Allow a small lookahead (currently up to 3 tokens) trying to find any in
+ /// [lookFor].
+ ///
+ /// If any wanted token is found an error is issued about unexpected tokens,
+ /// and the last skipped token is returned.
+ /// Otherwise null is returned.
+ Token? recoverySmallLookAheadSkipTokens(
+ final Token token, Iterable<String> lookFor) {
+ // Recovery: Allow a small lookahead for '{'. E.g. the user might be in
+ // the middle of writing 'with' or 'implements'.
+ Token skipToken = token.next!;
+ bool foundWanted = false;
+
+ if (looksLikeStartOfNextTopLevelDeclaration(skipToken)) return null;
+
+ int skipped = 0;
+ while (skipped < 3) {
+ skipped++;
+ if (isOneOf(skipToken.next!, lookFor)) {
+ foundWanted = true;
+ break;
+ }
+
+ skipToken = skipToken.next!;
+ if (looksLikeStartOfNextTopLevelDeclaration(skipToken)) return null;
+ }
+
+ if (foundWanted) {
+ // Give error and skip the tokens.
+ if (skipped == 1) {
+ reportRecoverableError(
+ skipToken, codes.templateUnexpectedToken.withArguments(skipToken));
+ } else {
+ reportRecoverableErrorWithEnd(
+ token.next!, skipToken, codes.messageUnexpectedTokens);
+ }
+ return skipToken;
+ }
+
+ return null;
+ }
+
Token parseEnumElement(Token token) {
Token beginToken = token;
token = parseMetadataStar(token);
@@ -2065,8 +2163,8 @@
return token;
}
- Token parseClassOrNamedMixinApplication(
- Token? abstractToken, Token? macroToken, Token classKeyword) {
+ Token parseClassOrNamedMixinApplication(Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token classKeyword) {
assert(optional('class', classKeyword));
Token begin = abstractToken ?? classKeyword;
listener.beginClassOrMixinOrNamedMixinApplicationPrelude(begin);
@@ -2077,10 +2175,11 @@
.parseVariables(name, this);
if (optional('=', token.next!)) {
listener.beginNamedMixinApplication(
- begin, abstractToken, macroToken, name);
+ begin, abstractToken, macroToken, augmentToken, name);
return parseNamedMixinApplication(token, begin, classKeyword);
} else {
- listener.beginClassDeclaration(begin, abstractToken, macroToken, name);
+ listener.beginClassDeclaration(
+ begin, abstractToken, macroToken, augmentToken, name);
return parseClass(token, begin, classKeyword, name.lexeme);
}
}
@@ -2294,11 +2393,11 @@
///
/// ```
/// mixinDeclaration:
- /// metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
+ /// metadata? 'augment'? 'mixin' [SimpleIdentifier] [TypeParameterList]?
/// [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
/// ;
/// ```
- Token parseMixin(Token mixinKeyword) {
+ Token parseMixin(Token? augmentToken, Token mixinKeyword) {
assert(optional('mixin', mixinKeyword));
listener.beginClassOrMixinOrNamedMixinApplicationPrelude(mixinKeyword);
Token name = ensureIdentifier(
@@ -2306,7 +2405,7 @@
Token headerStart = computeTypeParamOrArg(
name, /* inDeclaration = */ true, /* allowsVariance = */ true)
.parseVariables(name, this);
- listener.beginMixinDeclaration(mixinKeyword, name);
+ listener.beginMixinDeclaration(augmentToken, mixinKeyword, name);
Token token = parseMixinHeaderOpt(headerStart, mixinKeyword);
if (!optional('{', token.next!)) {
// Recovery
@@ -2745,6 +2844,7 @@
}
Token? externalToken;
+ Token? augmentToken;
Token? lateToken;
Token? varFinalOrConst;
@@ -2752,6 +2852,9 @@
if (optional('external', next)) {
externalToken = token = next;
next = token.next!;
+ } else if (optional('augment', next)) {
+ augmentToken = token = next;
+ next = token.next!;
}
if (isModifier(next)) {
if (optional('final', next)) {
@@ -2780,14 +2883,16 @@
// If another `var`, `final`, or `const` then fall through
// to parse that as part of the next top level declaration.
} else {
- ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+ ModifierContext context = new ModifierContext(this)
..externalToken = externalToken
+ ..augmentToken = augmentToken
..lateToken = lateToken
..varFinalOrConst = varFinalOrConst;
- token = context.parseTopLevelModifiers(token);
+ token = context.parseTopLevelMemberModifiers(token);
next = token.next!;
+ augmentToken = context.augmentToken;
externalToken = context.externalToken;
lateToken = context.lateToken;
varFinalOrConst = context.varFinalOrConst;
@@ -2912,8 +3017,8 @@
reportRecoverableErrorWithToken(
lateToken, codes.templateExtraneousModifier);
}
- return parseTopLevelMethod(beforeStart, externalToken, beforeType,
- typeInfo, getOrSet, token.next!, nameIsRecovered);
+ return parseTopLevelMethod(beforeStart, augmentToken, externalToken,
+ beforeType, typeInfo, getOrSet, token.next!, nameIsRecovered);
}
if (getOrSet != null) {
@@ -2923,6 +3028,7 @@
return parseFields(
beforeStart,
/* abstractToken = */ null,
+ augmentToken,
externalToken,
/* staticToken = */ null,
/* covariantToken = */ null,
@@ -2939,6 +3045,7 @@
Token parseFields(
Token beforeStart,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -2950,8 +3057,8 @@
DeclarationKind kind,
String? enclosingDeclarationName,
bool nameIsRecovered) {
- listener.beginFields(kind, abstractToken, externalToken, staticToken,
- covariantToken, lateToken, varFinalOrConst, beforeStart);
+ listener.beginFields(kind, abstractToken, augmentToken, externalToken,
+ staticToken, covariantToken, lateToken, varFinalOrConst, beforeStart);
// Covariant affects only the setter and final fields do not have a setter,
// unless it's a late field (dartbug.com/40805).
@@ -2998,12 +3105,28 @@
}
int fieldCount = 1;
- token = parseFieldInitializerOpt(name, name, lateToken, abstractToken,
- externalToken, varFinalOrConst, kind, enclosingDeclarationName);
+ token = parseFieldInitializerOpt(
+ name,
+ name,
+ lateToken,
+ abstractToken,
+ augmentToken,
+ externalToken,
+ varFinalOrConst,
+ kind,
+ enclosingDeclarationName);
while (optional(',', token.next!)) {
name = ensureIdentifier(token.next!, context);
- token = parseFieldInitializerOpt(name, name, lateToken, abstractToken,
- externalToken, varFinalOrConst, kind, enclosingDeclarationName);
+ token = parseFieldInitializerOpt(
+ name,
+ name,
+ lateToken,
+ abstractToken,
+ augmentToken,
+ externalToken,
+ varFinalOrConst,
+ kind,
+ enclosingDeclarationName);
++fieldCount;
}
Token semicolon = token.next!;
@@ -3036,6 +3159,7 @@
case DeclarationKind.Class:
listener.endClassFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3048,6 +3172,7 @@
case DeclarationKind.Mixin:
listener.endMixinFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3068,6 +3193,7 @@
}
listener.endExtensionFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3080,6 +3206,7 @@
case DeclarationKind.Enum:
listener.endEnumFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3095,13 +3222,14 @@
Token parseTopLevelMethod(
Token beforeStart,
+ Token? augmentToken,
Token? externalToken,
Token beforeType,
TypeInfo typeInfo,
Token? getOrSet,
Token name,
bool nameIsRecovered) {
- listener.beginTopLevelMethod(beforeStart, externalToken);
+ listener.beginTopLevelMethod(beforeStart, augmentToken, externalToken);
Token token = typeInfo.parseType(beforeType, this);
assert(token.next == (getOrSet ?? name) || token.next!.isEof);
@@ -3178,6 +3306,7 @@
Token name,
Token? lateToken,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? varFinalOrConst,
DeclarationKind kind,
@@ -3262,26 +3391,22 @@
if (!optional('(', next)) {
break;
}
- // Looks like assert expression ... fall through to insert comma
- } else if (!next.isIdentifier && !optional('this', next)) {
- // An identifier that wasn't an initializer. Break.
- break;
- } else {
- if (optional('this', next)) {
- next = next.next!;
- if (!optional('.', next)) {
- break;
- }
- next = next.next!;
- if (!next.isIdentifier && !optional('assert', next)) {
- break;
- }
+ // Looks like assert expression ... fall through to insert comma.
+ } else if (optional('this', next) || optional('super', next)) {
+ next = next.next!;
+ if (!optional('(', next) && !optional('.', next)) {
+ break;
}
+ // `this` or `super` followed by either `.` or `(`.
+ // Fall through to insert comma.
+ } else if (next.isIdentifier) {
next = next.next!;
if (!optional('=', next)) {
break;
}
- // Looks like field assignment... fall through to insert comma
+ // Looks like field assignment... fall through to insert comma.
+ } else {
+ break;
}
// TODO(danrubel): Consider enhancing this to indicate that we are
// expecting one of `,` or `;` or `{`
@@ -3737,6 +3862,7 @@
Token? covariantToken;
Token? abstractToken;
+ Token? augmentToken;
Token? externalToken;
Token? lateToken;
Token? staticToken;
@@ -3747,6 +3873,9 @@
if (optional('external', next)) {
externalToken = token = next;
next = token.next!;
+ } else if (optional('augment', next)) {
+ augmentToken = token = next;
+ next = token.next!;
} else if (optional('abstract', next)) {
abstractToken = token = next;
next = token.next!;
@@ -3778,8 +3907,9 @@
}
}
if (isModifier(next)) {
- ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+ ModifierContext context = new ModifierContext(this)
..covariantToken = covariantToken
+ ..augmentToken = augmentToken
..externalToken = externalToken
..lateToken = lateToken
..staticToken = staticToken
@@ -3859,6 +3989,7 @@
token = parseMethod(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3882,6 +4013,7 @@
return parseInvalidOperatorDeclaration(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3895,6 +4027,7 @@
token = parseMethod(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3924,6 +4057,7 @@
token,
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3946,6 +4080,7 @@
return parseInvalidOperatorDeclaration(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -3981,6 +4116,7 @@
token = parseMethod(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -4001,6 +4137,7 @@
token = parseFields(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -4020,6 +4157,7 @@
Token parseMethod(
Token beforeStart,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -4093,8 +4231,8 @@
// TODO(danrubel): Consider parsing the name before calling beginMethod
// rather than passing the name token into beginMethod.
- listener.beginMethod(kind, externalToken, staticToken, covariantToken,
- varFinalOrConst, getOrSet, name);
+ listener.beginMethod(kind, augmentToken, externalToken, staticToken,
+ covariantToken, varFinalOrConst, getOrSet, name);
Token token = typeInfo.parseType(beforeType, this);
assert(token.next == (getOrSet ?? name) ||
@@ -4294,7 +4432,7 @@
if (!isValidTypeReference(token.next!)) {
// Recovery
- ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+ ModifierContext context = new ModifierContext(this)
..externalToken = externalToken
..staticOrCovariant = staticOrCovariant
..varFinalOrConst = varFinalOrConst;
@@ -6786,7 +6924,7 @@
if (isModifier(next)) {
// Recovery
- ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+ ModifierContext context = new ModifierContext(this)
..lateToken = lateToken
..varFinalOrConst = varFinalOrConst;
@@ -6827,7 +6965,7 @@
beforeType = start = beforeType.next!;
// The below doesn't parse modifiers, so we need to do it here.
- ModifierRecoveryContext context = new ModifierRecoveryContext(this);
+ ModifierContext context = new ModifierContext(this);
beforeType =
start = context.parseVariableDeclarationModifiers(beforeType);
varFinalOrConst = context.varFinalOrConst;
@@ -6874,7 +7012,7 @@
typeInfo.couldBeExpression) {
assert(optional('?', token));
assert(next.isKeywordOrIdentifier);
- if (!next.isIdentifier) {
+ if (!looksLikeName(next)) {
reportRecoverableError(
next, codes.templateExpectedIdentifier.withArguments(next));
next = rewriter.insertSyntheticIdentifier(next);
@@ -7488,19 +7626,33 @@
String? value = token.stringValue;
while (identical(value, 'catch') || identical(value, 'on')) {
- listener.beginCatchClause(token);
+ bool didBeginCatchClause = false;
Token? onKeyword = null;
if (identical(value, 'on')) {
// 'on' type catchPart?
onKeyword = token;
- lastConsumed = computeType(token, /* required = */ true)
- .ensureTypeNotVoid(token, this);
+ TypeInfo typeInfo = computeType(token, /* required = */ true);
+ if (catchCount > 0 && (typeInfo == noType || typeInfo.recovered)) {
+ // Not a valid on-clause and we have enough catch counts to be a valid
+ // try block already.
+ // This could for instance be code like `on([...])` or `on = 42` after
+ // some actual catch/on as that could be a valid method call, local
+ // function, assignment etc.
+ break;
+ }
+ listener.beginCatchClause(token);
+ didBeginCatchClause = true;
+ lastConsumed = typeInfo.ensureTypeNotVoid(token, this);
token = lastConsumed.next!;
value = token.stringValue;
}
Token? catchKeyword = null;
Token? comma = null;
if (identical(value, 'catch')) {
+ if (!didBeginCatchClause) {
+ listener.beginCatchClause(token);
+ didBeginCatchClause = true;
+ }
catchKeyword = token;
Token openParens = catchKeyword.next!;
@@ -7895,6 +8047,7 @@
Token parseInvalidOperatorDeclaration(
Token beforeStart,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -7943,6 +8096,7 @@
Token token = parseMethod(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -7966,6 +8120,7 @@
Token token,
Token beforeStart,
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -7989,6 +8144,7 @@
return parseInvalidOperatorDeclaration(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -8006,6 +8162,7 @@
token = parseMethod(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -8030,6 +8187,7 @@
token = parseFields(
beforeStart,
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
index fbc3ab3..4f5ad4e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
@@ -42,6 +42,7 @@
ContinueTarget,
Deferred,
DocumentationComment,
+ EnumConstantInfo,
Expression,
ExtendsClause,
FieldInitializer,
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
index 9e76440..90c69c8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
@@ -252,17 +252,6 @@
assert(typeParamOrArg == noTypeParamOrArg);
next = next.next!;
- // TODO(scheglov) This is a hack to partially fix.
- // https://github.com/dart-lang/sdk/issues/47951
- if (optional('?', next) &&
- optional('super', next.next!) &&
- optional('.', next.next!.next!)) {
- return simpleNullableType;
- }
- if (optional('super', next) && optional('.', next.next!)) {
- return simpleType;
- }
-
if (optional('.', next)) {
next = next.next!;
if (isValidTypeReference(next)) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
index 099319f..07d1752 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
@@ -451,6 +451,7 @@
bool looksLikeName(Token token) {
return token.kind == IDENTIFIER_TOKEN ||
optional('this', token) ||
+ optional('super', token) ||
(token.isIdentifier &&
// Although `typedef` is a legal identifier,
// type `typedef` identifier is not legal and in this situation
@@ -794,7 +795,9 @@
if (optional('?', next)) {
next = next.next!;
}
- if (!(next.isIdentifier || optional('this', next))) {
+ if (!(next.isIdentifier ||
+ optional('this', next) ||
+ optional('super', next))) {
break; // `Function` used as the name in a function declaration.
}
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
index 7f70b75..8c6a343 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
@@ -73,6 +73,9 @@
/// and https://github.com/dart-lang/language/issues/60
bool _enableTripleShift = false;
+ /// If `true`, 'augment' is treated as a built-in identifier.
+ bool _forAugmentationLibrary = false;
+
/**
* The string offset for the next token that will be created.
*
@@ -159,6 +162,7 @@
_enableExtensionMethods = config.enableExtensionMethods;
_enableNonNullable = config.enableNonNullable;
_enableTripleShift = config.enableTripleShift;
+ _forAugmentationLibrary = config.forAugmentationLibrary;
}
}
@@ -1619,6 +1623,9 @@
(keyword == Keyword.LATE || keyword == Keyword.REQUIRED)) {
return tokenizeIdentifier(next, start, allowDollar);
}
+ if (!_forAugmentationLibrary && keyword == Keyword.AUGMENT) {
+ return tokenizeIdentifier(next, start, allowDollar);
+ }
if (($A <= next && next <= $Z) ||
($0 <= next && next <= $9) ||
identical(next, $_) ||
@@ -2055,13 +2062,18 @@
/// and https://github.com/dart-lang/language/issues/60
final bool enableTripleShift;
+ /// If `true`, 'augment' is treated as a built-in identifier.
+ final bool forAugmentationLibrary;
+
const ScannerConfiguration({
bool enableExtensionMethods = false,
bool enableNonNullable = false,
bool enableTripleShift = false,
+ bool forAugmentationLibrary = false,
}) : this.enableExtensionMethods = enableExtensionMethods,
this.enableNonNullable = enableNonNullable,
- this.enableTripleShift = enableTripleShift;
+ this.enableTripleShift = enableTripleShift,
+ this.forAugmentationLibrary = forAugmentationLibrary;
}
bool _isIdentifierChar(int next, bool allowDollar) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
index 63fd51c..35a6386 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
@@ -72,7 +72,7 @@
bool includeComments: false,
LanguageVersionChanged? languageVersionChanged}) {
if (bytes.last != 0) {
- throw new ArgumentError("[bytes]: the last byte must be null.");
+ throw new ArgumentError("[bytes]: the last byte must be 0.");
}
Scanner scanner = new Utf8BytesScanner(bytes,
configuration: configuration,
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
index 0a6ab6c..d4225fb 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -144,6 +144,10 @@
static const Keyword ASYNC =
const Keyword("async", "ASYNC", KeywordStyle.pseudo);
+ static const Keyword AUGMENT = const Keyword(
+ "augment", "AUGMENT", KeywordStyle.builtIn,
+ isModifier: true);
+
static const Keyword AWAIT =
const Keyword("await", "AWAIT", KeywordStyle.pseudo);
@@ -345,6 +349,7 @@
AS,
ASSERT,
ASYNC,
+ AUGMENT,
AWAIT,
BREAK,
CASE,
@@ -734,6 +739,9 @@
: super(type, offset, precedingComment);
@override
+ Token? beforeSynthetic;
+
+ @override
Token copy() =>
new SyntheticBeginToken(type, offset, copyComments(precedingComments));
@@ -755,6 +763,9 @@
SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, offset);
@override
+ Token? beforeSynthetic;
+
+ @override
int get length => 0;
@override
@@ -1085,7 +1096,8 @@
* Return the token with the smallest offset, or `null` if all of the
* tokens are `null`.
*/
- static Token? lexicallyFirst([Token? t1, Token? t2, Token? t3, Token? t4]) {
+ static Token? lexicallyFirst(
+ [Token? t1, Token? t2, Token? t3, Token? t4, Token? t5]) {
Token? result = t1;
if (result == null || t2 != null && t2.offset < result.offset) {
result = t2;
@@ -1096,6 +1108,9 @@
if (result == null || t4 != null && t4.offset < result.offset) {
result = t4;
}
+ if (result == null || t5 != null && t5.offset < result.offset) {
+ result = t5;
+ }
return result;
}
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
index 896c670..a1bbadb 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
@@ -65,13 +65,13 @@
Map<Id, Map<String, IdValue>> idValuePerId = idValuePerUri[uri] ?? {};
Map<Id, Map<String, ActualData<T>>> actualDataPerId =
actualDataPerUri[uri] ?? {};
- AnnotatedCode code = annotatedCode[uri]!;
- assert(
- // ignore: unnecessary_null_comparison
- code != null, "No annotated code for ${uri} in ${annotatedCode.keys}");
- result[uri] = _computeAnnotations(code, expectedMaps.keys, actualMarkers,
+ AnnotatedCode? code = annotatedCode[uri];
+ if (code != null) {
+ // Annotations are not computed from synthesized code.
+ result[uri] = _computeAnnotations(code, expectedMaps.keys, actualMarkers,
idValuePerId, actualDataPerId, dataInterpreter,
sortMarkers: false, createDiff: createDiff, forceUpdate: forceUpdate);
+ }
}
return result;
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
index 68ad3ab6..f29fc9f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -771,7 +771,9 @@
List<FileSystemEntity> entities = dataDir
.listSync()
.where((entity) =>
- !entity.path.endsWith('~') && !entity.path.endsWith('marker.options'))
+ !entity.path.endsWith('~') &&
+ !entity.path.endsWith('marker.options') &&
+ !entity.path.endsWith('.expect'))
.toList();
if (shards > 1) {
entities.sort((a, b) => getTestName(a).compareTo(getTestName(b)));
@@ -842,9 +844,11 @@
actualData[marker] = {};
void addActualData(Uri uri, Map<Id, ActualData<T>> actualData) {
- // ignore: unnecessary_null_comparison
- assert(uri != null && testData.code.containsKey(uri) ||
- actualData.isEmpty);
+ assert(
+ // ignore: unnecessary_null_comparison
+ uri != null && testData.code.containsKey(uri) ||
+ actualData.isEmpty,
+ "Unexpected data ${actualData} for $uri");
// ignore: unnecessary_null_comparison
if (uri == null || actualData.isEmpty) {
// TODO(johnniwinther): Avoid collecting data without
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart b/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
index 4e453145..a25f8e8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
@@ -238,7 +238,7 @@
_reportError(messageIncludePathIsNotAString(targetName, specUri));
}
Uri uri = Uri.parse(path);
- if (uri.scheme != '' && uri.scheme != 'file') {
+ if (uri.hasScheme && !uri.isScheme('file')) {
return _reportError(messageUnsupportedUriScheme(path, specUri));
}
LibrariesSpecification specification =
@@ -269,7 +269,7 @@
uriString, libraryName, targetName, specUri));
}
Uri uri = Uri.parse(uriString);
- if (uri.scheme != '' && uri.scheme != 'file') {
+ if (uri.hasScheme && !uri.isScheme('file')) {
return _reportError(
messageUnsupportedUriScheme(uriString, specUri));
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/resolve_input_uri.dart b/pkg/_fe_analyzer_shared/lib/src/util/resolve_input_uri.dart
index 2600d6d..39ce9d4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/resolve_input_uri.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/resolve_input_uri.dart
@@ -18,7 +18,7 @@
Uri parseUri(String path) {
if (path.startsWith("file:")) {
- if (Uri.base.scheme == "file") {
+ if (Uri.base.isScheme("file")) {
// The Uri class doesn't handle relative file URIs correctly, the
// following works around that issue.
return new Uri(path: Uri.parse("x-$path").path);
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index cfc2267..e4718a0 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 34.0.0
+version: 36.0.0
description: Logic that is shared between the front_end and analyzer packages.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/_fe_analyzer_shared/test/macros/api/api_test_data.dart b/pkg/_fe_analyzer_shared/test/macros/api/api_test_data.dart
new file mode 100644
index 0000000..5a96c10
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/api/api_test_data.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'api_test_macro.dart';
+
+main() {}
+
+var field;
+get getter => null;
+set setter(_) => null;
+
+@ClassMacro()
+class Class1 {}
+
+@ClassMacro()
+abstract class Class2 {}
+
+@ClassMacro()
+class Class3 extends Class2 {}
+
+mixin Mixin {}
+
+@ClassMacro()
+class Class4 extends Class1 with Mixin {}
+
+@FunctionMacro()
+void topLevelFunction1(Class1 a, {Class1? b, required Class2? c}) {}
+
+@FunctionMacro()
+external Class2 topLevelFunction2(Class1 a, [Class2? b]);
diff --git a/pkg/_fe_analyzer_shared/test/macros/api/api_test_expectations.dart b/pkg/_fe_analyzer_shared/test/macros/api/api_test_expectations.dart
new file mode 100644
index 0000000..c826563
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/api/api_test_expectations.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+const Map<String, ClassData> expectedClassData = {
+ 'Class1': ClassData(superclassOf: 'Object'),
+ 'Class2': ClassData(isAbstract: true, superclassOf: 'Object'),
+ 'Class3': ClassData(superclassOf: 'Class2', superSuperclassOf: 'Object'),
+ 'Class4': ClassData(superclassOf: 'Class1', superSuperclassOf: 'Object'),
+};
+
+const Map<String, FunctionData> expectedFunctionData = {
+ 'topLevelFunction1': FunctionData(
+ returnType: NamedTypeData(name: 'void'),
+ positionalParameters: [
+ ParameterData('a',
+ type: NamedTypeData(name: 'Class1'), isRequired: true),
+ ],
+ namedParameters: [
+ ParameterData('b',
+ type: NamedTypeData(name: 'Class1', isNullable: true),
+ isNamed: true,
+ isRequired: false),
+ ParameterData('c',
+ type: NamedTypeData(name: 'Class2', isNullable: true),
+ isNamed: true,
+ isRequired: true),
+ ]),
+ 'topLevelFunction2': FunctionData(
+ isExternal: true,
+ returnType: NamedTypeData(name: 'Class2'),
+ positionalParameters: [
+ ParameterData('a', type: NamedTypeData(name: 'Class1'), isRequired: true),
+ ParameterData('b', type: NamedTypeData(name: 'Class2', isNullable: true)),
+ ],
+ ),
+};
+
+expect(expected, actual, property) {
+ if (expected != actual) {
+ throw 'Expected $expected, actual $actual on $property';
+ }
+}
+
+Future<void> throws(Future<void> Function() f, property) async {
+ try {
+ await f();
+ } catch (_) {
+ return;
+ }
+ throw 'Expected throws on $property';
+}
+
+void checkTypeAnnotation(
+ TypeData expected, TypeAnnotation typeAnnotation, String context) {
+ expect(expected.isNullable, typeAnnotation.isNullable, '$context.isNullable');
+ expect(expected is NamedTypeData, typeAnnotation is NamedTypeAnnotation,
+ '$context is NamedTypeAnnotation');
+ if (expected is NamedTypeData && typeAnnotation is NamedTypeAnnotation) {
+ expect(expected.name, typeAnnotation.identifier.name, '$context.name');
+ // TODO(johnniwinther): Test more properties.
+ }
+}
+
+void checkParameterDeclaration(
+ ParameterData expected, ParameterDeclaration declaration, String context) {
+ expect(expected.name, declaration.identifier.name, '$context.identifer.name');
+ expect(expected.isNamed, declaration.isNamed, '$context.isNamed');
+ expect(expected.isRequired, declaration.isRequired, '$context.isRequired');
+ checkTypeAnnotation(expected.type, declaration.type, '$context.type');
+}
+
+Future<void> checkClassDeclaration(ClassDeclaration declaration,
+ {ClassIntrospector? classIntrospector}) async {
+ String name = declaration.identifier.name;
+ ClassData? expected = expectedClassData[name];
+ if (expected != null) {
+ expect(expected.isAbstract, declaration.isAbstract, '$name.isAbstract');
+ expect(expected.isExternal, declaration.isExternal, '$name.isExternal');
+ if (classIntrospector != null) {
+ ClassDeclaration? superclassOf =
+ await classIntrospector.superclassOf(declaration);
+ expect(expected.superclassOf, superclassOf?.identifier.name,
+ '$name.superclassOf');
+ if (superclassOf != null) {
+ ClassDeclaration? superSuperclassOf =
+ await classIntrospector.superclassOf(superclassOf);
+ expect(expected.superSuperclassOf, superSuperclassOf?.identifier.name,
+ '$name.superSuperclassOf');
+ }
+ }
+ // TODO(johnniwinther): Test more properties when there are supported.
+ } else {
+ throw 'Unexpected class declaration "${name}"';
+ }
+}
+
+void checkFunctionDeclaration(FunctionDeclaration actual) {
+ String name = actual.identifier.name;
+ FunctionData? expected = expectedFunctionData[name];
+ if (expected != null) {
+ expect(expected.isAbstract, actual.isAbstract, '$name.isAbstract');
+ expect(expected.isExternal, actual.isExternal, '$name.isExternal');
+ expect(expected.isOperator, actual.isOperator, '$name.isOperator');
+ expect(expected.isGetter, actual.isGetter, '$name.isGetter');
+ expect(expected.isSetter, actual.isSetter, '$name.isSetter');
+ checkTypeAnnotation(
+ expected.returnType, actual.returnType, '$name.returnType');
+ expect(
+ expected.positionalParameters.length,
+ actual.positionalParameters.length,
+ '$name.positionalParameters.length');
+ for (int i = 0; i < expected.positionalParameters.length; i++) {
+ checkParameterDeclaration(
+ expected.positionalParameters[i],
+ actual.positionalParameters.elementAt(i),
+ '$name.positionalParameters[$i]');
+ }
+ expect(expected.namedParameters.length, actual.namedParameters.length,
+ '$name.namedParameters.length');
+ for (int i = 0; i < expected.namedParameters.length; i++) {
+ checkParameterDeclaration(expected.namedParameters[i],
+ actual.namedParameters.elementAt(i), '$name.namedParameters[$i]');
+ }
+ // TODO(johnniwinther): Test more properties.
+ } else {
+ throw 'Unexpected function declaration "${name}"';
+ }
+}
+
+Future<void> checkIdentifierResolver(
+ IdentifierResolver identifierResolver) async {
+ Uri dartCore = Uri.parse('dart:core');
+ Uri macroApiData = Uri.parse('package:macro_api_test/api_test_data.dart');
+
+ Future<void> check(Uri uri, String name, {bool expectThrows: false}) async {
+ if (expectThrows) {
+ await throws(() async {
+ await identifierResolver.resolveIdentifier(uri, name);
+ }, '$name from $uri');
+ } else {
+ Identifier result = await identifierResolver.resolveIdentifier(uri, name);
+ expect(name, result.name, '$name from $uri');
+ }
+ }
+
+ await check(dartCore, 'Object');
+ await check(dartCore, 'String');
+ await check(dartCore, 'override');
+
+ await check(macroApiData, 'Class1');
+ await check(macroApiData, 'getter');
+ await check(macroApiData, 'setter=');
+ await check(macroApiData, 'field');
+
+ await check(macroApiData, 'non-existing', expectThrows: true);
+ await check(macroApiData, 'getter=', expectThrows: true);
+ await check(macroApiData, 'setter', expectThrows: true);
+ await check(macroApiData, 'field=', expectThrows: true);
+}
+
+class ClassData {
+ final bool isAbstract;
+ final bool isExternal;
+ final String superclassOf;
+ final String? superSuperclassOf;
+
+ const ClassData(
+ {this.isAbstract: false,
+ this.isExternal: false,
+ required this.superclassOf,
+ this.superSuperclassOf});
+}
+
+class FunctionData {
+ final bool isAbstract;
+ final bool isExternal;
+ final bool isOperator;
+ final bool isGetter;
+ final bool isSetter;
+ final TypeData returnType;
+ final List<ParameterData> positionalParameters;
+ final List<ParameterData> namedParameters;
+
+ const FunctionData(
+ {this.isAbstract: false,
+ this.isExternal: false,
+ this.isOperator: false,
+ this.isGetter: false,
+ this.isSetter: false,
+ required this.returnType,
+ this.positionalParameters: const [],
+ this.namedParameters: const []});
+}
+
+class TypeData {
+ final bool isNullable;
+
+ const TypeData({this.isNullable: false});
+}
+
+class NamedTypeData extends TypeData {
+ final String? name;
+ final List<TypeData>? typeArguments;
+
+ const NamedTypeData({bool isNullable: false, this.name, this.typeArguments})
+ : super(isNullable: isNullable);
+}
+
+class ParameterData {
+ final String name;
+ final TypeData type;
+ final bool isRequired;
+ final bool isNamed;
+
+ const ParameterData(this.name,
+ {required this.type, this.isNamed: false, this.isRequired: false});
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/api/api_test_macro.dart b/pkg/_fe_analyzer_shared/test/macros/api/api_test_macro.dart
new file mode 100644
index 0000000..d54db3b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/api/api_test_macro.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'api_test_expectations.dart';
+
+
+
+macro class ClassMacro
+ implements ClassTypesMacro, ClassDeclarationsMacro, ClassDefinitionMacro {
+ const ClassMacro();
+
+ FutureOr<void> buildTypesForClass(
+ ClassDeclaration clazz, TypeBuilder builder) async {
+ await checkClassDeclaration(clazz);
+ }
+
+ FutureOr<void> buildDeclarationsForClass(
+ ClassDeclaration clazz, ClassMemberDeclarationBuilder builder) async {
+ await checkClassDeclaration(clazz, classIntrospector: builder);
+ }
+
+ FutureOr<void> buildDefinitionForClass(
+ ClassDeclaration clazz, ClassDefinitionBuilder builder) async {
+ await checkClassDeclaration(clazz, classIntrospector: builder);
+ }
+}
+
+macro class FunctionMacro
+ implements
+ FunctionTypesMacro,
+ FunctionDeclarationsMacro,
+ FunctionDefinitionMacro {
+ const FunctionMacro();
+
+ FutureOr<void> buildTypesForFunction(
+ FunctionDeclaration function, TypeBuilder builder) async {
+ checkFunctionDeclaration(function);
+ await checkIdentifierResolver(builder);
+ }
+
+ FutureOr<void> buildDeclarationsForFunction(
+ FunctionDeclaration function, DeclarationBuilder builder) async {
+ checkFunctionDeclaration(function);
+ await checkIdentifierResolver(builder);
+ }
+
+ FutureOr<void> buildDefinitionForFunction(
+ FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
+ checkFunctionDeclaration(function);
+ await checkIdentifierResolver(builder);
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/api/package_config.json b/pkg/_fe_analyzer_shared/test/macros/api/package_config.json
new file mode 100644
index 0000000..8fa0595
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/api/package_config.json
@@ -0,0 +1,18 @@
+{
+ "configVersion": 2,
+ "packages": [
+ {
+ "name": "macro_api_test",
+ "rootUri": "../../../../_fe_analyzer_shared/test/macros/api/"
+ },
+ {
+ "name": "meta",
+ "rootUri": "../../../../meta/",
+ "packageUri": "lib/"
+ },
+ {
+ "name": "_fe_analyzer_shared",
+ "rootUri": "../../../../_fe_analyzer_shared/lib/"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
new file mode 100644
index 0000000..af3d9d7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
@@ -0,0 +1,150 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
+import 'package:test/fake.dart';
+import 'package:test/test.dart';
+
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/augmentation_library.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/response_impls.dart';
+
+import '../util.dart';
+
+void main() {
+ group('AugmentationLibraryBuilder', () {
+ test('can combine multiple execution results', () {
+ var results = [
+ for (var i = 0; i < 2; i++)
+ MacroExecutionResultImpl(classAugmentations: {
+ for (var j = 0; j < 3; j++)
+ 'Foo$i$j': [
+ DeclarationCode.fromString('int get i => $i;\n'),
+ DeclarationCode.fromString('int get j => $j;\n'),
+ ]
+ }, libraryAugmentations: [
+ for (var j = 0; j < 3; j++)
+ DeclarationCode.fromString('int get i${i}j$j => ${i + j};\n'),
+ ], newTypeNames: [
+ 'Foo${i}0',
+ 'Foo${i}1',
+ 'Foo${i}2',
+ ]),
+ ];
+ var library = _TestExecutor().buildAugmentationLibrary(
+ results, (Identifier i) => (i as TestIdentifier).resolved);
+ expect(library, equalsIgnoringWhitespace('''
+ int get i0j0 => 0;
+ int get i0j1 => 1;
+ int get i0j2 => 2;
+ int get i1j0 => 1;
+ int get i1j1 => 2;
+ int get i1j2 => 3;
+ augment class Foo00 {
+ int get i => 0;
+ int get j => 0;
+ }
+ augment class Foo01 {
+ int get i => 0;
+ int get j => 1;
+ }
+ augment class Foo02 {
+ int get i => 0;
+ int get j => 2;
+ }
+ augment class Foo10 {
+ int get i => 1;
+ int get j => 0;
+ }
+ augment class Foo11 {
+ int get i => 1;
+ int get j => 1;
+ }
+ augment class Foo12 {
+ int get i => 1;
+ int get j => 2;
+ }
+ '''));
+ });
+
+ test('can add imports for identifiers', () {
+ var fooIdentifier = TestIdentifier(
+ id: RemoteInstance.uniqueId,
+ name: 'Foo',
+ kind: IdentifierKind.topLevelMember,
+ staticScope: null,
+ uri: Uri.parse('package:foo/foo.dart'));
+ var barIdentifier = TestIdentifier(
+ id: RemoteInstance.uniqueId,
+ name: 'Bar',
+ kind: IdentifierKind.topLevelMember,
+ staticScope: null,
+ uri: Uri.parse('package:bar/bar.dart'));
+ var builderIdentifier = TestIdentifier(
+ id: RemoteInstance.uniqueId,
+ name: 'Builder',
+ kind: IdentifierKind.topLevelMember,
+ staticScope: null,
+ uri: Uri.parse('package:builder/builder.dart'));
+ var barInstanceMember = TestIdentifier(
+ id: RemoteInstance.uniqueId,
+ name: 'baz',
+ kind: IdentifierKind.instanceMember,
+ staticScope: null,
+ uri: Uri.parse('package:bar/bar.dart'));
+ var barStaticMember = TestIdentifier(
+ id: RemoteInstance.uniqueId,
+ name: 'zap',
+ kind: IdentifierKind.staticInstanceMember,
+ staticScope: 'Bar',
+ uri: Uri.parse('package:bar/bar.dart'));
+ var results = [
+ MacroExecutionResultImpl(
+ classAugmentations: {},
+ libraryAugmentations: [
+ DeclarationCode.fromParts([
+ 'class FooBuilder<T extends ',
+ fooIdentifier,
+ '> implements ',
+ builderIdentifier,
+ '<',
+ barIdentifier,
+ '<T>> {\n',
+ 'late int ${barInstanceMember.name};\n',
+ barIdentifier,
+ '<T> build() => new ',
+ barIdentifier,
+ '()..',
+ barInstanceMember,
+ ' = ',
+ barStaticMember,
+ ';',
+ '\n}',
+ ]),
+ ],
+ newTypeNames: [
+ 'FooBuilder',
+ ],
+ )
+ ];
+ var library = _TestExecutor().buildAugmentationLibrary(
+ results, (Identifier i) => (i as TestIdentifier).resolved);
+ expect(library, equalsIgnoringWhitespace('''
+ import 'package:foo/foo.dart' as i0;
+ import 'package:builder/builder.dart' as i1;
+ import 'package:bar/bar.dart' as i2;
+
+ class FooBuilder<T extends i0.Foo> implements i1.Builder<i2.Bar<T>> {
+ late int baz;
+
+ i2.Bar<T> build() => new i2.Bar()..baz = i2.Bar.zap;
+ }
+ '''));
+ });
+ });
+}
+
+class _TestExecutor extends MacroExecutor
+ with AugmentationLibraryBuilder, Fake {}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
new file mode 100644
index 0000000..13b54ac
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/executor_test.dart
@@ -0,0 +1,545 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
+ as isolatedExecutor;
+import 'package:_fe_analyzer_shared/src/macros/executor/process_executor.dart'
+ as processExecutor;
+
+import 'package:test/test.dart';
+
+import '../util.dart';
+
+void main() {
+ late MacroExecutor executor;
+ late File kernelOutputFile;
+ final macroName = 'SimpleMacro';
+ late MacroInstanceIdentifier instanceId;
+ late Uri macroUri;
+ late File simpleMacroFile;
+ late Directory tmpDir;
+
+ for (var executorKind in ['Isolated', 'Process']) {
+ group('$executorKind executor', () {
+ for (var mode in [
+ SerializationMode.byteDataServer,
+ SerializationMode.jsonServer
+ ]) {
+ final clientMode = mode == SerializationMode.byteDataServer
+ ? SerializationMode.byteDataClient
+ : SerializationMode.jsonClient;
+
+ group('$mode', () {
+ setUpAll(() async {
+ simpleMacroFile =
+ File(Platform.script.resolve('simple_macro.dart').toFilePath());
+ executor = executorKind == 'Isolated'
+ ? await isolatedExecutor.start(mode)
+ : await processExecutor.start(mode);
+ tmpDir = Directory.systemTemp.createTempSync('executor_test');
+ macroUri = simpleMacroFile.absolute.uri;
+
+ var bootstrapContent = bootstrapMacroIsolate({
+ macroUri.toString(): {
+ macroName: ['', 'named']
+ }
+ }, clientMode);
+ var bootstrapFile =
+ File(tmpDir.uri.resolve('main.dart').toFilePath())
+ ..writeAsStringSync(bootstrapContent);
+ kernelOutputFile =
+ File(tmpDir.uri.resolve('main.dart.dill').toFilePath());
+ var packageConfigPath = (await Isolate.packageConfig)!.toFilePath();
+ var buildSnapshotResult =
+ await Process.run(Platform.resolvedExecutable, [
+ if (executorKind == 'Isolated') ...[
+ '--snapshot=${kernelOutputFile.uri.toFilePath()}',
+ '--snapshot-kind=kernel',
+ ] else ...[
+ 'compile',
+ 'exe',
+ '-o',
+ kernelOutputFile.uri.toFilePath(),
+ ],
+ '--packages=${packageConfigPath}',
+ bootstrapFile.uri.toFilePath(),
+ ]);
+ expect(buildSnapshotResult.exitCode, 0,
+ reason: 'stdout: ${buildSnapshotResult.stdout}\n'
+ 'stderr: ${buildSnapshotResult.stderr}');
+
+ var clazzId = await executor.loadMacro(macroUri, macroName,
+ precompiledKernelUri: kernelOutputFile.uri);
+ expect(clazzId, isNotNull, reason: 'Can load a macro.');
+
+ instanceId =
+ await executor.instantiateMacro(clazzId, '', Arguments([], {}));
+ expect(instanceId, isNotNull,
+ reason: 'Can create an instance with no arguments.');
+
+ instanceId = await executor.instantiateMacro(
+ clazzId, '', Arguments([1, 2], {}));
+ expect(instanceId, isNotNull,
+ reason: 'Can create an instance with positional arguments.');
+
+ instanceId = await executor.instantiateMacro(
+ clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
+ expect(instanceId, isNotNull,
+ reason: 'Can create an instance with named arguments.');
+ });
+
+ tearDownAll(() {
+ if (tmpDir.existsSync()) {
+ try {
+ // Fails flakily on windows if a process still has the file open
+ tmpDir.deleteSync(recursive: true);
+ } catch (_) {}
+ }
+ executor.close();
+ });
+
+ group('run macros', () {
+ group('in the types phase', () {
+ test('on functions', () async {
+ var result = await executor.executeTypesPhase(
+ instanceId, Fixtures.myFunction, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('class GeneratedByMyFunction {}'));
+ });
+
+ test('on methods', () async {
+ var result = await executor.executeTypesPhase(
+ instanceId, Fixtures.myMethod, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('class GeneratedByMyMethod {}'));
+ });
+
+ test('on getters', () async {
+ var result = await executor.executeTypesPhase(instanceId,
+ Fixtures.myVariableGetter, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'class GeneratedByMyVariableGetter {}'));
+ });
+
+ test('on setters', () async {
+ var result = await executor.executeTypesPhase(instanceId,
+ Fixtures.myVariableSetter, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'class GeneratedByMyVariableSetter {}'));
+ });
+
+ test('on variables', () async {
+ var result = await executor.executeTypesPhase(
+ instanceId, Fixtures.myVariable, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'class GeneratedBy_myVariable {}'));
+ });
+
+ test('on constructors', () async {
+ var result = await executor.executeTypesPhase(instanceId,
+ Fixtures.myConstructor, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'class GeneratedByMyConstructor {}'));
+ });
+
+ test('on fields', () async {
+ var result = await executor.executeTypesPhase(
+ instanceId, Fixtures.myField, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('class GeneratedByMyField {}'));
+ });
+
+ test('on classes', () async {
+ var result = await executor.executeTypesPhase(
+ instanceId, Fixtures.myClass, FakeIdentifierResolver());
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'class MyClassBuilder implements Builder<MyClass> {}'));
+ });
+ });
+
+ group('in the declaration phase', () {
+ test('on functions', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myFunction,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'String delegateMyFunction() => myFunction();'));
+ });
+
+ test('on methods', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myMethod,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace(
+ 'String delegateMemberMyMethod() => myMethod();'));
+ });
+
+ test('on constructors', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myConstructor,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, hasLength(1));
+ expect(
+ result.classAugmentations['MyClass']!.single
+ .debugString()
+ .toString(),
+ equalsIgnoringWhitespace('''
+ factory MyClass.myConstructorDelegate() => MyClass.myConstructor();
+ '''));
+ expect(result.libraryAugmentations, isEmpty);
+ });
+
+ test('on getters', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myVariableGetter,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ String get delegateMyVariable => myVariable;'''));
+ });
+
+ test('on setters', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myVariableSetter,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ void set delegateMyVariable(String value) => myVariable = value;'''));
+ });
+
+ test('on variables', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myVariable,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ String get delegate_myVariable => _myVariable;'''));
+ });
+
+ test('on fields', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myField,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, hasLength(1));
+ expect(
+ result.classAugmentations['MyClass']!.single
+ .debugString()
+ .toString(),
+ equalsIgnoringWhitespace('''
+ String get delegateMyField => myField;
+ '''));
+ expect(result.libraryAugmentations, isEmpty);
+ });
+
+ test('on classes', () async {
+ var result = await executor.executeDeclarationsPhase(
+ instanceId,
+ Fixtures.myClass,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector);
+ expect(result.classAugmentations, hasLength(1));
+ expect(
+ result.classAugmentations['MyClass']!.single
+ .debugString()
+ .toString(),
+ equalsIgnoringWhitespace('''
+ static const List<String> fieldNames = ['myField',];
+ '''));
+ expect(result.libraryAugmentations, isEmpty);
+ });
+ });
+
+ group('in the definition phase', () {
+ test('on functions', () async {
+ var result = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myFunction,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ augment String myFunction() {
+ print('isAbstract: false');
+ print('isExternal: false');
+ print('isGetter: false');
+ print('isSetter: false');
+ print('returnType: String');
+ return augment super();
+ }'''));
+ });
+
+ test('on methods', () async {
+ var definitionResult = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myMethod,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(definitionResult.classAugmentations, hasLength(1));
+ var augmentationStrings = definitionResult
+ .classAugmentations['MyClass']!
+ .map((a) => a.debugString().toString())
+ .toList();
+ expect(augmentationStrings,
+ unorderedEquals(methodDefinitionMatchers));
+ expect(definitionResult.libraryAugmentations, isEmpty);
+ });
+
+ test('on constructors', () async {
+ var definitionResult = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myConstructor,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(definitionResult.classAugmentations, hasLength(1));
+ expect(
+ definitionResult.classAugmentations['MyClass']!.first
+ .debugString()
+ .toString(),
+ constructorDefinitionMatcher);
+ expect(definitionResult.libraryAugmentations, isEmpty);
+ });
+
+ test('on getters', () async {
+ var result = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myVariableGetter,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ augment String myVariable() {
+ print('isAbstract: false');
+ print('isExternal: false');
+ print('isGetter: true');
+ print('isSetter: false');
+ print('returnType: String');
+ return augment super;
+ }'''));
+ });
+
+ test('on setters', () async {
+ var result = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myVariableSetter,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations.single.debugString().toString(),
+ equalsIgnoringWhitespace('''
+ augment void myVariable(String value, ) {
+ print('isAbstract: false');
+ print('isExternal: false');
+ print('isGetter: false');
+ print('isSetter: true');
+ print('returnType: void');
+ print('positionalParam: String value');
+ return augment super = value;
+ }'''));
+ });
+
+ test('on variables', () async {
+ var result = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myVariable,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(result.classAugmentations, isEmpty);
+ expect(
+ result.libraryAugmentations
+ .map((a) => a.debugString().toString()),
+ unorderedEquals([
+ equalsIgnoringWhitespace('''
+ augment String get _myVariable {
+ print('parentClass: ');
+ print('isExternal: false');
+ print('isFinal: true');
+ print('isLate: false');
+ return augment super;
+ }'''),
+ equalsIgnoringWhitespace('''
+ augment set _myVariable(String value) {
+ augment super = value;
+ }'''),
+ equalsIgnoringWhitespace('''
+ augment final String _myVariable = 'new initial value' + augment super;
+ '''),
+ ]));
+ });
+
+ test('on fields', () async {
+ var definitionResult = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myField,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(definitionResult.classAugmentations, hasLength(1));
+ expect(
+ definitionResult.classAugmentations['MyClass']!
+ .map((a) => a.debugString().toString()),
+ unorderedEquals(fieldDefinitionMatchers));
+ expect(definitionResult.libraryAugmentations, isEmpty);
+ });
+
+ test('on classes', () async {
+ var definitionResult = await executor.executeDefinitionsPhase(
+ instanceId,
+ Fixtures.myClass,
+ FakeIdentifierResolver(),
+ Fixtures.testTypeResolver,
+ Fixtures.testClassIntrospector,
+ Fixtures.testTypeDeclarationResolver);
+ expect(definitionResult.classAugmentations, hasLength(1));
+ var augmentationStrings = definitionResult
+ .classAugmentations['MyClass']!
+ .map((a) => a.debugString().toString())
+ .toList();
+ expect(
+ augmentationStrings,
+ unorderedEquals([
+ ...methodDefinitionMatchers,
+ constructorDefinitionMatcher,
+ ...fieldDefinitionMatchers,
+ ]));
+ });
+ });
+ });
+ });
+ }
+ });
+ }
+}
+
+final constructorDefinitionMatcher = equalsIgnoringWhitespace('''
+augment MyClass.myConstructor() {
+ print('definingClass: MyClass');
+ print('isFactory: false');
+ print('isAbstract: false');
+ print('isExternal: false');
+ print('isGetter: false');
+ print('isSetter: false');
+ print('returnType: MyClass');
+ return augment super();
+}''');
+
+final fieldDefinitionMatchers = [
+ equalsIgnoringWhitespace('''
+ augment String get myField {
+ print('parentClass: MyClass');
+ print('isExternal: false');
+ print('isFinal: false');
+ print('isLate: false');
+ return augment super;
+ }'''),
+ equalsIgnoringWhitespace('''
+ augment set myField(String value) {
+ augment super = value;
+ }'''),
+ equalsIgnoringWhitespace('''
+ augment String myField = \'new initial value\' + augment super;'''),
+];
+
+final methodDefinitionMatchers = [
+ equalsIgnoringWhitespace('''
+ augment String myMethod() {
+ print('definingClass: MyClass');
+ print('isAbstract: false');
+ print('isExternal: false');
+ print('isGetter: false');
+ print('isSetter: false');
+ print('returnType: String');
+ return augment super();
+ }'''),
+ equalsIgnoringWhitespace('''
+ augment String myMethod() {
+ print('x: 1, y: 2');
+ print('parentClass: MyClass');
+ print('superClass: MySuperclass');
+ print('interface: MyInterface');
+ print('mixin: MyMixin');
+ print('field: myField');
+ print('method: myMethod');
+ print('constructor: myConstructor');
+ return augment super();
+ }'''),
+];
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart
new file mode 100644
index 0000000..c64b7c7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
+import 'package:test/fake.dart';
+import 'package:test/test.dart';
+
+import 'package:_fe_analyzer_shared/src/macros/executor/response_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+void main() {
+ group('MacroInstanceIdentifierImpl', () {
+ test('shouldExecute', () {
+ for (var kind in DeclarationKind.values) {
+ for (var phase in Phase.values) {
+ var instance = instancesByKindAndPhase[kind]![phase]!;
+ for (var otherKind in DeclarationKind.values) {
+ for (var otherPhase in Phase.values) {
+ var expected = false;
+ if (otherPhase == phase) {
+ if (kind == otherKind) {
+ expected = true;
+ } else if (kind == DeclarationKind.function &&
+ otherKind == DeclarationKind.method) {
+ expected = true;
+ } else if (kind == DeclarationKind.variable &&
+ otherKind == DeclarationKind.field) {
+ expected = true;
+ }
+ }
+ expect(instance.shouldExecute(otherKind, otherPhase), expected,
+ reason: 'Expected a $kind macro in $phase to '
+ '${expected ? '' : 'not '}be applied to a $otherKind '
+ 'in $otherPhase');
+ }
+ }
+ }
+ }
+ });
+
+ test('supportsDeclarationKind', () {
+ for (var kind in DeclarationKind.values) {
+ for (var phase in Phase.values) {
+ var instance = instancesByKindAndPhase[kind]![phase]!;
+ for (var otherKind in DeclarationKind.values) {
+ var expected = false;
+ if (kind == otherKind) {
+ expected = true;
+ } else if (kind == DeclarationKind.function &&
+ otherKind == DeclarationKind.method) {
+ expected = true;
+ } else if (kind == DeclarationKind.variable &&
+ otherKind == DeclarationKind.field) {
+ expected = true;
+ }
+ expect(instance.supportsDeclarationKind(otherKind), expected,
+ reason: 'Expected a $kind macro to ${expected ? '' : 'not '}'
+ 'support a $otherKind');
+ }
+ }
+ }
+ });
+ });
+}
+
+final Map<DeclarationKind, Map<Phase, MacroInstanceIdentifierImpl>>
+ instancesByKindAndPhase = {
+ DeclarationKind.clazz: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeClassTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeClassDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeClassDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+ DeclarationKind.constructor: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeConstructorTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeConstructorDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeConstructorDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+ DeclarationKind.field: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeFieldTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeFieldDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeFieldDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+ DeclarationKind.function: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeFunctionTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeFunctionDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeFunctionDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+ DeclarationKind.method: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeMethodTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeMethodDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeMethodDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+ DeclarationKind.variable: {
+ Phase.types: MacroInstanceIdentifierImpl(
+ FakeVariableTypesMacro(), RemoteInstance.uniqueId),
+ Phase.declarations: MacroInstanceIdentifierImpl(
+ FakeVariableDeclarationsMacro(), RemoteInstance.uniqueId),
+ Phase.definitions: MacroInstanceIdentifierImpl(
+ FakeVariableDefinitionMacro(), RemoteInstance.uniqueId),
+ },
+};
+
+class FakeClassTypesMacro extends Fake implements ClassTypesMacro {}
+
+class FakeClassDeclarationsMacro extends Fake
+ implements ClassDeclarationsMacro {}
+
+class FakeClassDefinitionMacro extends Fake implements ClassDefinitionMacro {}
+
+class FakeConstructorTypesMacro extends Fake implements ConstructorTypesMacro {}
+
+class FakeConstructorDeclarationsMacro extends Fake
+ implements ConstructorDeclarationsMacro {}
+
+class FakeConstructorDefinitionMacro extends Fake
+ implements ConstructorDefinitionMacro {}
+
+class FakeFieldTypesMacro extends Fake implements FieldTypesMacro {}
+
+class FakeFieldDeclarationsMacro extends Fake
+ implements FieldDeclarationsMacro {}
+
+class FakeFieldDefinitionMacro extends Fake implements FieldDefinitionMacro {}
+
+class FakeFunctionTypesMacro extends Fake implements FunctionTypesMacro {}
+
+class FakeFunctionDeclarationsMacro extends Fake
+ implements FunctionDeclarationsMacro {}
+
+class FakeFunctionDefinitionMacro extends Fake
+ implements FunctionDefinitionMacro {}
+
+class FakeMethodTypesMacro extends Fake implements MethodTypesMacro {}
+
+class FakeMethodDeclarationsMacro extends Fake
+ implements MethodDeclarationsMacro {}
+
+class FakeMethodDefinitionMacro extends Fake implements MethodDefinitionMacro {}
+
+class FakeVariableTypesMacro extends Fake implements VariableTypesMacro {}
+
+class FakeVariableDeclarationsMacro extends Fake
+ implements VariableDeclarationsMacro {}
+
+class FakeVariableDefinitionMacro extends Fake
+ implements VariableDefinitionMacro {}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart
new file mode 100644
index 0000000..eb74a8e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/serialization_test.dart
@@ -0,0 +1,376 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization_extensions.dart';
+import 'package:test/test.dart';
+
+import '../util.dart';
+
+void main() {
+ for (var mode in [
+ SerializationMode.jsonClient,
+ SerializationMode.jsonServer,
+ SerializationMode.byteDataClient,
+ SerializationMode.byteDataServer,
+ ]) {
+ test('$mode can serialize and deserialize basic data', () {
+ withSerializationMode(mode, () {
+ var serializer = serializerFactory();
+ serializer
+ ..addInt(0)
+ ..addInt(1)
+ ..addInt(0xff)
+ ..addInt(0xffff)
+ ..addInt(0xffffffff)
+ ..addInt(0xffffffffffffffff)
+ ..addInt(-1)
+ ..addInt(-0x80)
+ ..addInt(-0x8000)
+ ..addInt(-0x80000000)
+ ..addInt(-0x8000000000000000)
+ ..addNullableInt(null)
+ ..addString('hello')
+ ..addString('€') // Requires a two byte string
+ ..addString('𐐷') // Requires two, 16 bit code units
+ ..addNullableString(null)
+ ..startList()
+ ..addBool(true)
+ ..startList()
+ ..addNull()
+ ..endList()
+ ..addNullableBool(null)
+ ..endList()
+ ..addDouble(1.0)
+ ..startList()
+ ..endList();
+ var deserializer = deserializerFactory(serializer.result);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 1);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffffffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffffffffffffffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -1);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x80);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x8000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x80000000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x8000000000000000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableInt(), null);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), 'hello');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), '€');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), '𐐷');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableString(), null);
+ expect(deserializer.moveNext(), true);
+
+ deserializer.expectList();
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectBool(), true);
+ expect(deserializer.moveNext(), true);
+
+ deserializer.expectList();
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.checkNull(), true);
+ expect(deserializer.moveNext(), false);
+
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableBool(), null);
+ expect(deserializer.moveNext(), false);
+
+ // Have to move the parent again to advance it past the list entry.
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectDouble(), 1.0);
+ expect(deserializer.moveNext(), true);
+
+ deserializer.expectList();
+ expect(deserializer.moveNext(), false);
+
+ expect(deserializer.moveNext(), false);
+ });
+ });
+ }
+
+ for (var mode in [
+ SerializationMode.byteDataServer,
+ SerializationMode.jsonServer
+ ]) {
+ test('remote instances in $mode', () async {
+ var string = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
+ typeArguments: const []);
+ var foo = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ typeArguments: [string]);
+
+ withSerializationMode(mode, () {
+ var serializer = serializerFactory();
+ foo.serialize(serializer);
+ var response = roundTrip(serializer.result);
+ var deserializer = deserializerFactory(response);
+ var instance = RemoteInstance.deserialize(deserializer);
+ expect(instance, foo);
+ });
+ });
+ }
+
+ group('declarations', () {
+ final barType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Bar'),
+ typeArguments: []);
+ final fooType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: true,
+ identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ typeArguments: [barType]);
+
+ for (var mode in [
+ SerializationMode.byteDataServer,
+ SerializationMode.jsonServer
+ ]) {
+ group('with mode $mode', () {
+ test('NamedTypeAnnotation', () {
+ expectSerializationEquality(fooType, mode);
+ });
+
+ final fooNamedParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ isNamed: true,
+ isRequired: true,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
+ type: fooType);
+
+ final barPositionalParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ isNamed: false,
+ isRequired: false,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ type: barType);
+
+ final zapTypeParam = TypeParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
+ bound: barType);
+
+ // Transitively tests `TypeParameterDeclaration` and
+ // `ParameterDeclaration`.
+ test('FunctionTypeAnnotation', () {
+ var functionType = FunctionTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: true,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(functionType, mode);
+ });
+
+ test('FunctionDeclaration', () {
+ var function = FunctionDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
+ isAbstract: true,
+ isExternal: false,
+ isGetter: true,
+ isOperator: false,
+ isSetter: false,
+ namedParameters: [],
+ positionalParameters: [],
+ returnType: fooType,
+ typeParameters: []);
+ expectSerializationEquality(function, mode);
+ });
+
+ test('MethodDeclaration', () {
+ var method = MethodDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isOperator: false,
+ isSetter: true,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType.identifier,
+ isStatic: false);
+ expectSerializationEquality(method, mode);
+ });
+
+ test('ConstructorDeclaration', () {
+ var constructor = ConstructorDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isOperator: true,
+ isSetter: false,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType.identifier,
+ isFactory: true,
+ );
+ expectSerializationEquality(constructor, mode);
+ });
+
+ test('VariableDeclaration', () {
+ var bar = VariableDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ isExternal: true,
+ isFinal: false,
+ isLate: true,
+ type: barType,
+ );
+ expectSerializationEquality(bar, mode);
+ });
+
+ test('FieldDeclaration', () {
+ var bar = FieldDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ isExternal: false,
+ isFinal: true,
+ isLate: false,
+ type: barType,
+ definingClass: fooType.identifier,
+ isStatic: false,
+ );
+ expectSerializationEquality(bar, mode);
+ });
+
+ var objectType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object'),
+ isNullable: false,
+ typeArguments: [],
+ );
+ var serializableType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Serializable'),
+ isNullable: false,
+ typeArguments: [],
+ );
+
+ test('ClassDeclaration', () {
+ var fooClass = ClassDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ interfaces: [barType],
+ isAbstract: true,
+ isExternal: false,
+ mixins: [serializableType],
+ superclass: objectType,
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(fooClass, mode);
+ });
+
+ test('TypeAliasDeclaration', () {
+ var typeAlias = TypeAliasDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
+ typeParameters: [zapTypeParam],
+ aliasedType: NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ typeArguments: [barType]),
+ );
+ expectSerializationEquality(typeAlias, mode);
+ });
+ });
+ }
+ });
+}
+
+/// Serializes [serializable] in server mode, then deserializes it in client
+/// mode, and checks that all the fields are the same.
+void expectSerializationEquality(
+ Serializable serializable, SerializationMode serverMode) {
+ late Object? serialized;
+ withSerializationMode(serverMode, () {
+ var serializer = serializerFactory();
+ serializable.serialize(serializer);
+ serialized = serializer.result;
+ });
+ withSerializationMode(_clientModeForServerMode(serverMode), () {
+ var deserializer = deserializerFactory(serialized);
+ var deserialized = (deserializer..moveNext()).expectRemoteInstance();
+ if (deserialized is Declaration) {
+ expect(serializable, deepEqualsDeclaration(deserialized));
+ } else if (deserialized is TypeAnnotation) {
+ expect(serializable, deepEqualsTypeAnnotation(deserialized));
+ } else {
+ throw new UnsupportedError('Unsupported object type $deserialized');
+ }
+ });
+}
+
+/// Deserializes [serialized] in client mode and sends it back.
+Object? roundTrip<Declaration>(Object? serialized) {
+ return withSerializationMode(_clientModeForServerMode(serializationMode), () {
+ var deserializer = deserializerFactory(serialized);
+ var instance =
+ RemoteInstance.deserialize<NamedTypeAnnotationImpl>(deserializer);
+ var serializer = serializerFactory();
+ instance.serialize(serializer);
+ return serializer.result;
+ });
+}
+
+SerializationMode _clientModeForServerMode(SerializationMode serverMode) {
+ switch (serverMode) {
+ case SerializationMode.byteDataServer:
+ return SerializationMode.byteDataClient;
+ case SerializationMode.jsonServer:
+ return SerializationMode.jsonClient;
+ default:
+ throw StateError('Expected to be running in a server mode');
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/executor/simple_macro.dart
new file mode 100644
index 0000000..b5a2d2d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/simple_macro.dart
@@ -0,0 +1,402 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+/// A very simple macro that augments any declaration it is given, usually
+/// adding print statements and inlining values from the declaration object
+/// for comparision with expected values in tests.
+///
+/// When applied to [MethodDeclaration]s there is some extra work that happens
+/// to validate the introspection APIs work as expected.
+class SimpleMacro
+ implements
+ ClassTypesMacro,
+ ClassDeclarationsMacro,
+ ClassDefinitionMacro,
+ ConstructorTypesMacro,
+ ConstructorDeclarationsMacro,
+ ConstructorDefinitionMacro,
+ FieldTypesMacro,
+ FieldDeclarationsMacro,
+ FieldDefinitionMacro,
+ FunctionTypesMacro,
+ FunctionDeclarationsMacro,
+ FunctionDefinitionMacro,
+ MethodTypesMacro,
+ MethodDeclarationsMacro,
+ MethodDefinitionMacro,
+ VariableTypesMacro,
+ VariableDeclarationsMacro,
+ VariableDefinitionMacro {
+ final int? x;
+ final int? y;
+
+ SimpleMacro([this.x, this.y]);
+
+ SimpleMacro.named({this.x, this.y});
+
+ @override
+ FutureOr<void> buildDeclarationsForClass(
+ ClassDeclaration clazz, ClassMemberDeclarationBuilder builder) async {
+ var fields = await builder.fieldsOf(clazz);
+ builder.declareInClass(DeclarationCode.fromParts([
+ 'static const List<String> fieldNames = [',
+ for (var field in fields) "'${field.identifier.name}',",
+ '];',
+ ]));
+ }
+
+ @override
+ FutureOr<void> buildDeclarationsForConstructor(
+ ConstructorDeclaration constructor,
+ ClassMemberDeclarationBuilder builder) {
+ if (constructor.positionalParameters.isNotEmpty ||
+ constructor.namedParameters.isNotEmpty) {
+ throw new UnsupportedError(
+ 'Can only run on constructors with no parameters!');
+ }
+ var className = constructor.definingClass.name;
+ var constructorName = constructor.identifier.name;
+ builder.declareInClass(DeclarationCode.fromString(
+ 'factory $className.${constructorName}Delegate() => '
+ '$className.$constructorName();'));
+ }
+
+ @override
+ FutureOr<void> buildDeclarationsForFunction(
+ FunctionDeclaration function, DeclarationBuilder builder) {
+ if (!function.isSetter &&
+ (function.positionalParameters.isNotEmpty ||
+ function.namedParameters.isNotEmpty)) {
+ throw new UnsupportedError(
+ 'Can only run on functions with no parameters!');
+ }
+ var functionName = function.identifier.name;
+ builder.declareInLibrary(DeclarationCode.fromParts([
+ function.returnType.code,
+ if (function.isGetter) ' get' else if (function.isSetter) ' set ',
+ ' delegate${functionName.capitalize()}',
+ if (!function.isGetter) ...[
+ '(',
+ if (function.isSetter) ...[
+ function.positionalParameters.first.type.code,
+ ' value',
+ ],
+ ')',
+ ],
+ ' => ${functionName}',
+ function.isGetter
+ ? ''
+ : function.isSetter
+ ? ' = value'
+ : '()',
+ ';',
+ ]));
+ }
+
+ @override
+ FutureOr<void> buildDeclarationsForMethod(
+ MethodDeclaration method, ClassMemberDeclarationBuilder builder) {
+ if (method.positionalParameters.isNotEmpty ||
+ method.namedParameters.isNotEmpty) {
+ throw new UnsupportedError('Can only run on method with no parameters!');
+ }
+ var methodName = method.identifier.name;
+ builder.declareInLibrary(DeclarationCode.fromParts([
+ method.returnType.code,
+ ' delegateMember${methodName.capitalize()}() => $methodName();',
+ ]));
+ }
+
+ @override
+ FutureOr<void> buildDeclarationsForVariable(
+ VariableDeclaration variable, DeclarationBuilder builder) {
+ var variableName = variable.identifier.name;
+ builder.declareInLibrary(DeclarationCode.fromParts([
+ variable.type.code,
+ ' get delegate${variableName.capitalize()} => $variableName;',
+ ]));
+ }
+
+ @override
+ FutureOr<void> buildDeclarationsForField(
+ FieldDeclaration field, ClassMemberDeclarationBuilder builder) {
+ var fieldName = field.identifier.name;
+ builder.declareInClass(DeclarationCode.fromParts([
+ field.type.code,
+ ' get delegate${fieldName.capitalize()} => $fieldName;',
+ ]));
+ }
+
+ @override
+ Future<void> buildDefinitionForClass(
+ ClassDeclaration clazz, ClassDefinitionBuilder builder) async {
+ // Apply ourself to all our members
+ var fields = (await builder.fieldsOf(clazz));
+ for (var field in fields) {
+ await buildDefinitionForField(
+ field, await builder.buildField(field.identifier));
+ }
+ var methods = (await builder.methodsOf(clazz));
+ for (var method in methods) {
+ await buildDefinitionForMethod(
+ method, await builder.buildMethod(method.identifier));
+ }
+ var constructors = (await builder.constructorsOf(clazz));
+ for (var constructor in constructors) {
+ await buildDefinitionForConstructor(
+ constructor, await builder.buildConstructor(constructor.identifier));
+ }
+ }
+
+ @override
+ Future<void> buildDefinitionForConstructor(ConstructorDeclaration constructor,
+ ConstructorDefinitionBuilder builder) async {
+ var clazz = await builder.declarationOf(constructor.definingClass)
+ as ClassDeclaration;
+ var fields = (await builder.fieldsOf(clazz));
+
+ builder.augment(
+ body: _buildFunctionAugmentation(constructor),
+ initializers: [
+ for (var field in fields)
+ // TODO: Compare against actual `int` type.
+ if (field.isFinal &&
+ (field.type as NamedTypeAnnotation).identifier.name == 'int')
+ Code.fromParts([field.identifier, ' = ${x!}']),
+ ],
+ );
+ }
+
+ @override
+ Future<void> buildDefinitionForField(
+ FieldDeclaration field, VariableDefinitionBuilder builder) async =>
+ buildDefinitionForVariable(field, builder);
+
+ @override
+ Future<void> buildDefinitionForFunction(
+ FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
+ builder.augment(_buildFunctionAugmentation(function));
+ }
+
+ @override
+ Future<void> buildDefinitionForMethod(
+ MethodDeclaration method, FunctionDefinitionBuilder builder) async {
+ await buildDefinitionForFunction(method, builder);
+
+ // Test the type declaration resolver
+ var parentClass =
+ await builder.declarationOf(method.definingClass) as ClassDeclaration;
+ // Should be able to find ourself in the methods of the parent class.
+ (await builder.methodsOf(parentClass))
+ .singleWhere((m) => m.identifier == method.identifier);
+
+ // Test the class introspector
+ var superClass = (await builder.superclassOf(parentClass))!;
+ var interfaces = (await builder.interfacesOf(parentClass));
+ var mixins = (await builder.mixinsOf(parentClass));
+ var fields = (await builder.fieldsOf(parentClass));
+ var methods = (await builder.methodsOf(parentClass));
+ var constructors = (await builder.constructorsOf(parentClass));
+
+ // Test the type resolver and static type interfaces
+ var staticReturnType = await builder.resolve(method.returnType.code);
+ if (!(await staticReturnType.isExactly(staticReturnType))) {
+ throw StateError('The return type should be exactly equal to itself!');
+ }
+ if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
+ throw StateError('The return type should be a subtype of itself!');
+ }
+
+ // TODO: Use `builder.instantiateCode` instead once implemented.
+ var classType = await builder.resolve(constructors.first.returnType.code);
+ if (await staticReturnType.isExactly(classType)) {
+ throw StateError(
+ 'The return type should not be exactly equal to the class type');
+ }
+ if (await staticReturnType.isSubtypeOf(classType)) {
+ throw StateError(
+ 'The return type should not be a subtype of the class type!');
+ }
+
+ builder.augment(FunctionBodyCode.fromParts([
+ '''{
+ print('x: $x, y: $y');
+ print('parentClass: ${parentClass.identifier.name}');
+ print('superClass: ${superClass.identifier.name}');''',
+ for (var interface in interfaces)
+ "\n print('interface: ${interface.identifier.name}');",
+ for (var mixin in mixins)
+ "\n print('mixin: ${mixin.identifier.name}');",
+ for (var field in fields)
+ "\n print('field: ${field.identifier.name}');",
+ for (var method in methods)
+ "\n print('method: ${method.identifier.name}');",
+ for (var constructor in constructors)
+ "\n print('constructor: ${constructor.identifier.name}');",
+ '''
+\n return augment super();
+ }''',
+ ]));
+ }
+
+ @override
+ Future<void> buildDefinitionForVariable(
+ VariableDeclaration variable, VariableDefinitionBuilder builder) async {
+ var definingClass =
+ variable is FieldDeclaration ? variable.definingClass.name : '';
+ builder.augment(
+ getter: DeclarationCode.fromParts([
+ variable.type.code,
+ ' get ',
+ variable.identifier.name,
+ ''' {
+ print('parentClass: $definingClass');
+ print('isExternal: ${variable.isExternal}');
+ print('isFinal: ${variable.isFinal}');
+ print('isLate: ${variable.isLate}');
+ return augment super;
+ }''',
+ ]),
+ setter: DeclarationCode.fromParts([
+ 'set ',
+ variable.identifier.name,
+ '(',
+ variable.type.code,
+ ' value) { augment super = value; }'
+ ]),
+ initializer:
+ ExpressionCode.fromString("'new initial value' + augment super"),
+ );
+ }
+
+ @override
+ FutureOr<void> buildTypesForClass(
+ ClassDeclaration clazz, TypeBuilder builder) {
+ List<Object> _buildTypeParam(
+ TypeParameterDeclaration typeParam, bool isFirst) {
+ return [
+ if (!isFirst) ', ',
+ typeParam.identifier.name,
+ if (typeParam.bound != null) ...[
+ ' extends ',
+ typeParam.bound!.code,
+ ]
+ ];
+ }
+
+ var name = '${clazz.identifier.name}Builder';
+ builder.declareType(
+ name,
+ DeclarationCode.fromParts([
+ 'class $name',
+ if (clazz.typeParameters.isNotEmpty) ...[
+ '<',
+ ..._buildTypeParam(clazz.typeParameters.first, true),
+ for (var typeParam in clazz.typeParameters.skip(1))
+ ..._buildTypeParam(typeParam, false),
+ '>',
+ ],
+ ' implements Builder<',
+ clazz.identifier,
+ if (clazz.typeParameters.isNotEmpty) ...[
+ '<',
+ clazz.typeParameters.first.identifier.name,
+ for (var typeParam in clazz.typeParameters)
+ ', ${typeParam.identifier.name}',
+ '>',
+ ],
+ '> {}'
+ ]));
+ }
+
+ @override
+ FutureOr<void> buildTypesForConstructor(
+ ConstructorDeclaration constructor, TypeBuilder builder) {
+ var name = 'GeneratedBy${constructor.identifier.name.capitalize()}';
+ builder.declareType(name, DeclarationCode.fromString('class $name {}'));
+ }
+
+ @override
+ FutureOr<void> buildTypesForField(
+ FieldDeclaration field, TypeBuilder builder) {
+ var name = 'GeneratedBy${field.identifier.name.capitalize()}';
+ builder.declareType(name, DeclarationCode.fromString('class $name {}'));
+ }
+
+ @override
+ FutureOr<void> buildTypesForFunction(
+ FunctionDeclaration function, TypeBuilder builder) {
+ var suffix = function.isGetter
+ ? 'Getter'
+ : function.isSetter
+ ? 'Setter'
+ : '';
+ var name = 'GeneratedBy${function.identifier.name.capitalize()}$suffix';
+ builder.declareType(name, DeclarationCode.fromString('class $name {}'));
+ }
+
+ @override
+ FutureOr<void> buildTypesForMethod(
+ MethodDeclaration method, TypeBuilder builder) {
+ var name = 'GeneratedBy${method.identifier.name.capitalize()}';
+ builder.declareType(name, DeclarationCode.fromString('class $name {}'));
+ }
+
+ @override
+ FutureOr<void> buildTypesForVariable(
+ VariableDeclaration variable, TypeBuilder builder) {
+ var name = 'GeneratedBy${variable.identifier.name.capitalize()}';
+ builder.declareType(name, DeclarationCode.fromString('class $name {}'));
+ }
+}
+
+FunctionBodyCode _buildFunctionAugmentation(FunctionDeclaration function) =>
+ FunctionBodyCode.fromParts([
+ '{\n',
+ if (function is MethodDeclaration)
+ "print('definingClass: ${function.definingClass.name}');\n",
+ if (function is ConstructorDeclaration)
+ "print('isFactory: ${function.isFactory}');\n",
+ '''
+ print('isAbstract: ${function.isAbstract}');
+ print('isExternal: ${function.isExternal}');
+ print('isGetter: ${function.isGetter}');
+ print('isSetter: ${function.isSetter}');
+ print('returnType: ''',
+ function.returnType.code,
+ "');\n",
+ for (var param in function.positionalParameters) ...[
+ "print('positionalParam: ",
+ param.type.code,
+ ' ${param.identifier.name}',
+ "');\n",
+ ],
+ for (var param in function.namedParameters) ...[
+ "print('namedParam: ",
+ param.type.code,
+ ' ${param.identifier.name}',
+ "');\n",
+ ],
+ for (var param in function.typeParameters) ...[
+ "print('typeParam: ${param.identifier.name} ",
+ if (param.bound != null) param.bound!.code,
+ "');\n",
+ ],
+ 'return augment super',
+ if (function.isSetter) ...[
+ ' = ',
+ function.positionalParameters.first.identifier,
+ ],
+ if (!function.isGetter && !function.isSetter) '()',
+ ''';
+ }''',
+ ]);
+
+extension _ on String {
+ String capitalize() => '${this[0].toUpperCase()}${substring(1)}';
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart
deleted file mode 100644
index da0c02e..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/fake.dart';
-import 'package:test/test.dart';
-
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-void main() {
- group('MacroInstanceIdentifierImpl', () {
- test('shouldExecute', () {
- for (var kind in DeclarationKind.values) {
- for (var phase in Phase.values) {
- var instance = instancesByKindAndPhase[kind]![phase]!;
- for (var otherKind in DeclarationKind.values) {
- for (var otherPhase in Phase.values) {
- var expected = false;
- if (otherPhase == phase) {
- if (kind == otherKind) {
- expected = true;
- } else if (kind == DeclarationKind.function &&
- otherKind == DeclarationKind.method) {
- expected = true;
- } else if (kind == DeclarationKind.variable &&
- otherKind == DeclarationKind.field) {
- expected = true;
- }
- }
- expect(instance.shouldExecute(otherKind, otherPhase), expected,
- reason: 'Expected a $kind macro in $phase to '
- '${expected ? '' : 'not '}be applied to a $otherKind '
- 'in $otherPhase');
- }
- }
- }
- }
- });
-
- test('supportsDeclarationKind', () {
- for (var kind in DeclarationKind.values) {
- for (var phase in Phase.values) {
- var instance = instancesByKindAndPhase[kind]![phase]!;
- for (var otherKind in DeclarationKind.values) {
- var expected = false;
- if (kind == otherKind) {
- expected = true;
- } else if (kind == DeclarationKind.function &&
- otherKind == DeclarationKind.method) {
- expected = true;
- } else if (kind == DeclarationKind.variable &&
- otherKind == DeclarationKind.field) {
- expected = true;
- }
- expect(instance.supportsDeclarationKind(otherKind), expected,
- reason: 'Expected a $kind macro to ${expected ? '' : 'not '}'
- 'support a $otherKind');
- }
- }
- }
- });
- });
-}
-
-final Map<DeclarationKind, Map<Phase, MacroInstanceIdentifierImpl>>
- instancesByKindAndPhase = {
- DeclarationKind.clazz: {
- Phase.types: MacroInstanceIdentifierImpl(FakeClassTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeClassDeclarationsMacro()),
- Phase.definitions: MacroInstanceIdentifierImpl(FakeClassDefinitionMacro()),
- },
- DeclarationKind.constructor: {
- Phase.types: MacroInstanceIdentifierImpl(FakeConstructorTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeConstructorDeclarationsMacro()),
- Phase.definitions:
- MacroInstanceIdentifierImpl(FakeConstructorDefinitionMacro()),
- },
- DeclarationKind.field: {
- Phase.types: MacroInstanceIdentifierImpl(FakeFieldTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeFieldDeclarationsMacro()),
- Phase.definitions: MacroInstanceIdentifierImpl(FakeFieldDefinitionMacro()),
- },
- DeclarationKind.function: {
- Phase.types: MacroInstanceIdentifierImpl(FakeFunctionTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeFunctionDeclarationsMacro()),
- Phase.definitions:
- MacroInstanceIdentifierImpl(FakeFunctionDefinitionMacro()),
- },
- DeclarationKind.method: {
- Phase.types: MacroInstanceIdentifierImpl(FakeMethodTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeMethodDeclarationsMacro()),
- Phase.definitions: MacroInstanceIdentifierImpl(FakeMethodDefinitionMacro()),
- },
- DeclarationKind.variable: {
- Phase.types: MacroInstanceIdentifierImpl(FakeVariableTypesMacro()),
- Phase.declarations:
- MacroInstanceIdentifierImpl(FakeVariableDeclarationsMacro()),
- Phase.definitions:
- MacroInstanceIdentifierImpl(FakeVariableDefinitionMacro()),
- },
-};
-
-class FakeClassTypesMacro extends Fake implements ClassTypesMacro {}
-
-class FakeClassDeclarationsMacro extends Fake
- implements ClassDeclarationsMacro {}
-
-class FakeClassDefinitionMacro extends Fake implements ClassDefinitionMacro {}
-
-class FakeConstructorTypesMacro extends Fake implements ConstructorTypesMacro {}
-
-class FakeConstructorDeclarationsMacro extends Fake
- implements ConstructorDeclarationsMacro {}
-
-class FakeConstructorDefinitionMacro extends Fake
- implements ConstructorDefinitionMacro {}
-
-class FakeFieldTypesMacro extends Fake implements FieldTypesMacro {}
-
-class FakeFieldDeclarationsMacro extends Fake
- implements FieldDeclarationsMacro {}
-
-class FakeFieldDefinitionMacro extends Fake implements FieldDefinitionMacro {}
-
-class FakeFunctionTypesMacro extends Fake implements FunctionTypesMacro {}
-
-class FakeFunctionDeclarationsMacro extends Fake
- implements FunctionDeclarationsMacro {}
-
-class FakeFunctionDefinitionMacro extends Fake
- implements FunctionDefinitionMacro {}
-
-class FakeMethodTypesMacro extends Fake implements MethodTypesMacro {}
-
-class FakeMethodDeclarationsMacro extends Fake
- implements MethodDeclarationsMacro {}
-
-class FakeMethodDefinitionMacro extends Fake implements MethodDefinitionMacro {}
-
-class FakeVariableTypesMacro extends Fake implements VariableTypesMacro {}
-
-class FakeVariableDeclarationsMacro extends Fake
- implements VariableDeclarationsMacro {}
-
-class FakeVariableDefinitionMacro extends Fake
- implements VariableDefinitionMacro {}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
deleted file mode 100644
index 502f9f9..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization_extensions.dart';
-import 'package:test/test.dart';
-
-import '../util.dart';
-
-void main() {
- group('json serializer', () {
- test('can serialize and deserialize basic data', () {
- var serializer = JsonSerializer();
- serializer
- ..addNum(1)
- ..addNullableNum(null)
- ..addString('hello')
- ..addNullableString(null)
- ..startList()
- ..addBool(true)
- ..startList()
- ..addNull()
- ..endList()
- ..addNullableBool(null)
- ..endList()
- ..addNum(1.0)
- ..startList()
- ..endList();
- expect(
- serializer.result,
- equals([
- 1,
- null,
- 'hello',
- null,
- [
- true,
- [null],
- null
- ],
- 1.0,
- [],
- ]));
- var deserializer = JsonDeserializer(serializer.result);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNum(), 1);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableNum(), null);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectString(), 'hello');
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableString(), null);
- expect(deserializer.moveNext(), true);
-
- deserializer.expectList();
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectBool(), true);
- expect(deserializer.moveNext(), true);
-
- deserializer.expectList();
- expect(deserializer.moveNext(), true);
- expect(deserializer.checkNull(), true);
- expect(deserializer.moveNext(), false);
-
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableBool(), null);
- expect(deserializer.moveNext(), false);
-
- // Have to move the parent again to advance it past the list entry.
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNum(), 1.0);
- expect(deserializer.moveNext(), true);
-
- deserializer.expectList();
- expect(deserializer.moveNext(), false);
-
- expect(deserializer.moveNext(), false);
- });
-
- test('remote instances', () async {
- var string = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
- typeArguments: const []);
- var foo = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- typeArguments: [string]);
- Object? serializedFoo;
- var serializer = JsonSerializer();
-
- withSerializationMode(SerializationMode.server, () {
- foo.serialize(serializer);
- serializedFoo = serializer.result;
- var response = roundTrip(serializedFoo);
- var deserializer = JsonDeserializer(response as List<Object?>);
- var instance = RemoteInstance.deserialize(deserializer);
- expect(instance, foo);
- });
- });
-
- group('declarations', () {
- final barType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Bar'),
- typeArguments: []);
- final fooType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: true,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- typeArguments: [barType]);
-
- test('NamedTypeAnnotation', () {
- expectSerializationEquality(fooType);
- });
-
- final fooNamedParam = ParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- defaultValue: null,
- isNamed: true,
- isRequired: true,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
- type: fooType);
-
- final barPositionalParam = ParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- defaultValue: Code.fromString('const Bar()'),
- isNamed: false,
- isRequired: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- type: barType);
-
- final zapTypeParam = TypeParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
- bounds: barType);
-
- // Transitively tests `TypeParameterDeclaration` and
- // `ParameterDeclaration`.
- test('FunctionTypeAnnotation', () {
- var functionType = FunctionTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: true,
- namedParameters: [fooNamedParam],
- positionalParameters: [barPositionalParam],
- returnType: fooType,
- typeParameters: [zapTypeParam],
- );
- expectSerializationEquality(functionType);
- });
-
- test('FunctionDeclaration', () {
- var function = FunctionDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
- isAbstract: true,
- isExternal: false,
- isGetter: true,
- isSetter: false,
- namedParameters: [],
- positionalParameters: [],
- returnType: fooType,
- typeParameters: []);
- expectSerializationEquality(function);
- });
-
- test('MethodDeclaration', () {
- var method = MethodDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
- isAbstract: false,
- isExternal: false,
- isGetter: false,
- isSetter: true,
- namedParameters: [fooNamedParam],
- positionalParameters: [barPositionalParam],
- returnType: fooType,
- typeParameters: [zapTypeParam],
- definingClass: fooType.identifier);
- expectSerializationEquality(method);
- });
-
- test('ConstructorDeclaration', () {
- var constructor = ConstructorDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
- isAbstract: false,
- isExternal: false,
- isGetter: false,
- isSetter: false,
- namedParameters: [fooNamedParam],
- positionalParameters: [barPositionalParam],
- returnType: fooType,
- typeParameters: [zapTypeParam],
- definingClass: fooType.identifier,
- isFactory: true,
- );
- expectSerializationEquality(constructor);
- });
-
- test('VariableDeclaration', () {
- var bar = VariableDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- isExternal: true,
- isFinal: false,
- isLate: true,
- initializer: ExpressionCode.fromString('Bar()'),
- type: barType,
- );
- expectSerializationEquality(bar);
- });
-
- test('FieldDeclaration', () {
- var bar = FieldDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- isExternal: false,
- isFinal: true,
- isLate: false,
- initializer: null,
- type: barType,
- definingClass: fooType.identifier,
- );
- expectSerializationEquality(bar);
- });
-
- var objectType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object'),
- isNullable: false,
- typeArguments: [],
- );
- var serializableType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Serializable'),
- isNullable: false,
- typeArguments: [],
- );
-
- test('ClassDeclaration', () {
- var fooClass = ClassDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- interfaces: [barType],
- isAbstract: true,
- isExternal: false,
- mixins: [serializableType],
- superclass: objectType,
- typeParameters: [zapTypeParam],
- );
- expectSerializationEquality(fooClass);
- });
-
- test('TypeAliasDeclaration', () {
- var typeAlias = TypeAliasDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
- typeParameters: [zapTypeParam],
- aliasedType: NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- typeArguments: [barType]),
- );
- expectSerializationEquality(typeAlias);
- });
- });
- });
-}
-
-/// Serializes [serializable] in server mode, then deserializes it in client
-/// mode, and checks that all the fields are the same.
-void expectSerializationEquality(Serializable serializable) {
- var serializer = JsonSerializer();
- withSerializationMode(SerializationMode.server, () {
- serializable.serialize(serializer);
- });
- withSerializationMode(SerializationMode.client, () {
- var deserializer = JsonDeserializer(serializer.result);
- var deserialized = (deserializer..moveNext()).expectRemoteInstance();
- if (deserialized is Declaration) {
- expect(serializable, deepEqualsDeclaration(deserialized));
- } else if (deserialized is TypeAnnotation) {
- expect(serializable, deepEqualsTypeAnnotation(deserialized));
- } else {
- throw new UnsupportedError('Unsupported object type $deserialized');
- }
- });
-}
-
-/// Deserializes [serialized] in client mode and sends it back.
-Object? roundTrip<Declaration>(Object? serialized) {
- return withSerializationMode(SerializationMode.client, () {
- var deserializer = JsonDeserializer(serialized as List<Object?>);
- var instance =
- RemoteInstance.deserialize<NamedTypeAnnotationImpl>(deserializer);
- var serializer = JsonSerializer();
- instance.serialize(serializer);
- return serializer.result;
- });
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
deleted file mode 100644
index 80136bd..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
-import 'package:_fe_analyzer_shared/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart'
- as mirrorExecutor;
-
-import 'package:test/test.dart';
-
-import '../util.dart';
-
-void main() {
- late MacroExecutor executor;
- late File simpleMacroFile;
-
- setUpAll(() {
- // We support running from either the root of the SDK or the package root.
- simpleMacroFile = File(
- 'pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart');
- if (!simpleMacroFile.existsSync()) {
- simpleMacroFile =
- File('test/macros/isolate_mirror_executor/simple_macro.dart');
- }
- });
-
- setUp(() async {
- executor = await mirrorExecutor.start();
- });
-
- tearDown(() {
- executor.close();
- });
-
- test('can load macros and create instances', () async {
- var clazzId =
- await executor.loadMacro(simpleMacroFile.absolute.uri, 'SimpleMacro');
- expect(clazzId, isNotNull, reason: 'Can load a macro.');
-
- var instanceId =
- await executor.instantiateMacro(clazzId, '', Arguments([], {}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with no arguments.');
-
- instanceId =
- await executor.instantiateMacro(clazzId, '', Arguments([1, 2], {}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with positional arguments.');
-
- instanceId = await executor.instantiateMacro(
- clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with named arguments.');
-
- var returnType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
- isNullable: false,
- typeArguments: const []);
- var definitionResult = await executor.executeDefinitionsPhase(
- instanceId,
- FunctionDeclarationImpl(
- id: RemoteInstance.uniqueId,
- isAbstract: false,
- isExternal: false,
- isGetter: false,
- isSetter: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
- namedParameters: [],
- positionalParameters: [],
- returnType: returnType,
- typeParameters: [],
- ),
- TestTypeResolver({
- returnType:
- TestNamedStaticType(returnType.identifier, 'dart:core', [])
- }),
- FakeClassIntrospector(),
- FakeTypeDeclarationResolver());
- expect(definitionResult.augmentations, hasLength(1));
- expect(definitionResult.augmentations.first.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment String foo() {
- print('x: 1, y: 2');
- return augment super();
- }'''));
- });
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
deleted file mode 100644
index 7972041..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-/// A very simple macro that annotates functions (or getters) with no arguments
-/// and adds a print statement to the top of them.
-class SimpleMacro implements FunctionDefinitionMacro {
- final int? x;
- final int? y;
-
- SimpleMacro([this.x, this.y]);
-
- SimpleMacro.named({this.x, this.y});
-
- @override
- FutureOr<void> buildDefinitionForFunction(
- FunctionDeclaration method, FunctionDefinitionBuilder builder) async {
- if (method.namedParameters
- .followedBy(method.positionalParameters)
- .isNotEmpty) {
- throw ArgumentError(
- 'This macro can only be run on functions with no arguments!');
- }
-
- // Test the type resolver and static type interfaces
- var staticReturnType = await builder.instantiateType(method.returnType);
- if (!(await staticReturnType.isExactly(staticReturnType))) {
- throw StateError('The return type should be exactly equal to itself!');
- }
- if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
- throw StateError('The return type should be a subtype of itself!');
- }
-
- builder.augment(FunctionBodyCode.fromString('''{
- print('x: $x, y: $y');
- return augment super();
- }'''));
- }
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
deleted file mode 100644
index cdd1725..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-import 'dart:isolate';
-
-import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
- as isolatedExecutor;
-
-import 'package:test/test.dart';
-
-import '../util.dart';
-
-void main() {
- late MacroExecutor executor;
- late File kernelOutputFile;
- final macroName = 'SimpleMacro';
- late MacroInstanceIdentifier instanceId;
- late Uri macroUri;
- late File simpleMacroFile;
- late Directory tmpDir;
-
- setUpAll(() async {
- // We support running from either the root of the SDK or the package root.
- simpleMacroFile = File(
- 'pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart');
- if (!simpleMacroFile.existsSync()) {
- simpleMacroFile = File('test/macros/isolated_executor/simple_macro.dart');
- }
- executor = await isolatedExecutor.start();
- tmpDir = Directory.systemTemp.createTempSync('isolated_executor_test');
- macroUri = simpleMacroFile.absolute.uri;
-
- var bootstrapContent = bootstrapMacroIsolate({
- macroUri.toString(): {
- macroName: ['', 'named']
- }
- });
- var bootstrapFile = File(tmpDir.uri.resolve('main.dart').toFilePath())
- ..writeAsStringSync(bootstrapContent);
- kernelOutputFile = File(tmpDir.uri.resolve('main.dart.dill').toFilePath());
- var buildSnapshotResult = await Process.run(Platform.resolvedExecutable, [
- '--snapshot=${kernelOutputFile.uri.toFilePath()}',
- '--snapshot-kind=kernel',
- '--packages=${(await Isolate.packageConfig)!}',
- bootstrapFile.uri.toFilePath(),
- ]);
- expect(buildSnapshotResult.exitCode, 0,
- reason: 'stdout: ${buildSnapshotResult.stdout}\n'
- 'stderr: ${buildSnapshotResult.stderr}');
-
- var clazzId = await executor.loadMacro(macroUri, macroName,
- precompiledKernelUri: kernelOutputFile.uri);
- expect(clazzId, isNotNull, reason: 'Can load a macro.');
-
- instanceId =
- await executor.instantiateMacro(clazzId, '', Arguments([], {}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with no arguments.');
-
- instanceId =
- await executor.instantiateMacro(clazzId, '', Arguments([1, 2], {}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with positional arguments.');
-
- instanceId = await executor.instantiateMacro(
- clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
- expect(instanceId, isNotNull,
- reason: 'Can create an instance with named arguments.');
- });
-
- tearDownAll(() {
- if (tmpDir.existsSync()) tmpDir.deleteSync(recursive: true);
- executor.close();
- });
-
- group('run macros', () {
- group('in the types phase', () {
- test('on functions', () async {
- var result =
- await executor.executeTypesPhase(instanceId, Fixtures.myFunction);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyFunction {}'));
- });
-
- test('on methods', () async {
- var result =
- await executor.executeTypesPhase(instanceId, Fixtures.myMethod);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyMethod {}'));
- });
-
- test('on getters', () async {
- var result = await executor.executeTypesPhase(
- instanceId,
- Fixtures.myVariableGetter,
- );
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyVariableGetter {}'));
- });
-
- test('on setters', () async {
- var result = await executor.executeTypesPhase(
- instanceId,
- Fixtures.myVariableSetter,
- );
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyVariableSetter {}'));
- });
-
- test('on variables', () async {
- var result = await executor.executeTypesPhase(
- instanceId,
- Fixtures.myVariable,
- );
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedBy_myVariable {}'));
- });
-
- test('on constructors', () async {
- var result = await executor.executeTypesPhase(
- instanceId, Fixtures.myConstructor);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyConstructor {}'));
- });
-
- test('on fields', () async {
- var result =
- await executor.executeTypesPhase(instanceId, Fixtures.myField);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('class GeneratedByMyField {}'));
- });
-
- test('on classes', () async {
- var result =
- await executor.executeTypesPhase(instanceId, Fixtures.myClass);
- expect(
- result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace(
- 'class MyClassBuilder implements Builder<MyClass> {}'));
- });
- });
-
- group('in the declaration phase', () {
- test('on functions', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myFunction,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(
- result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace(
- 'String delegateMyFunction() => myFunction();'));
- });
-
- test('on methods', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myMethod,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(
- result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace(
- 'String delegateMemberMyMethod() => myMethod();'));
- });
-
- test('on constructors', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myConstructor,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment class MyClass {
- factory MyClass.myConstructorDelegate() => MyClass.myConstructor();
- }'''));
- });
-
- test('on getters', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myVariableGetter,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- String get delegateMyVariable => myVariable;'''));
- });
-
- test('on setters', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myVariableSetter,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- void set delegateMyVariable(String value) => myVariable = value;'''));
- });
-
- test('on variables', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myVariable,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- String get delegate_myVariable => _myVariable;'''));
- });
-
- test('on fields', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myField,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment class MyClass {
- String get delegateMyField => myField;
- }'''));
- });
-
- test('on classes', () async {
- var result = await executor.executeDeclarationsPhase(
- instanceId,
- Fixtures.myClass,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment class MyClass {
- static const List<String> fieldNames = ['myField',];
- }'''));
- });
- });
-
- group('in the definition phase', () {
- test('on functions', () async {
- var result = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myFunction,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment String myFunction() {
- print('isAbstract: false');
- print('isExternal: false');
- print('isGetter: false');
- print('isSetter: false');
- print('returnType: String');
- return augment super();
- }'''));
- });
-
- test('on methods', () async {
- var definitionResult = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myMethod,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(definitionResult.augmentations, hasLength(2));
- var augmentationStrings = definitionResult.augmentations
- .map((a) => a.debugString().toString())
- .toList();
- expect(augmentationStrings, unorderedEquals(methodDefinitionMatchers));
- });
-
- test('on constructors', () async {
- var definitionResult = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myConstructor,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(definitionResult.augmentations, hasLength(1));
- expect(definitionResult.augmentations.first.debugString().toString(),
- constructorDefinitionMatcher);
- });
-
- test('on getters', () async {
- var result = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myVariableGetter,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment String myVariable() {
- print('isAbstract: false');
- print('isExternal: false');
- print('isGetter: true');
- print('isSetter: false');
- print('returnType: String');
- return augment super;
- }'''));
- });
-
- test('on setters', () async {
- var result = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myVariableSetter,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(result.augmentations.single.debugString().toString(),
- equalsIgnoringWhitespace('''
- augment void myVariable(String value, ) {
- print('isAbstract: false');
- print('isExternal: false');
- print('isGetter: false');
- print('isSetter: true');
- print('returnType: void');
- print('positionalParam: String value');
- return augment super = value;
- }'''));
- });
-
- test('on variables', () async {
- var result = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myVariable,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(
- result.augmentations.map((a) => a.debugString().toString()),
- unorderedEquals([
- equalsIgnoringWhitespace('''
- augment String get _myVariable {
- print('parentClass: ');
- print('isExternal: false');
- print('isFinal: true');
- print('isLate: false');
- return augment super;
- }'''),
- equalsIgnoringWhitespace('''
- augment set _myVariable(String value) {
- augment super = value;
- }'''),
- equalsIgnoringWhitespace('''
- augment final String _myVariable = '';
- '''),
- ]));
- });
-
- test('on fields', () async {
- var definitionResult = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myField,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- expect(definitionResult.augmentations, hasLength(1));
- expect(definitionResult.augmentations.first.debugString().toString(),
- fieldDefinitionMatcher);
- });
-
- test('on classes', () async {
- var definitionResult = await executor.executeDefinitionsPhase(
- instanceId,
- Fixtures.myClass,
- Fixtures.testTypeResolver,
- Fixtures.testClassIntrospector,
- Fixtures.testTypeDeclarationResolver);
- var augmentationStrings = definitionResult.augmentations
- .map((a) => a.debugString().toString())
- .toList();
- expect(
- augmentationStrings,
- unorderedEquals([
- ...methodDefinitionMatchers,
- constructorDefinitionMatcher,
- fieldDefinitionMatcher
- ]));
- });
- });
- });
-}
-
-final constructorDefinitionMatcher = equalsIgnoringWhitespace('''
-augment class MyClass {
- augment MyClass.myConstructor() {
- print('definingClass: MyClass');
- print('isFactory: false');
- print('isAbstract: false');
- print('isExternal: false');
- print('isGetter: false');
- print('isSetter: false');
- print('returnType: MyClass');
- return augment super();
- }
-}''');
-
-final fieldDefinitionMatcher = equalsIgnoringWhitespace('''
-augment class MyClass {
- augment String get myField {
- print('parentClass: MyClass');
- print('isExternal: false');
- print('isFinal: false');
- print('isLate: false');
- return augment super;
- }
- augment set myField(String value) {
- augment super = value;
- }
-}''');
-
-final methodDefinitionMatchers = [
- equalsIgnoringWhitespace('''
- augment class MyClass {
- augment String myMethod() {
- print('definingClass: MyClass');
- print('isAbstract: false');
- print('isExternal: false');
- print('isGetter: false');
- print('isSetter: false');
- print('returnType: String');
- return augment super();
- }
- }
- '''),
- equalsIgnoringWhitespace('''
- augment class MyClass {
- augment String myMethod() {
- print('x: 1, y: 2');
- print('parentClass: MyClass');
- print('superClass: MySuperclass');
- print('interface: MyInterface');
- print('mixin: MyMixin');
- print('field: myField');
- print('method: myMethod');
- print('constructor: myConstructor');
- return augment super();
- }
- }'''),
-];
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
deleted file mode 100644
index 610c83e..0000000
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-/// A very simple macro that augments any declaration it is given, usually
-/// adding print statements and inlining values from the declaration object
-/// for comparision with expected values in tests.
-///
-/// When applied to [MethodDeclaration]s there is some extra work that happens
-/// to validate the introspection APIs work as expected.
-class SimpleMacro
- implements
- ClassTypesMacro,
- ClassDeclarationsMacro,
- ClassDefinitionMacro,
- ConstructorTypesMacro,
- ConstructorDeclarationsMacro,
- ConstructorDefinitionMacro,
- FieldTypesMacro,
- FieldDeclarationsMacro,
- FieldDefinitionMacro,
- FunctionTypesMacro,
- FunctionDeclarationsMacro,
- FunctionDefinitionMacro,
- MethodTypesMacro,
- MethodDeclarationsMacro,
- MethodDefinitionMacro,
- VariableTypesMacro,
- VariableDeclarationsMacro,
- VariableDefinitionMacro {
- final int? x;
- final int? y;
-
- SimpleMacro([this.x, this.y]);
-
- SimpleMacro.named({this.x, this.y});
-
- @override
- FutureOr<void> buildDeclarationsForClass(
- ClassDeclaration clazz, ClassMemberDeclarationBuilder builder) async {
- var fields = await builder.fieldsOf(clazz);
- builder.declareInClass(DeclarationCode.fromParts([
- 'static const List<String> fieldNames = [',
- for (var field in fields) "'${field.identifier.name}',",
- '];',
- ]));
- }
-
- @override
- FutureOr<void> buildDeclarationsForConstructor(
- ConstructorDeclaration constructor,
- ClassMemberDeclarationBuilder builder) {
- if (constructor.positionalParameters.isNotEmpty ||
- constructor.namedParameters.isNotEmpty) {
- throw new UnsupportedError(
- 'Can only run on constructors with no parameters!');
- }
- var className = constructor.definingClass.name;
- var constructorName = constructor.identifier.name;
- builder.declareInClass(DeclarationCode.fromString(
- 'factory $className.${constructorName}Delegate() => '
- '$className.$constructorName();'));
- }
-
- @override
- FutureOr<void> buildDeclarationsForFunction(
- FunctionDeclaration function, DeclarationBuilder builder) {
- if (!function.isSetter &&
- (function.positionalParameters.isNotEmpty ||
- function.namedParameters.isNotEmpty)) {
- throw new UnsupportedError(
- 'Can only run on functions with no parameters!');
- }
- var functionName = function.identifier.name;
- builder.declareInLibrary(DeclarationCode.fromParts([
- function.returnType.code,
- if (function.isGetter) ' get' else if (function.isSetter) ' set ',
- ' delegate${functionName.capitalize()}',
- if (!function.isGetter) ...[
- '(',
- if (function.isSetter) ...[
- function.positionalParameters.first.type.code,
- ' value',
- ],
- ')',
- ],
- ' => ${functionName}',
- function.isGetter
- ? ''
- : function.isSetter
- ? ' = value'
- : '()',
- ';',
- ]));
- }
-
- @override
- FutureOr<void> buildDeclarationsForMethod(
- MethodDeclaration method, ClassMemberDeclarationBuilder builder) {
- if (method.positionalParameters.isNotEmpty ||
- method.namedParameters.isNotEmpty) {
- throw new UnsupportedError('Can only run on method with no parameters!');
- }
- var methodName = method.identifier.name;
- builder.declareInLibrary(DeclarationCode.fromParts([
- method.returnType.code,
- ' delegateMember${methodName.capitalize()}() => $methodName();',
- ]));
- }
-
- @override
- FutureOr<void> buildDeclarationsForVariable(
- VariableDeclaration variable, DeclarationBuilder builder) {
- var variableName = variable.identifier.name;
- builder.declareInLibrary(DeclarationCode.fromParts([
- variable.type.code,
- ' get delegate${variableName.capitalize()} => $variableName;',
- ]));
- }
-
- @override
- FutureOr<void> buildDeclarationsForField(
- FieldDeclaration field, ClassMemberDeclarationBuilder builder) {
- var fieldName = field.identifier.name;
- builder.declareInClass(DeclarationCode.fromParts([
- field.type.code,
- ' get delegate${fieldName.capitalize()} => $fieldName;',
- ]));
- }
-
- @override
- Future<void> buildDefinitionForClass(
- ClassDeclaration clazz, ClassDefinitionBuilder builder) async {
- // Apply ourself to all our members
- var fields = (await builder.fieldsOf(clazz));
- for (var field in fields) {
- await buildDefinitionForField(
- field, await builder.buildField(field.identifier));
- }
- var methods = (await builder.methodsOf(clazz));
- for (var method in methods) {
- await buildDefinitionForMethod(
- method, await builder.buildMethod(method.identifier));
- }
- var constructors = (await builder.constructorsOf(clazz));
- for (var constructor in constructors) {
- await buildDefinitionForConstructor(
- constructor, await builder.buildConstructor(constructor.identifier));
- }
- }
-
- @override
- Future<void> buildDefinitionForConstructor(ConstructorDeclaration constructor,
- ConstructorDefinitionBuilder builder) async {
- var clazz = await builder.declarationOf(constructor.definingClass)
- as ClassDeclaration;
- var fields = (await builder.fieldsOf(clazz));
-
- builder.augment(
- body: _buildFunctionAugmentation(constructor),
- initializers: [
- for (var field in fields)
- // TODO: Compare against actual `int` type.
- if (field.isFinal &&
- (field.type as NamedTypeAnnotation).identifier.name == 'int')
- Code.fromParts([field.identifier, ' = ${x!}']),
- ],
- );
- }
-
- @override
- Future<void> buildDefinitionForField(
- FieldDeclaration field, VariableDefinitionBuilder builder) async =>
- buildDefinitionForVariable(field, builder);
-
- @override
- Future<void> buildDefinitionForFunction(
- FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
- builder.augment(_buildFunctionAugmentation(function));
- }
-
- @override
- Future<void> buildDefinitionForMethod(
- MethodDeclaration method, FunctionDefinitionBuilder builder) async {
- await buildDefinitionForFunction(method, builder);
-
- // Test the type declaration resolver
- var parentClass =
- await builder.declarationOf(method.definingClass) as ClassDeclaration;
- // Should be able to find ourself in the methods of the parent class.
- (await builder.methodsOf(parentClass))
- .singleWhere((m) => m.identifier == method.identifier);
-
- // Test the class introspector
- var superClass = (await builder.superclassOf(parentClass))!;
- var interfaces = (await builder.interfacesOf(parentClass));
- var mixins = (await builder.mixinsOf(parentClass));
- var fields = (await builder.fieldsOf(parentClass));
- var methods = (await builder.methodsOf(parentClass));
- var constructors = (await builder.constructorsOf(parentClass));
-
- // Test the type resolver and static type interfaces
- var staticReturnType = await builder.instantiateType(method.returnType);
- if (!(await staticReturnType.isExactly(staticReturnType))) {
- throw StateError('The return type should be exactly equal to itself!');
- }
- if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
- throw StateError('The return type should be a subtype of itself!');
- }
-
- // TODO: Use `builder.instantiateCode` instead once implemented.
- var classType =
- await builder.instantiateType(constructors.first.returnType);
- if (await staticReturnType.isExactly(classType)) {
- throw StateError(
- 'The return type should not be exactly equal to the class type');
- }
- if (await staticReturnType.isSubtypeOf(classType)) {
- throw StateError(
- 'The return type should not be a subtype of the class type!');
- }
-
- builder.augment(FunctionBodyCode.fromParts([
- '''{
- print('x: $x, y: $y');
- print('parentClass: ${parentClass.identifier.name}');
- print('superClass: ${superClass.identifier.name}');''',
- for (var interface in interfaces)
- "\n print('interface: ${interface.identifier.name}');",
- for (var mixin in mixins)
- "\n print('mixin: ${mixin.identifier.name}');",
- for (var field in fields)
- "\n print('field: ${field.identifier.name}');",
- for (var method in methods)
- "\n print('method: ${method.identifier.name}');",
- for (var constructor in constructors)
- "\n print('constructor: ${constructor.identifier.name}');",
- '''
-\n return augment super();
- }''',
- ]));
- }
-
- @override
- Future<void> buildDefinitionForVariable(
- VariableDeclaration variable, VariableDefinitionBuilder builder) async {
- var definingClass =
- variable is FieldDeclaration ? variable.definingClass.name : '';
- builder.augment(
- getter: DeclarationCode.fromParts([
- variable.type.code,
- ' get ',
- variable.identifier.name,
- ''' {
- print('parentClass: $definingClass');
- print('isExternal: ${variable.isExternal}');
- print('isFinal: ${variable.isFinal}');
- print('isLate: ${variable.isLate}');
- return augment super;
- }''',
- ]),
- setter: DeclarationCode.fromParts([
- 'set ',
- variable.identifier.name,
- '(',
- variable.type.code,
- ' value) { augment super = value; }'
- ]),
- initializer: variable.initializer,
- );
- }
-
- @override
- FutureOr<void> buildTypesForClass(
- ClassDeclaration clazz, TypeBuilder builder) {
- List<Object> _buildTypeParam(
- TypeParameterDeclaration typeParam, bool isFirst) {
- return [
- if (!isFirst) ', ',
- typeParam.identifier.name,
- if (typeParam.bounds != null) ...[
- ' extends ',
- typeParam.bounds!.code,
- ]
- ];
- }
-
- builder.declareType(DeclarationCode.fromParts([
- 'class ${clazz.identifier.name}Builder',
- if (clazz.typeParameters.isNotEmpty) ...[
- '<',
- ..._buildTypeParam(clazz.typeParameters.first, true),
- for (var typeParam in clazz.typeParameters.skip(1))
- ..._buildTypeParam(typeParam, false),
- '>',
- ],
- ' implements Builder<',
- clazz.identifier,
- if (clazz.typeParameters.isNotEmpty) ...[
- '<',
- clazz.typeParameters.first.identifier.name,
- for (var typeParam in clazz.typeParameters)
- ', ${typeParam.identifier.name}',
- '>',
- ],
- '> {}'
- ]));
- }
-
- @override
- FutureOr<void> buildTypesForConstructor(
- ConstructorDeclaration constructor, TypeBuilder builder) {
- builder.declareType(DeclarationCode.fromString(
- 'class GeneratedBy${constructor.identifier.name.capitalize()} {}'));
- }
-
- @override
- FutureOr<void> buildTypesForField(
- FieldDeclaration field, TypeBuilder builder) {
- builder.declareType(DeclarationCode.fromString(
- 'class GeneratedBy${field.identifier.name.capitalize()} {}'));
- }
-
- @override
- FutureOr<void> buildTypesForFunction(
- FunctionDeclaration function, TypeBuilder builder) {
- var suffix = function.isGetter
- ? 'Getter'
- : function.isSetter
- ? 'Setter'
- : '';
- builder.declareType(DeclarationCode.fromString(
- 'class GeneratedBy${function.identifier.name.capitalize()}'
- '$suffix {}'));
- }
-
- @override
- FutureOr<void> buildTypesForMethod(
- MethodDeclaration method, TypeBuilder builder) {
- builder.declareType(DeclarationCode.fromString(
- 'class GeneratedBy${method.identifier.name.capitalize()} {}'));
- }
-
- @override
- FutureOr<void> buildTypesForVariable(
- VariableDeclaration variable, TypeBuilder builder) {
- builder.declareType(DeclarationCode.fromString(
- 'class GeneratedBy${variable.identifier.name.capitalize()} {}'));
- }
-}
-
-FunctionBodyCode _buildFunctionAugmentation(FunctionDeclaration function) =>
- FunctionBodyCode.fromParts([
- '{\n',
- if (function is MethodDeclaration)
- "print('definingClass: ${function.definingClass.name}');\n",
- if (function is ConstructorDeclaration)
- "print('isFactory: ${function.isFactory}');\n",
- '''
- print('isAbstract: ${function.isAbstract}');
- print('isExternal: ${function.isExternal}');
- print('isGetter: ${function.isGetter}');
- print('isSetter: ${function.isSetter}');
- print('returnType: ''',
- function.returnType.code,
- "');\n",
- for (var param in function.positionalParameters) ...[
- "print('positionalParam: ",
- param.type.code,
- ' ${param.identifier.name}',
- if (param.defaultValue != null) ...[' = ', param.defaultValue!],
- "');\n",
- ],
- for (var param in function.namedParameters) ...[
- "print('namedParam: ",
- param.type.code,
- ' ${param.identifier.name}',
- if (param.defaultValue != null) ...[' = ', param.defaultValue!],
- "');\n",
- ],
- for (var param in function.typeParameters) ...[
- "print('typeParam: ${param.identifier.name} ",
- if (param.bounds != null) param.bounds!.code,
- "');\n",
- ],
- 'return augment super',
- if (function.isSetter) ...[
- ' = ',
- function.positionalParameters.first.identifier,
- ],
- if (!function.isGetter && !function.isSetter) '()',
- ''';
- }''',
- ]);
-
-extension _ on String {
- String capitalize() => '${this[0].toUpperCase()}${substring(1)}';
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index 831a4f8..edb0788 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -5,8 +5,9 @@
import 'dart:mirrors';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
-import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
import 'package:test/fake.dart';
import 'package:test/test.dart';
@@ -61,6 +62,8 @@
superclass[clazz];
}
+class FakeIdentifierResolver extends Fake implements IdentifierResolver {}
+
class FakeTypeDeclarationResolver extends Fake
implements TypeDeclarationResolver {}
@@ -76,24 +79,18 @@
}
class TestTypeResolver implements TypeResolver {
- final Map<TypeAnnotation, StaticType> staticTypes;
+ final Map<Identifier, StaticType> staticTypes;
TestTypeResolver(this.staticTypes);
@override
- Future<StaticType> instantiateType(
- covariant TypeAnnotation typeAnnotation) async {
- return staticTypes[typeAnnotation]!;
- }
-
- @override
- Future<StaticType> instantiateCode(ExpressionCode code) {
- // TODO: implement instantiateCode
- throw UnimplementedError();
+ Future<StaticType> resolve(covariant TypeAnnotationCode type) async {
+ assert(type.parts.length == 1);
+ return staticTypes[type.parts.first]!;
}
}
-// Doesn't handle generics etc but thats ok for now
+/// Doesn't handle generics etc but thats ok for now
class TestNamedStaticType implements NamedStaticType {
final IdentifierImpl identifier;
final String library;
@@ -114,6 +111,24 @@
(library == other.library && identifier.name == other.identifier.name);
}
+/// An identifier that knows the resolved version of itself.
+class TestIdentifier extends IdentifierImpl {
+ final ResolvedIdentifier resolved;
+
+ TestIdentifier({
+ required int id,
+ required String name,
+ required IdentifierKind kind,
+ required Uri uri,
+ required String? staticScope,
+ }) : resolved = ResolvedIdentifier(
+ kind: kind, name: name, staticScope: staticScope, uri: uri),
+ super(
+ id: id,
+ name: name,
+ );
+}
+
extension DebugCodeString on Code {
StringBuffer debugString([StringBuffer? buffer]) {
buffer ??= StringBuffer();
@@ -243,6 +258,7 @@
isAbstract: false,
isExternal: false,
isGetter: false,
+ isOperator: false,
isSetter: false,
namedParameters: [],
positionalParameters: [],
@@ -252,7 +268,6 @@
id: RemoteInstance.uniqueId,
identifier:
IdentifierImpl(id: RemoteInstance.uniqueId, name: '_myVariable'),
- initializer: ExpressionCode.fromString("''"),
isExternal: false,
isFinal: true,
isLate: false,
@@ -264,6 +279,7 @@
isAbstract: false,
isExternal: false,
isGetter: true,
+ isOperator: false,
isSetter: false,
namedParameters: [],
positionalParameters: [],
@@ -276,6 +292,7 @@
isAbstract: false,
isExternal: false,
isGetter: false,
+ isOperator: false,
isSetter: true,
namedParameters: [],
positionalParameters: [
@@ -283,7 +300,6 @@
id: RemoteInstance.uniqueId,
identifier:
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'value'),
- defaultValue: null,
isNamed: false,
isRequired: true,
type: stringType)
@@ -330,6 +346,7 @@
isAbstract: false,
isExternal: false,
isGetter: false,
+ isOperator: false,
isSetter: false,
namedParameters: [],
positionalParameters: [],
@@ -340,12 +357,12 @@
static final myField = FieldDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
- initializer: null,
isExternal: false,
isFinal: false,
isLate: false,
type: stringType,
- definingClass: myClassType.identifier);
+ definingClass: myClassType.identifier,
+ isStatic: false);
static final myInterface = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: myInterfaceType.identifier,
@@ -361,12 +378,14 @@
isAbstract: false,
isExternal: false,
isGetter: false,
+ isOperator: false,
isSetter: false,
namedParameters: [],
positionalParameters: [],
returnType: stringType,
typeParameters: [],
- definingClass: myClassType.identifier);
+ definingClass: myClassType.identifier,
+ isStatic: false);
static final myMixin = ClassDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: myMixinType.identifier,
@@ -390,8 +409,9 @@
myClassType.identifier, 'package:my_package/my_package.dart', []);
static final testTypeResolver = TestTypeResolver({
- stringType: TestNamedStaticType(stringType.identifier, 'dart:core', []),
- myClassType: myClassStaticType,
+ stringType.identifier:
+ TestNamedStaticType(stringType.identifier, 'dart:core', []),
+ myClass.identifier: myClassStaticType,
});
static final testClassIntrospector = TestClassIntrospector(
constructors: {
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index e9f6fb0..6dab119 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -362,7 +362,7 @@
/// or a from environment constructor.
bool _isAllowedExternalUsage(Member member) {
Uri uri = member.enclosingLibrary.importUri;
- return uri.scheme == 'dart' &&
+ return uri.isScheme('dart') &&
_pathsWithAllowedDartExternalUsage.contains(uri.path) ||
_allowedNativeTestPatterns.any((pattern) => uri.path.contains(pattern));
}
diff --git a/pkg/analysis_server/OWNERS b/pkg/analysis_server/OWNERS
new file mode 100644
index 0000000..1592b3e
--- /dev/null
+++ b/pkg/analysis_server/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_ANALYZER
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 560c08b..be632ea 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- 1.32.9
+ 1.32.10
</h1>
<p>
This document contains a specification of the API provided by the
@@ -236,6 +236,10 @@
ignoring the item or treating it with some default/fallback handling.
</p>
<h3>Changelog</h3>
+<h4>1.32.10</h4>
+<ul>
+ <li>The <tt>MOVE_FILE</tt> refactor now supports moving/renaming folders.</li>
+</ul>
<h4>1.32.8</h4>
<ul>
<li>Added <tt>server.cancelRequest</tt> to allow clients to request cancellation
@@ -969,7 +973,8 @@
</p>
<p>
If a package root is a file, then the analyzer
- will behave as though that file is a ".packages" file in the
+ will behave as though that file is a
+ ".dart_tool/package_config.json" file in the
source directory. The effect is the same as specifying the file
as a "--packages" parameter to the Dart VM when
executing any Dart file inside the source directory.
@@ -3118,6 +3123,7 @@
+
<dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
<p>
A directive to begin overlaying the contents of a file. The supplied
@@ -3479,6 +3485,27 @@
The label associated with this range that should be displayed to the
user.
</p>
+ </dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionCaseMatchingMode">CompletionCaseMatchingMode: String</a></dt><dd>
+ <p>
+ An enumeration of the character case matching modes that the user may set in the client.
+ </p>
+
+ <dl><dt class="value">FIRST_CHAR</dt><dd>
+
+ <p>
+ Match the first character case only when filtering completions, the default for this
+ enumeration.
+ </p>
+ </dd><dt class="value">ALL_CHARS</dt><dd>
+
+ <p>
+ Match all character cases when filtering completion lists.
+ </p>
+ </dd><dt class="value">NONE</dt><dd>
+
+ <p>
+ Do not match character cases when filtering completion lists.
+ </p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionId">CompletionId: String</a></dt><dd>
<p>
@@ -4754,7 +4781,8 @@
<dl><dt class="field"><b>positions: List<<a href="#type_Position">Position</a>></b></dt><dd>
<p>
- The positions of the regions that should be edited simultaneously.
+ The positions of the regions (after applying the relevant edits) that
+ should be edited simultaneously.
</p>
</dd><dt class="field"><b>length: int</b></dt><dd>
@@ -6044,10 +6072,15 @@
</p>
</dd></dl></dd><dt class="refactoring">MOVE_FILE</dt><dd>
<p>
- Move the given file and update all of the references to that file
- and from it. The move operation is supported in general case - for
- renaming a file in the same folder, moving it to a different folder
- or both.
+ Move the given file or folder and update all of the references to
+ and from it. The move operation is supported in general case -
+ for renaming an item in the same folder, moving it to a different
+ folder or both.
+
+ Moving or renaming large folders may take time and clients should
+ consider showing an indicator to the user with the ability to
+ cancel the request (which can be done using
+ <tt>server.cancelRequest</tt>).
</p>
<p>
The refactoring must be activated before an actual file moving
@@ -6115,7 +6148,7 @@
TODO: TBD
</p>
<h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li><li><a href="#request_server.cancelRequest">cancelRequest</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.log">log</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getPostfixCompletion">getPostfixCompletion</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h4>flutter (<a href="#domain_flutter">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_flutter.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_flutter.outline">outline</a></li></ul></div></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_BulkFix">BulkFix</a></li><li><a href="#type_BulkFixDetail">BulkFixDetail</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionMode">CompletionMode</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FlutterOutline">FlutterOutline</a></li><li><a href="#type_FlutterOutlineAttribute">FlutterOutlineAttribute</a></li><li><a href="#type_FlutterOutlineKind">FlutterOutlineKind</a></li><li><a href="#type_FlutterService">FlutterService</a></li><li><a href="#type_FlutterWidgetProperty">FlutterWidgetProperty</a></li><li><a href="#type_FlutterWidgetPropertyEditor">FlutterWidgetPropertyEditor</a></li><li><a href="#type_FlutterWidgetPropertyEditorKind">FlutterWidgetPropertyEditorKind</a></li><li><a href="#type_FlutterWidgetPropertyValue">FlutterWidgetPropertyValue</a></li><li><a href="#type_FlutterWidgetPropertyValueEnumItem">FlutterWidgetPropertyValueEnumItem</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li><li><a href="#request_server.cancelRequest">cancelRequest</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.log">log</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getPostfixCompletion">getPostfixCompletion</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h4>flutter (<a href="#domain_flutter">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_flutter.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_flutter.outline">outline</a></li></ul></div></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_BulkFix">BulkFix</a></li><li><a href="#type_BulkFixDetail">BulkFixDetail</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionCaseMatchingMode">CompletionCaseMatchingMode</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionMode">CompletionMode</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FlutterOutline">FlutterOutline</a></li><li><a href="#type_FlutterOutlineAttribute">FlutterOutlineAttribute</a></li><li><a href="#type_FlutterOutlineKind">FlutterOutlineKind</a></li><li><a href="#type_FlutterService">FlutterService</a></li><li><a href="#type_FlutterWidgetProperty">FlutterWidgetProperty</a></li><li><a href="#type_FlutterWidgetPropertyEditor">FlutterWidgetPropertyEditor</a></li><li><a href="#type_FlutterWidgetPropertyEditorKind">FlutterWidgetPropertyEditorKind</a></li><li><a href="#type_FlutterWidgetPropertyValue">FlutterWidgetPropertyValue</a></li><li><a href="#type_FlutterWidgetPropertyValueEnumItem">FlutterWidgetPropertyValueEnumItem</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
</body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index ffba325..5e3a9c5 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -36,7 +36,6 @@
aliasedType: aliasedType,
parameters: elementParameters,
returnType: elementReturnType,
- libraryUri: element.library?.source.uri.toString(),
);
}
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 3baa946..e8a4e7e 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.9';
+const String PROTOCOL_VERSION = '1.32.10';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -138,6 +138,8 @@
const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_CASE_MATCHING_MODE =
+ 'completionCaseMatchingMode';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_MODE =
'completionMode';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 98395e9..dc2c12a 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -2583,9 +2583,9 @@
/// the normal package: URI resolution mechanism.
///
/// If a package root is a file, then the analyzer will behave as though that
- /// file is a ".packages" file in the source directory. The effect is the
- /// same as specifying the file as a "--packages" parameter to the Dart VM
- /// when executing any Dart file inside the source directory.
+ /// file is a ".dart_tool/package_config.json" file in the source directory.
+ /// The effect is the same as specifying the file as a "--packages" parameter
+ /// to the Dart VM when executing any Dart file inside the source directory.
///
/// Files in any directories that are not overridden by this mapping have
/// their package: URI's resolved using the normal pubspec.yaml mechanism. If
@@ -4215,6 +4215,68 @@
);
}
+/// CompletionCaseMatchingMode
+///
+/// enum {
+/// FIRST_CHAR
+/// ALL_CHARS
+/// NONE
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionCaseMatchingMode implements Enum {
+ /// Match the first character case only when filtering completions, the
+ /// default for this enumeration.
+ static const CompletionCaseMatchingMode FIRST_CHAR =
+ CompletionCaseMatchingMode._('FIRST_CHAR');
+
+ /// Match all character cases when filtering completion lists.
+ static const CompletionCaseMatchingMode ALL_CHARS =
+ CompletionCaseMatchingMode._('ALL_CHARS');
+
+ /// Do not match character cases when filtering completion lists.
+ static const CompletionCaseMatchingMode NONE =
+ CompletionCaseMatchingMode._('NONE');
+
+ /// A list containing all of the enum values that are defined.
+ static const List<CompletionCaseMatchingMode> VALUES =
+ <CompletionCaseMatchingMode>[FIRST_CHAR, ALL_CHARS, NONE];
+
+ @override
+ final String name;
+
+ const CompletionCaseMatchingMode._(this.name);
+
+ factory CompletionCaseMatchingMode(String name) {
+ switch (name) {
+ case 'FIRST_CHAR':
+ return FIRST_CHAR;
+ case 'ALL_CHARS':
+ return ALL_CHARS;
+ case 'NONE':
+ return NONE;
+ }
+ throw Exception('Illegal enum value: $name');
+ }
+
+ factory CompletionCaseMatchingMode.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+ if (json is String) {
+ try {
+ return CompletionCaseMatchingMode(json);
+ } catch (_) {
+ // Fall through
+ }
+ }
+ throw jsonDecoder.mismatch(jsonPath, 'CompletionCaseMatchingMode', json);
+ }
+
+ @override
+ String toString() => 'CompletionCaseMatchingMode.$name';
+
+ String toJson() => name;
+}
+
/// completion.existingImports params
///
/// {
@@ -4683,6 +4745,7 @@
/// "file": FilePath
/// "offset": int
/// "maxResults": int
+/// "completionCaseMatchingMode": optional CompletionCaseMatchingMode
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -4698,6 +4761,10 @@
/// to true.
int maxResults;
+ /// The mode of code completion being invoked. If no value is provided,
+ /// MATCH_FIRST_CHAR will be assumed.
+ CompletionCaseMatchingMode? completionCaseMatchingMode;
+
/// The mode of code completion being invoked. If no value is provided, BASIC
/// will be assumed. BASIC is also the only currently supported.
CompletionMode? completionMode;
@@ -4714,7 +4781,10 @@
int? timeout;
CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults,
- {this.completionMode, this.invocationCount, this.timeout});
+ {this.completionCaseMatchingMode,
+ this.completionMode,
+ this.invocationCount,
+ this.timeout});
factory CompletionGetSuggestions2Params.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4739,6 +4809,13 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'maxResults');
}
+ CompletionCaseMatchingMode? completionCaseMatchingMode;
+ if (json.containsKey('completionCaseMatchingMode')) {
+ completionCaseMatchingMode = CompletionCaseMatchingMode.fromJson(
+ jsonDecoder,
+ jsonPath + '.completionCaseMatchingMode',
+ json['completionCaseMatchingMode']);
+ }
CompletionMode? completionMode;
if (json.containsKey('completionMode')) {
completionMode = CompletionMode.fromJson(
@@ -4754,6 +4831,7 @@
timeout = jsonDecoder.decodeInt(jsonPath + '.timeout', json['timeout']);
}
return CompletionGetSuggestions2Params(file, offset, maxResults,
+ completionCaseMatchingMode: completionCaseMatchingMode,
completionMode: completionMode,
invocationCount: invocationCount,
timeout: timeout);
@@ -4774,6 +4852,11 @@
result['file'] = file;
result['offset'] = offset;
result['maxResults'] = maxResults;
+ var completionCaseMatchingMode = this.completionCaseMatchingMode;
+ if (completionCaseMatchingMode != null) {
+ result['completionCaseMatchingMode'] =
+ completionCaseMatchingMode.toJson();
+ }
var completionMode = this.completionMode;
if (completionMode != null) {
result['completionMode'] = completionMode.toJson();
@@ -4803,6 +4886,7 @@
return file == other.file &&
offset == other.offset &&
maxResults == other.maxResults &&
+ completionCaseMatchingMode == other.completionCaseMatchingMode &&
completionMode == other.completionMode &&
invocationCount == other.invocationCount &&
timeout == other.timeout;
@@ -4815,6 +4899,7 @@
file,
offset,
maxResults,
+ completionCaseMatchingMode,
completionMode,
invocationCount,
timeout,
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 1350c46..12ae415 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -703,8 +703,9 @@
@override
void applyFileRemoved(String file) {
- sendAnalysisNotificationFlushResults(analysisServer, [file]);
- filesToFlush.remove(file);
+ if (filesToFlush.remove(file)) {
+ sendAnalysisNotificationFlushResults(analysisServer, [file]);
+ }
}
@override
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 4f6aaaa3..25a8bf9 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -131,7 +131,7 @@
});
var result = CiderCompletionResult._(
- suggestions: suggestions,
+ suggestions: suggestions.map((e) => e.build()).toList(),
performance: CiderCompletionPerformance._(
operations: _performanceRoot.children.first,
),
@@ -157,25 +157,25 @@
///
/// TODO(scheglov) Implement show / hide combinators.
/// TODO(scheglov) Implement prefixes.
- List<CompletionSuggestion> _importedLibrariesSuggestions({
+ List<CompletionSuggestionBuilder> _importedLibrariesSuggestions({
required LibraryElement target,
required OperationPerformanceImpl performance,
}) {
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
for (var importedLibrary in target.importedLibraries) {
var importedSuggestions = _importedLibrarySuggestions(
element: importedLibrary,
performance: performance,
);
- suggestions.addAll(importedSuggestions);
+ suggestionBuilders.addAll(importedSuggestions);
}
- performance.getDataInt('count').add(suggestions.length);
- return suggestions;
+ performance.getDataInt('count').add(suggestionBuilders.length);
+ return suggestionBuilders;
}
/// Return cached, or compute unprefixed suggestions for all elements
/// exported from the library.
- List<CompletionSuggestion> _importedLibrarySuggestions({
+ List<CompletionSuggestionBuilder> _importedLibrarySuggestions({
required LibraryElement element,
required OperationPerformanceImpl performance,
}) {
@@ -198,13 +198,15 @@
);
_cache._importedLibraries[path] = cacheEntry;
}
- return cacheEntry.suggestions;
+ return cacheEntry.suggestionBuilders;
}
/// Compute all unprefixed suggestions for all elements exported from
/// the library.
- List<CompletionSuggestion> _librarySuggestions(LibraryElement element) {
+ List<CompletionSuggestionBuilder> _librarySuggestions(
+ LibraryElement element) {
var suggestionBuilder = SuggestionBuilder(_dartCompletionRequest);
+ suggestionBuilder.libraryUriStr = element.source.uri.toString();
var visitor = LibraryElementSuggestionBuilder(
_dartCompletionRequest, suggestionBuilder);
var exportMap = element.exportNamespace.definedNames;
@@ -250,7 +252,7 @@
class _CiderImportedLibrarySuggestions {
final String signature;
- final List<CompletionSuggestion> suggestions;
+ final List<CompletionSuggestionBuilder> suggestionBuilders;
- _CiderImportedLibrarySuggestions(this.signature, this.suggestions);
+ _CiderImportedLibrarySuggestions(this.signature, this.suggestionBuilders);
}
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 0b7a0fc..44eadad 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -31,19 +31,21 @@
_flutterWidgetState = _findFlutterStateClass(element, name);
RefactoringStatus? status;
- if (element is LocalVariableElement) {
- status = validateVariableName(name);
- } else if (element is ParameterElement) {
+ if (element is ParameterElement) {
status = validateParameterName(name);
+ } else if (element is VariableElement) {
+ status = validateVariableName(name);
} else if (element is FunctionElement) {
status = validateFunctionName(name);
- } else if (element is TopLevelVariableElement) {
- status = validateVariableName(name);
+ } else if (element is FieldElement) {
+ status = validateFieldName(name);
} else if (element is TypeAliasElement) {
status = validateTypeAliasName(name);
} else if (element is ClassElement) {
status = validateClassName(name);
- } else if (status == null) {
+ }
+
+ if (status == null) {
return null;
}
return CheckNameResponse(status, this);
@@ -95,7 +97,6 @@
for (var element in elements) {
matches.addAll(canRename._fileResolver.findReferences(element));
}
-
FlutterWidgetRename? flutterRename;
if (canRename._flutterWidgetState != null) {
var stateWidget = canRename._flutterWidgetState!;
diff --git a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
index 76a08e2..856e20d 100644
--- a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
@@ -51,7 +51,7 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
- var labelText = node.constructorName.type2.name.name;
+ var labelText = node.constructorName.type.name.name;
var name = node.constructorName.name;
if (name != null) {
labelText += '.${name.name}';
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index df18a65..303ffc6 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -253,8 +253,7 @@
// prepare type
HighlightRegionType? type;
if (element is FieldElement) {
- var enclosingElement = element.enclosingElement;
- if (enclosingElement is ClassElement && enclosingElement.isEnum) {
+ if (element.isEnumConstant) {
type = HighlightRegionType.ENUM_CONSTANT;
} else if (element.isStatic) {
type = HighlightRegionType.STATIC_FIELD_DECLARATION;
@@ -268,12 +267,12 @@
}
if (element is PropertyAccessorElement) {
var accessor = element;
- var enclosingElement = element.enclosingElement;
- if (accessor.variable is TopLevelVariableElement) {
+ var variable = accessor.variable;
+ if (variable is TopLevelVariableElement) {
type = accessor.isGetter
? HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE
: HighlightRegionType.TOP_LEVEL_SETTER_REFERENCE;
- } else if (enclosingElement is ClassElement && enclosingElement.isEnum) {
+ } else if (variable is FieldElement && variable.isEnumConstant) {
type = HighlightRegionType.ENUM_CONSTANT;
} else if (accessor.isStatic) {
type = accessor.isGetter
@@ -688,7 +687,7 @@
@override
void visitConstructorReference(ConstructorReference node) {
var constructorName = node.constructorName;
- constructorName.type2.accept(this);
+ constructorName.type.accept(this);
// We have a `ConstructorReference` only when it is resolved.
// TODO(scheglov) The `ConstructorName` in a tear-off always has a name,
@@ -698,6 +697,15 @@
}
@override
+ void visitConstructorSelector(ConstructorSelector node) {
+ computer._addRegion_node(
+ node.name,
+ HighlightRegionType.CONSTRUCTOR,
+ );
+ node.visitChildren(this);
+ }
+
+ @override
void visitContinueStatement(ContinueStatement node) {
computer._addRegion_token(node.continueKeyword, HighlightRegionType.KEYWORD,
semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
@@ -727,6 +735,15 @@
}
@override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ computer._addRegion_node(
+ node.name,
+ HighlightRegionType.ENUM_CONSTANT,
+ );
+ node.visitChildren(this);
+ }
+
+ @override
void visitEnumDeclaration(EnumDeclaration node) {
computer._addRegion_token(node.enumKeyword, HighlightRegionType.KEYWORD);
super.visitEnumDeclaration(node);
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index d51da04..e16e3078 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -82,7 +82,7 @@
if (library != null) {
var uri = library.source.uri;
var analysisSession = _unit.declaredElement?.session;
- if (uri.scheme == 'file' && analysisSession != null) {
+ if (uri.isScheme('file') && analysisSession != null) {
// for 'file:' URIs, use the path after the project root
var context = analysisSession.resourceProvider.pathContext;
var projectRootDir =
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index c4247be..61e3abb 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -29,12 +29,13 @@
unitContents.add(_newMixinOutline(
unitMember, _outlinesForMembers(unitMember.members)));
} else if (unitMember is EnumDeclaration) {
- var enumDeclaration = unitMember;
- var constantOutlines = <Outline>[];
- for (var constant in enumDeclaration.constants) {
- constantOutlines.add(_newEnumConstant(constant));
- }
- unitContents.add(_newEnumOutline(enumDeclaration, constantOutlines));
+ unitContents.add(
+ _newEnumOutline(unitMember, [
+ for (var constant in unitMember.constants)
+ _newEnumConstant(constant),
+ ..._outlinesForMembers(unitMember.members),
+ ]),
+ );
} else if (unitMember is ExtensionDeclaration) {
unitContents.add(_newExtensionOutline(
unitMember, _outlinesForMembers(unitMember.members)));
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index 92f68d0..41e8088 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -27,23 +27,9 @@
List<proto.Override> compute() {
for (var unitMember in _unit.declarations) {
if (unitMember is ClassOrMixinDeclaration) {
- for (var classMember in unitMember.members) {
- if (classMember is MethodDeclaration) {
- if (classMember.isStatic) {
- continue;
- }
- _addOverride(classMember.name);
- }
- if (classMember is FieldDeclaration) {
- if (classMember.isStatic) {
- continue;
- }
- List<VariableDeclaration> fields = classMember.fields.variables;
- for (var field in fields) {
- _addOverride(field.name);
- }
- }
- }
+ _classMembers(unitMember.members);
+ } else if (unitMember is EnumDeclaration) {
+ _classMembers(unitMember.members);
}
}
return _overrides;
@@ -73,6 +59,26 @@
}
}
}
+
+ void _classMembers(List<ClassMember> members) {
+ for (var classMember in members) {
+ if (classMember is MethodDeclaration) {
+ if (classMember.isStatic) {
+ continue;
+ }
+ _addOverride(classMember.name);
+ }
+ if (classMember is FieldDeclaration) {
+ if (classMember.isStatic) {
+ continue;
+ }
+ List<VariableDeclaration> fields = classMember.fields.variables;
+ for (var field in fields) {
+ _addOverride(field.name);
+ }
+ }
+ }
+ }
}
/// The container with elements that a class member overrides.
@@ -92,26 +98,6 @@
}
class _OverriddenElementsFinder {
- static const List<ElementKind> FIELD_KINDS = <ElementKind>[
- ElementKind.FIELD,
- ElementKind.GETTER,
- ElementKind.SETTER
- ];
-
- static const List<ElementKind> GETTER_KINDS = <ElementKind>[
- ElementKind.FIELD,
- ElementKind.GETTER
- ];
-
- static const List<ElementKind> METHOD_KINDS = <ElementKind>[
- ElementKind.METHOD
- ];
-
- static const List<ElementKind> SETTER_KINDS = <ElementKind>[
- ElementKind.FIELD,
- ElementKind.SETTER
- ];
-
Element _seed;
LibraryElement _library;
ClassElement _class;
@@ -127,12 +113,19 @@
var library = class_.library;
var name = seed.displayName;
List<ElementKind> kinds;
- if (seed is MethodElement) {
- kinds = METHOD_KINDS;
+ if (seed is FieldElement) {
+ kinds = [
+ ElementKind.GETTER,
+ if (!seed.isFinal) ElementKind.SETTER,
+ ];
+ } else if (seed is MethodElement) {
+ kinds = const [ElementKind.METHOD];
} else if (seed is PropertyAccessorElement) {
- kinds = seed.isGetter ? GETTER_KINDS : SETTER_KINDS;
+ kinds = seed.isGetter
+ ? const [ElementKind.GETTER]
+ : const [ElementKind.SETTER];
} else {
- kinds = FIELD_KINDS;
+ kinds = const [];
}
return _OverriddenElementsFinder._(seed, library, class_, name, kinds);
}
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index 04013bf..0e852c2 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.dart
@@ -42,7 +42,7 @@
var element = ElementLocator.locate(parent);
execElement = element is ExecutableElement ? element : null;
} else if (parent is InstanceCreationExpression) {
- name = parent.constructorName.type2.name.name;
+ name = parent.constructorName.type.name.name;
var constructorName = parent.constructorName.name;
if (constructorName != null) {
name += '.${constructorName.name}';
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 45ccc9b..9f3043e 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -68,7 +68,7 @@
/// automatically called when a client listens to the stream returned by
/// [results]. Subclasses should override this method, append at least one
/// result to the [controller], and close the controller stream once complete.
- Future<List<CompletionSuggestion>> computeSuggestions({
+ Future<List<CompletionSuggestionBuilder>> computeSuggestions({
required CompletionBudget budget,
required OperationPerformanceImpl performance,
required DartCompletionRequest request,
@@ -87,7 +87,7 @@
//
// Compute completions generated by server.
//
- var suggestions = <CompletionSuggestion>[];
+ var suggestions = <CompletionSuggestionBuilder>[];
await performance.runAsync('computeSuggestions', (performance) async {
var manager = DartCompletionManager(
budget: budget,
@@ -357,9 +357,9 @@
setNewRequest(completionRequest);
var notImportedSuggestions = NotImportedSuggestions();
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
try {
- suggestions = await computeSuggestions(
+ suggestionBuilders = await computeSuggestions(
budget: budget,
performance: performance,
request: completionRequest,
@@ -377,36 +377,29 @@
}
performance.run('filter', (performance) {
- performance.getDataInt('count').add(suggestions.length);
- suggestions = fuzzyFilterSort(
+ performance.getDataInt('count').add(suggestionBuilders.length);
+ suggestionBuilders = fuzzyFilterSort(
pattern: completionRequest.targetPrefix,
- suggestions: suggestions,
+ suggestions: suggestionBuilders,
);
- performance.getDataInt('matchCount').add(suggestions.length);
+ performance.getDataInt('matchCount').add(suggestionBuilders.length);
});
- var lengthRestricted = suggestions.take(params.maxResults).toList();
+ var lengthRestricted =
+ suggestionBuilders.take(params.maxResults).toList();
completionPerformance.suggestionCount = lengthRestricted.length;
- // Update `isNotImported` for not yet imported.
- for (var i = 0; i < lengthRestricted.length; i++) {
- var suggestion = lengthRestricted[i];
- if (notImportedSuggestions.set.contains(suggestion)) {
- lengthRestricted[i] = suggestion.copyWith(
- isNotImported: CopyWithValue(true),
- );
- }
- }
+ var suggestions = lengthRestricted.map((e) => e.build()).toList();
var isIncomplete = notImportedSuggestions.isIncomplete ||
- lengthRestricted.length < suggestions.length;
+ lengthRestricted.length < suggestionBuilders.length;
performance.run('sendResponse', (_) {
server.sendResponse(
CompletionGetSuggestions2Result(
completionRequest.replacementOffset,
completionRequest.replacementLength,
- lengthRestricted,
+ suggestions,
isIncomplete,
).toResponse(request.id),
);
@@ -569,9 +562,9 @@
// Compute suggestions in the background
try {
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
try {
- suggestions = await computeSuggestions(
+ suggestionBuilders = await computeSuggestions(
budget: budget,
performance: performance,
request: completionRequest,
@@ -603,7 +596,7 @@
completionId,
completionRequest.replacementOffset,
completionRequest.replacementLength,
- suggestions,
+ suggestionBuilders.map((e) => e.build()).toList(),
libraryFile,
includedSuggestionSets,
includedElementKinds?.toList(),
@@ -611,7 +604,7 @@
);
});
- completionPerformance.suggestionCount = suggestions.length;
+ completionPerformance.suggestionCount = suggestionBuilders.length;
} finally {
ifMatchesRequestClear(completionRequest);
}
@@ -694,7 +687,7 @@
Future<void> _addPluginSuggestions(
CompletionBudget budget,
_RequestToPlugins requestToPlugins,
- List<CompletionSuggestion> suggestions,
+ List<CompletionSuggestionBuilder> suggestionBuilders,
) async {
var responses = await waitForResponses(
requestToPlugins.futures,
@@ -712,7 +705,11 @@
' replacement offset/length: ${result.toJson()}');
continue;
}
- suggestions.addAll(result.results);
+ suggestionBuilders.addAll(
+ result.results.map(
+ (suggestion) => ValueCompletionSuggestionBuilder(suggestion),
+ ),
+ );
}
}
}
diff --git a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
index 4e42510..01507f9 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
@@ -18,10 +18,13 @@
ImplementedComputer(this.searchEngine, this.unitElement);
Future<void> compute() async {
- for (var element in unitElement.mixins) {
+ for (var element in unitElement.classes) {
await _computeForClassElement(element);
}
- for (var element in unitElement.classes) {
+ for (var element in unitElement.enums) {
+ await _computeForClassElement(element);
+ }
+ for (var element in unitElement.mixins) {
await _computeForClassElement(element);
}
}
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index 3c7bbac..bca2807 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -173,7 +173,7 @@
/// Computes the best URI to import [what] into the [unit] library.
String? _getRelativeFileUri(DartCompletionRequest request, Uri what) {
- if (what.scheme == 'file') {
+ if (what.isScheme('file')) {
var pathContext = request.analysisSession.resourceProvider.pathContext;
var libraryPath = request.libraryElement.source.fullName;
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index e0eedc4..4fc64eb 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -74,12 +74,13 @@
offset: targetOffset,
);
- var suggestions = await DartCompletionManager(
+ var serverSuggestions = await DartCompletionManager(
budget: CompletionBudget(CompletionBudget.defaultDuration),
).computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
);
+ var suggestions = serverSuggestions.map((e) => e.build()).toList();
// Remove completions with synthetic import prefixes.
suggestions.removeWhere((s) => s.completion.startsWith('__prefix'));
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 655d9d9..eeda336 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -95,15 +95,16 @@
}
}
- var workspace = DartChangeWorkspace(server.currentSessions);
- var processor = BulkFixProcessor(server.instrumentationService, workspace,
- useConfigFiles: params.inTestMode ?? false);
-
var collection = AnalysisContextCollectionImpl(
includedPaths: params.included,
resourceProvider: server.resourceProvider,
sdkPath: server.sdkPath,
);
+ var workspace = DartChangeWorkspace(
+ collection.contexts.map((c) => c.currentSession).toList());
+ var processor = BulkFixProcessor(server.instrumentationService, workspace,
+ useConfigFiles: params.inTestMode ?? false);
+
var changeBuilder = await processor.fixErrors(collection.contexts);
var response = EditBulkFixesResult(
@@ -355,7 +356,7 @@
getFixes(request);
return Response.DELAYED_RESPONSE;
} else if (requestName == EDIT_REQUEST_GET_REFACTORING) {
- return _getRefactoring(request);
+ return _getRefactoring(request, cancellationToken);
} else if (requestName == EDIT_REQUEST_IMPORT_ELEMENTS) {
importElements(request);
return Response.DELAYED_RESPONSE;
@@ -865,7 +866,8 @@
}
}
- Response _getRefactoring(Request request) {
+ Response _getRefactoring(
+ Request request, CancellationToken cancellationToken) {
final refactoringManager = this.refactoringManager;
if (refactoringManager == null) {
return Response.unsupportedFeature(request.id, 'Search is not enabled.');
@@ -874,7 +876,7 @@
refactoringManager.cancel();
_newRefactoringManager();
}
- refactoringManager.getRefactoring(request);
+ refactoringManager.getRefactoring(request, cancellationToken);
return Response.DELAYED_RESPONSE;
}
@@ -973,7 +975,7 @@
_reset();
}
- void getRefactoring(Request _request) {
+ void getRefactoring(Request _request, CancellationToken cancellationToken) {
// prepare for processing the request
request = _request;
final result = this.result = EditGetRefactoringResult(
@@ -990,7 +992,8 @@
?.sendEvent('refactor', params.kind.name.toLowerCase());
runZonedGuarded(() async {
- await _init(params.kind, file, params.offset, params.length);
+ await _init(
+ params.kind, file, params.offset, params.length, cancellationToken);
if (initStatus.hasFatalError) {
feedback = null;
_sendResultResponse();
@@ -1076,8 +1079,8 @@
}
}
- Future<void> _createRefactoringFromKind(
- String file, int offset, int length) async {
+ Future<void> _createRefactoringFromKind(String file, int offset, int length,
+ CancellationToken cancellationToken) async {
if (kind == RefactoringKind.CONVERT_GETTER_TO_METHOD) {
var resolvedUnit = await server.getResolvedUnit(file);
if (resolvedUnit != null) {
@@ -1144,11 +1147,9 @@
);
}
} else if (kind == RefactoringKind.MOVE_FILE) {
- var resolvedUnit = await server.getResolvedUnit(file);
- if (resolvedUnit != null) {
- refactoring = MoveFileRefactoring(
- server.resourceProvider, refactoringWorkspace, resolvedUnit, file);
- }
+ refactoring = MoveFileRefactoring(
+ server.resourceProvider, refactoringWorkspace, file)
+ ..cancellationToken = cancellationToken;
} else if (kind == RefactoringKind.RENAME) {
var resolvedUnit = await server.getResolvedUnit(file);
if (resolvedUnit != null) {
@@ -1171,8 +1172,8 @@
/// Initializes this context to perform a refactoring with the specified
/// parameters. The existing [Refactoring] is reused or created as needed.
- Future _init(
- RefactoringKind kind, String file, int offset, int length) async {
+ Future _init(RefactoringKind kind, String file, int offset, int length,
+ CancellationToken cancellationToken) async {
// check if we can continue with the existing Refactoring instance
if (this.kind == kind &&
this.file == file &&
@@ -1191,7 +1192,7 @@
throw 'A simulated refactoring exception - init.';
}
// create a new Refactoring instance
- await _createRefactoringFromKind(file, offset, length);
+ await _createRefactoringFromKind(file, offset, length, cancellationToken);
final refactoring = this.refactoring;
if (refactoring == null) {
initStatus = RefactoringStatus.fatal('Unable to create a refactoring');
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 83b987b..c7497dd 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -165,6 +165,18 @@
_fallback?.enableSdkFormatter ??
true;
+ /// Whether to include Snippets in code completion results.
+ bool get enableSnippets =>
+ // TODO(dantup): Change this setting to `enableSnippets`
+ // and default to `true`
+ // and remove `initializeWithSnippetSupportAndPreviewFlag` from tests
+ // once all snippets are implemented and VS Code has shipped a
+ // version that maps `enableServerSnippets` to `enableSnippets` in
+ // middleware to avoid dupes.
+ _settings['previewEnableSnippets'] as bool? ??
+ _fallback?.enableSnippets ??
+ false;
+
/// The line length used when formatting documents.
///
/// If null, the formatters default will be used.
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index a782782..55257c6 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -208,6 +208,8 @@
static const InvalidFileLineCol = ErrorCodes(-32004);
static const UnknownCommand = ErrorCodes(-32005);
static const InvalidCommandArguments = ErrorCodes(-32006);
+
+ /// A file that is not part of the analyzed set.
static const FileNotAnalyzed = ErrorCodes(-32007);
static const FileHasErrors = ErrorCodes(-32008);
static const ClientFailedToApplyEdit = ErrorCodes(-32009);
@@ -215,6 +217,9 @@
static const RefactorFailed = ErrorCodes(-32011);
static const FeatureDisabled = ErrorCodes(-32012);
+ /// A file that is expected to be analyzed, but failed.
+ static const FileAnalysisFailed = ErrorCodes(-32013);
+
/// An error raised when the server detects that the server and client are out
/// of sync and cannot recover. For example if a textDocument/didChange notification
/// has invalid offsets, suggesting the client and server have become out of sync
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
index 879ac92..ee853d6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
@@ -45,11 +45,6 @@
}
final lineInfo = unit.lineInfo;
- if (lineInfo == null) {
- return error(ErrorCodes.InternalError,
- 'Unable to produce edits for $docIdentifier as no LineInfo was found');
- }
-
final workspaceEdit = toWorkspaceEdit(
clientCapabilities,
[FileEditInformation(docIdentifier, lineInfo, edits)],
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 736ab90..f64f323 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -21,7 +21,9 @@
import 'package:analysis_server/src/services/completion/yaml/fix_data_generator.dart';
import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/services/available_declarations.dart';
@@ -178,6 +180,31 @@
String _createImportedSymbolKey(String name, Uri declaringUri) =>
'$name/$declaringUri';
+ Future<List<CompletionItem>> _getDartSnippetItems({
+ required LspClientCapabilities clientCapabilities,
+ required ResolvedUnitResult unit,
+ required int offset,
+ required LineInfo lineInfo,
+ }) async {
+ final request = DartSnippetRequest(
+ unit: unit,
+ offset: offset,
+ );
+ final snippetManager = DartSnippetManager();
+ final snippets = await snippetManager.computeSnippets(request);
+
+ return snippets
+ .map((snippet) => snippetToCompletionItem(
+ server,
+ clientCapabilities,
+ unit.path,
+ lineInfo,
+ toPosition(lineInfo.getLocation(offset)),
+ snippet,
+ ))
+ .toList();
+ }
+
Future<ErrorOr<CompletionList>> _getPluginResults(
LspClientCapabilities capabilities,
LineInfo lineInfo,
@@ -256,11 +283,15 @@
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
);
- final serverSuggestions = await contributor.computeSuggestions(
+ final serverSuggestions2 = await contributor.computeSuggestions(
completionRequest,
performance,
);
+ final serverSuggestions = serverSuggestions2.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
+
final insertLength = _computeInsertLength(
offset,
completionRequest.replacementOffset,
@@ -416,14 +447,33 @@
});
}
+ // Add in any snippets.
+ final snippetsEnabled =
+ server.clientConfiguration.forResource(unit.path).enableSnippets;
+ // We can only produce edits with edit builders for files inside
+ // the root, so skip snippets entirely if not.
+ final isEditableFile =
+ unit.session.analysisContext.contextRoot.isAnalyzed(unit.path);
+ if (capabilities.completionSnippets &&
+ snippetsEnabled &&
+ isEditableFile) {
+ results.addAll(await _getDartSnippetItems(
+ clientCapabilities: capabilities,
+ unit: unit,
+ offset: offset,
+ lineInfo: unit.lineInfo,
+ ));
+ }
+
// Perform fuzzy matching based on the identifier in front of the caret to
// reduce the size of the payload.
final fuzzyPattern = completionRequest.targetPrefix;
final fuzzyMatcher =
FuzzyMatcher(fuzzyPattern, matchStyle: MatchStyle.TEXT);
- final matchingResults =
- results.where((e) => fuzzyMatcher.score(e.label) > 0).toList();
+ final matchingResults = results
+ .where((e) => fuzzyMatcher.score(e.filterText ?? e.label) > 0)
+ .toList();
completionPerformance.suggestionCount = results.length;
@@ -431,6 +481,8 @@
CompletionList(isIncomplete: false, items: matchingResults));
} on AbortCompletion {
return success(CompletionList(isIncomplete: false, items: []));
+ } on InconsistentAnalysisException {
+ return success(CompletionList(isIncomplete: false, items: []));
}
},
);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index d2d2bec..fa99c2b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -132,11 +132,13 @@
// the file we're importing into, rather than the full URI.
final pathContext = server.resourceProvider.pathContext;
final autoImportDisplayUri = libraryUri.isScheme('file')
- ? pathContext.relative(
+ // Compute the relative path and then put into a URI so the display
+ // always uses forward slashes (as a URI) regardless of platform.
+ ? Uri.file(pathContext.relative(
libraryUri.toFilePath(),
from: pathContext.dirname(file),
- )
- : libraryUri.toString();
+ ))
+ : libraryUri;
return success(CompletionItem(
label: item.label,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index 827a088..36aff2e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -11,9 +11,15 @@
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget;
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
+import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
import 'package:collection/collection.dart';
@@ -47,14 +53,16 @@
Future<AnalysisNavigationParams> getServerResult(
bool supportsLocationLink, String path, int offset) async {
- final collector =
- NavigationCollectorImpl(collectCodeLocations: supportsLocationLink);
+ final collector = NavigationCollectorImpl();
final result = await server.getResolvedUnit(path);
final unit = result?.unit;
if (unit != null) {
computeDartNavigation(
server.resourceProvider, collector, unit, offset, 0);
+ if (supportsLocationLink) {
+ _updateTargetsWithCodeLocations(collector);
+ }
collector.createRegions();
}
@@ -171,6 +179,50 @@
return otherResults.isNotEmpty ? otherResults : results;
}
+ /// Get the location of the code (excluding leading doc comments) for this element.
+ protocol.Location? _getCodeLocation(Element element) {
+ var codeElement = element;
+ // For synthetic getters created for fields, we need to access the associated
+ // variable to get the codeOffset/codeLength.
+ if (codeElement.isSynthetic && codeElement is PropertyAccessorElementImpl) {
+ final variable = codeElement.variable;
+ if (variable is ElementImpl) {
+ codeElement = variable as ElementImpl;
+ }
+ }
+
+ // Read the main codeOffset from the element. This may include doc comments
+ // but will give the correct end position.
+ int? codeOffset, codeLength;
+ if (codeElement is ElementImpl) {
+ codeOffset = codeElement.codeOffset;
+ codeLength = codeElement.codeLength;
+ }
+
+ if (codeOffset == null || codeLength == null) {
+ return null;
+ }
+
+ // Read the declaration so we can get the offset after the doc comments.
+ // TODO(dantup): Skip this for parts (getParsedLibrary will throw), but find
+ // a better solution.
+ final declaration = _parsedDeclaration(codeElement);
+ var node = declaration?.node;
+ if (node is VariableDeclaration) {
+ node = node.parent;
+ }
+ if (node is AnnotatedNode) {
+ var offsetAfterDocs = node.firstTokenAfterCommentAndMetadata.offset;
+
+ // Reduce the length by the difference between the end of docs and the start.
+ codeLength -= offsetAfterDocs - codeOffset;
+ codeOffset = offsetAfterDocs;
+ }
+
+ return AnalyzerConverter()
+ .locationFromElement(element, offset: codeOffset, length: codeLength);
+ }
+
Location? _toLocation(
AnalysisNavigationParams mergedResults, NavigationTarget target) {
final targetFilePath = mergedResults.files[target.fileIndex];
@@ -191,4 +243,34 @@
region, sourceLineInfo, targetFilePath, target, targetLineInfo)
: null;
}
+
+ void _updateTargetsWithCodeLocations(NavigationCollectorImpl collector) {
+ for (var targetToUpdate in collector.targetsToUpdate) {
+ var codeLocation = _getCodeLocation(targetToUpdate.element);
+ if (codeLocation != null) {
+ targetToUpdate.target
+ ..codeOffset = codeLocation.offset
+ ..codeLength = codeLocation.length;
+ }
+ }
+ }
+
+ static ElementDeclarationResult? _parsedDeclaration(Element element) {
+ var session = element.session;
+ if (session == null) {
+ return null;
+ }
+
+ var libraryPath = element.library?.source.fullName;
+ if (libraryPath == null) {
+ return null;
+ }
+
+ var parsedLibrary = session.getParsedLibrary(libraryPath);
+ if (parsedLibrary is! ParsedLibraryResult) {
+ return null;
+ }
+
+ return parsedLibrary.getElementDeclaration(element);
+ }
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 81b9b85..84da8f2 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -23,7 +23,8 @@
ErrorOr<List<TextEdit>?> formatFile(String path) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ return error(
+ ServerErrorCodes.InvalidFilePath, 'File does not exist', path);
}
final result = server.getParsedUnit(path);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
index a6bbf90..f28ef15 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
@@ -23,7 +23,8 @@
ErrorOr<List<TextEdit>?> formatRange(String path, Range range) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ return error(
+ ServerErrorCodes.InvalidFilePath, 'File does not exist', path);
}
final result = server.getParsedUnit(path);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index be75ccb..6ff4313 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -23,7 +23,8 @@
ErrorOr<List<TextEdit>?> formatFile(String path) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ return error(
+ ServerErrorCodes.InvalidFilePath, 'File does not exist', path);
}
final result = server.getParsedUnit(path);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
index d08152f..6cbcd6c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
@@ -23,7 +23,10 @@
Future<ErrorOr<WorkspaceEdit?>> handle(
RenameFilesParams params, CancellationToken token) async {
final files = params.files;
- // For performance reasons, only single-file rename/moves are currently supported.
+ // Only single-file rename/moves are currently supported.
+ // TODO(dantup): Tweak this when VS Code can correctly pass us cancellation
+ // requests to not check for .dart to also support folders (although we
+ // may still only support a single entry initially).
if (files.length > 1 || files.any((f) => !f.oldUri.endsWith('.dart'))) {
return success(null);
}
@@ -31,20 +34,17 @@
final file = files.single;
final oldPath = pathOfUri(Uri.tryParse(file.oldUri));
final newPath = pathOfUri(Uri.tryParse(file.newUri));
+
return oldPath.mapResult((oldPath) =>
- newPath.mapResult((newPath) => _renameFile(oldPath, newPath)));
+ newPath.mapResult((newPath) => _renameFile(oldPath, newPath, token)));
}
Future<ErrorOr<WorkspaceEdit?>> _renameFile(
- String oldPath, String newPath) async {
- final resolvedUnit = await server.getResolvedUnit(oldPath);
- if (resolvedUnit == null) {
- return success(null);
- }
-
- final refactoring = MoveFileRefactoring(server.resourceProvider,
- server.refactoringWorkspace, resolvedUnit, oldPath)
- ..newFile = newPath;
+ String oldPath, String newPath, CancellationToken token) async {
+ final refactoring = MoveFileRefactoring(
+ server.resourceProvider, server.refactoringWorkspace, oldPath)
+ ..newFile = newPath
+ ..cancellationToken = token;
// If we're unable to update imports for a rename, we should silently do
// nothing rather than interrupt the users file rename with an error.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index e0f497c..ddd82dc 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -56,7 +56,8 @@
final lineInfo = server.getLineInfo(path);
if (lineInfo == null) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ return error(ServerErrorCodes.InvalidFilePath,
+ 'Unable to obtain line information for file', path);
} else {
return success(lineInfo);
}
@@ -65,7 +66,19 @@
Future<ErrorOr<ResolvedUnitResult>> requireResolvedUnit(String path) async {
final result = await server.getResolvedUnit(path);
if (result == null) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ if (server.isAnalyzed(path)) {
+ // If the file was being analyzed and we got a null result, that usually
+ // indicators a parser or analysis failure, so provide a more specific
+ // message.
+ return error(ServerErrorCodes.FileAnalysisFailed,
+ 'Analysis failed for file', path);
+ } else {
+ return error(ServerErrorCodes.FileNotAnalyzed,
+ 'File is not being analyzed', path);
+ }
+ } else if (!result.exists) {
+ return error(
+ ServerErrorCodes.InvalidFilePath, 'File does not exist', path);
}
return success(result);
}
@@ -73,7 +86,16 @@
ErrorOr<ParsedUnitResult> requireUnresolvedUnit(String path) {
final result = server.getParsedUnit(path);
if (result == null) {
- return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
+ if (server.isAnalyzed(path)) {
+ // If the file was being analyzed and we got a null result, that usually
+ // indicators a parser or analysis failure, so provide a more specific
+ // message.
+ return error(ServerErrorCodes.FileAnalysisFailed,
+ 'Analysis failed for file', path);
+ } else {
+ return error(ServerErrorCodes.FileNotAnalyzed,
+ 'File is not being analyzed', path);
+ }
}
return success(result);
}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index c182eee..9026e05 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:io';
import 'dart:math';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
@@ -17,9 +18,11 @@
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/dartdoc.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp;
+import 'package:analysis_server/src/lsp/snippets.dart';
import 'package:analysis_server/src/lsp/source_edits.dart';
import 'package:analysis_server/src/protocol_server.dart' as server
hide AnalysisError;
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
import 'package:analyzer/dart/analysis/results.dart' as server;
import 'package:analyzer/error/error.dart' as server;
import 'package:analyzer/source/line_info.dart' as server;
@@ -67,50 +70,6 @@
_asMarkup(preferredFormats, content));
}
-/// Builds an LSP snippet string with supplied ranges as tabstops.
-String buildSnippetStringWithTabStops(
- String? text,
- List<int>? offsetLengthPairs,
-) {
- text ??= '';
- offsetLengthPairs ??= const [];
-
- // Snippets syntax is documented in the LSP spec:
- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
- //
- // $1, $2, etc. are used for tab stops and ${1:foo} inserts a placeholder of foo.
-
- final output = [];
- var offset = 0;
-
- // When there's only a single tabstop, it should be ${0} as this is treated
- // specially as the final cursor position (if we use 1, the editor will insert
- // a 0 at the end of the string which is not what we expect).
- // When there are multiple, start with ${1} since these are placeholders the
- // user can tab through and the editor-inserted ${0} at the end is expected.
- var tabStopNumber = offsetLengthPairs.length <= 2 ? 0 : 1;
-
- for (var i = 0; i < offsetLengthPairs.length; i += 2) {
- final pairOffset = offsetLengthPairs[i];
- final pairLength = offsetLengthPairs[i + 1];
-
- // Add any text that came before this tabstop to the result.
- output.add(escapeSnippetString(text.substring(offset, pairOffset)));
-
- // Add this tabstop
- final tabStopText = escapeSnippetString(
- text.substring(pairOffset, pairOffset + pairLength));
- output.add('\${${tabStopNumber++}:$tabStopText}');
-
- offset = pairOffset + pairLength;
- }
-
- // Add any remaining text that was after the last tabstop.
- output.add(escapeSnippetString(text.substring(offset)));
-
- return output.join('');
-}
-
/// Creates a [lsp.WorkspaceEdit] from simple [server.SourceFileEdit]s.
///
/// Note: This code will fetch the version of each document being modified so
@@ -572,15 +531,6 @@
.firstWhere(isSupported, orElse: () => lsp.SymbolKind.Obj);
}
-/// Escapes a string to be used in an LSP edit that uses Snippet mode.
-///
-/// Snippets can contain special markup like `${a:b}` so some characters need
-/// escaping (according to the LSP spec, those are `$`, `}` and `\`).
-String escapeSnippetString(String input) => input.replaceAllMapped(
- RegExp(r'[$}\\]'), // Replace any of $ } \
- (c) => '\\${c[0]}', // Prefix with a backslash
- );
-
String? getCompletionDetail(
server.CompletionSuggestion suggestion,
lsp.CompletionItemKind? completionKind,
@@ -798,7 +748,18 @@
));
}
try {
- return ErrorOr<String>.success(uri.toFilePath());
+ final filePath = uri.toFilePath();
+ // On Windows, paths that start with \ and not a drive letter are not
+ // supported but will return `true` from `path.isAbsolute` so check for them
+ // specifically.
+ if (Platform.isWindows && filePath.startsWith(r'\')) {
+ return ErrorOr<String>.error(ResponseError(
+ code: lsp.ServerErrorCodes.InvalidFilePath,
+ message: 'URI was not an absolute file path (missing drive letter)',
+ data: uri.toString(),
+ ));
+ }
+ return ErrorOr<String>.success(filePath);
} catch (e) {
// Even if tryParse() works and file == scheme, toFilePath() can throw on
// Windows if there are invalid characters.
@@ -810,7 +771,7 @@
}
lsp.Diagnostic pluginToDiagnostic(
- server.LineInfo Function(String) getLineInfo,
+ server.LineInfo? Function(String) getLineInfo,
plugin.AnalysisError error, {
required Set<lsp.DiagnosticTag>? supportedTags,
required bool clientSupportsCodeDescription,
@@ -832,7 +793,14 @@
final range = locationToRange(error.location) ??
locationOffsetLenToRange(
- getLineInfo(error.location.file), error.location);
+ // TODO(dantup): This null assertion is not sound and can lead to
+ // errors (for example during a large rename where files may be
+ // removed as diagnostics are being mapped). To remove this,
+ // error.location should be updated to require line/col information
+ // (which involves breaking changes).
+ getLineInfo(error.location.file)!,
+ error.location,
+ );
var documentationUrl = error.url;
return lsp.Diagnostic(
range: range,
@@ -923,6 +891,126 @@
);
}
+/// Creates a SnippetTextEdit for a set of edits using Linked Edit Groups.
+///
+/// Edit groups offsets are based on the entire content being modified after all
+/// edits, so [editOffset] must to take into account both the offset of the edit
+/// _and_ any delta from edits prior to this one in the file.
+///
+/// [selectionOffset] is also absolute and assumes [edit.replacement] will be
+/// inserted at [editOffset].
+lsp.SnippetTextEdit snippetTextEditFromEditGroups(
+ String filePath,
+ server.LineInfo lineInfo,
+ server.SourceEdit edit, {
+ required List<server.LinkedEditGroup> editGroups,
+ required int editOffset,
+ required int? selectionOffset,
+}) {
+ return lsp.SnippetTextEdit(
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
+ range: toRange(lineInfo, edit.offset, edit.length),
+ newText: buildSnippetStringForEditGroups(
+ edit.replacement,
+ filePath: filePath,
+ editGroups: editGroups,
+ editOffset: editOffset,
+ selectionOffset: selectionOffset,
+ ),
+ );
+}
+
+/// Creates a SnippetTextEdit for an edit with a selection placeholder.
+///
+/// [selectionOffset] is relative to (and therefore must be within) the edit.
+lsp.SnippetTextEdit snippetTextEditWithSelection(
+ server.LineInfo lineInfo,
+ server.SourceEdit edit, {
+ required int selectionOffsetRelative,
+ int? selectionLength,
+}) {
+ return lsp.SnippetTextEdit(
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
+ range: toRange(lineInfo, edit.offset, edit.length),
+ newText: buildSnippetStringWithTabStops(
+ edit.replacement,
+ [selectionOffsetRelative, selectionLength ?? 0],
+ ),
+ );
+}
+
+lsp.CompletionItem snippetToCompletionItem(
+ lsp.LspAnalysisServer server,
+ LspClientCapabilities capabilities,
+ String file,
+ LineInfo lineInfo,
+ Position position,
+ Snippet snippet,
+) {
+ assert(capabilities.completionSnippets);
+
+ final formats = capabilities.completionDocumentationFormats;
+ final documentation = snippet.documentation;
+ final supportsAsIsInsertMode =
+ capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);
+ final changes = snippet.change;
+
+ // We must only get one change for this file to be able to apply snippets.
+ final thisFilesChange = changes.edits.singleWhere((e) => e.file == file);
+ final otherFilesChanges = changes.edits.where((e) => e.file != file).toList();
+
+ // If this completion involves editing other files, we'll need to build
+ // a command that the client will call to apply those edits later, because
+ // LSP Completions can only provide simple edits for the current file.
+ Command? command;
+ if (otherFilesChanges.isNotEmpty) {
+ final workspaceEdit = createPlainWorkspaceEdit(server, otherFilesChanges);
+ command = Command(
+ title: 'Add import',
+ command: Commands.sendWorkspaceEdit,
+ arguments: [workspaceEdit]);
+ }
+
+ /// Convert the changes to TextEdits using snippet tokens for linked edit
+ /// groups.
+ final mainFileEdits = toSnippetTextEdits(
+ file,
+ thisFilesChange,
+ changes.linkedEditGroups,
+ lineInfo,
+ selectionOffset:
+ changes.selection?.file == file ? changes.selection?.offset : null,
+ );
+
+ // For LSP, we need to provide the main edit and other edits separately. The
+ // main edit must include the location that completion was invoked. If we find
+ // more than one, take the first one since imports are usually added as later
+ // edits (so when applied sequentially they will be inserted at the start of
+ // the file after the other edits).
+ final mainEdit = mainFileEdits
+ .firstWhere((edit) => edit.range.start.line == position.line);
+ final nonMainEdits = mainFileEdits.where((edit) => edit != mainEdit).toList();
+
+ return lsp.CompletionItem(
+ label: snippet.label,
+ filterText: snippet.prefix,
+ kind: lsp.CompletionItemKind.Snippet,
+ command: command,
+ documentation: documentation != null
+ ? asStringOrMarkupContent(formats, documentation)
+ : null,
+ // Force snippets to be sorted at the bottom of the list.
+ // TODO(dantup): Consider if we can rank these better. Client-side
+ // snippets have always been forced to the bottom partly because they
+ // show up in more places than wanted.
+ sortText: 'zzz${snippet.prefix}',
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
+ insertTextMode: supportsAsIsInsertMode ? InsertTextMode.asIs : null,
+ textEdit: Either2<TextEdit, InsertReplaceEdit>.t1(mainEdit),
+ additionalTextEdits: nonMainEdits,
+ );
+}
+
lsp.CompletionItemKind? suggestionKindToCompletionItemKind(
Set<lsp.CompletionItemKind> supportedCompletionKinds,
server.CompletionSuggestionKind kind,
@@ -1386,18 +1474,38 @@
);
}
-lsp.SnippetTextEdit toSnippetTextEdit(
- LspClientCapabilities capabilities,
- server.LineInfo lineInfo,
- server.SourceEdit edit,
- int selectionOffsetRelative,
- int? selectionLength) {
- return lsp.SnippetTextEdit(
- insertTextFormat: lsp.InsertTextFormat.Snippet,
- range: toRange(lineInfo, edit.offset, edit.length),
- newText: buildSnippetStringWithTabStops(
- edit.replacement, [selectionOffsetRelative, selectionLength ?? 0]),
- );
+List<lsp.SnippetTextEdit> toSnippetTextEdits(
+ String filePath,
+ server.SourceFileEdit change,
+ List<server.LinkedEditGroup> editGroups,
+ LineInfo lineInfo, {
+ required int? selectionOffset,
+}) {
+ final snippetEdits = <lsp.SnippetTextEdit>[];
+
+ // Edit groups offsets are based on the document after the edits are applied.
+ // This means we must compute an offset delta for each edit that takes into
+ // account all edits that might be made before it in the document (which are
+ // after it in the edits). To do this, reverse the list when computing the
+ // offsets, but reverse them back to the original list order when returning so
+ // that we do not apply them incorrectly in tests (where we will apply them
+ // in-sequence).
+
+ var offsetDelta = 0;
+ for (final edit in change.edits.reversed) {
+ snippetEdits.add(snippetTextEditFromEditGroups(
+ filePath,
+ lineInfo,
+ edit,
+ editGroups: editGroups,
+ editOffset: edit.offset + offsetDelta,
+ selectionOffset: selectionOffset,
+ ));
+
+ offsetDelta += edit.replacement.length - edit.length;
+ }
+
+ return snippetEdits.reversed.toList();
}
ErrorOr<server.SourceRange> toSourceRange(
@@ -1448,8 +1556,9 @@
toTextEdit(lineInfo, edit));
}
return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t1(
- toSnippetTextEdit(capabilities, lineInfo, edit, selectionOffsetRelative,
- selectionLength));
+ snippetTextEditWithSelection(lineInfo, edit,
+ selectionOffsetRelative: selectionOffsetRelative,
+ selectionLength: selectionLength));
}
lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
@@ -1561,21 +1670,20 @@
insertTextFormat = lsp.InsertTextFormat.Snippet;
final hasRequiredParameters =
(defaultArgumentListTextRanges?.length ?? 0) > 0;
- final functionCallSuffix = hasRequiredParameters
- ? buildSnippetStringWithTabStops(
- defaultArgumentListString,
- defaultArgumentListTextRanges,
- )
- : '\${0:}'; // No required params still gets a tabstop in the parens.
- insertText = '${escapeSnippetString(insertText)}($functionCallSuffix)';
+ final functionCallSuffix =
+ hasRequiredParameters && defaultArgumentListString != null
+ ? buildSnippetStringWithTabStops(
+ defaultArgumentListString, defaultArgumentListTextRanges)
+ // No required params still gets a final tab stop in the parens.
+ : SnippetBuilder.finalTabStop;
+ insertText =
+ '${SnippetBuilder.escapeSnippetPlainText(insertText)}($functionCallSuffix)';
} else if (selectionOffset != 0 &&
- // We don't need a tabstop if the selection is the end of the string.
+ // We don't need a tab stop if the selection is the end of the string.
selectionOffset != completion.length) {
insertTextFormat = lsp.InsertTextFormat.Snippet;
insertText = buildSnippetStringWithTabStops(
- completion,
- [selectionOffset, selectionLength],
- );
+ completion, [selectionOffset, selectionLength]);
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/notification_manager.dart b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
index 8f38df1..bae8def 100644
--- a/pkg/analysis_server/lib/src/lsp/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
@@ -30,9 +30,7 @@
String filePath, List<protocol.AnalysisError> errors) {
final diagnostics = errors
.map((error) => pluginToDiagnostic(
- // We should never return errors for a file we can't get a
- // LineInfo for
- (path) => server.getLineInfo(path)!,
+ (path) => server.getLineInfo(path),
error,
supportedTags: server.clientCapabilities?.diagnosticTags,
clientSupportsCodeDescription:
diff --git a/pkg/analysis_server/lib/src/lsp/snippets.dart b/pkg/analysis_server/lib/src/lsp/snippets.dart
new file mode 100644
index 0000000..e88dcaa
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/snippets.dart
@@ -0,0 +1,322 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math' as math;
+
+import 'package:analysis_server/src/protocol_server.dart' as server
+ hide AnalysisError;
+import 'package:collection/collection.dart';
+
+/// Builds an LSP snippet string using the supplied edit groups.
+///
+/// [editGroups] are provided as absolute positions, where the edit will be
+/// made starting at [editOffset].
+///
+/// [selectionOffset] is also absolute and assumes [text] will be
+/// inserted at [editOffset].
+String buildSnippetStringForEditGroups(
+ String text, {
+ required String filePath,
+ required List<server.LinkedEditGroup> editGroups,
+ required int editOffset,
+ int? selectionOffset,
+}) =>
+ _buildSnippetString(
+ text,
+ filePath: filePath,
+ editGroups: editGroups,
+ editGroupsOffset: editOffset,
+ selectionOffset:
+ selectionOffset != null ? selectionOffset - editOffset : null,
+ );
+
+/// Builds an LSP snippet string with supplied ranges as tab stops.
+///
+/// [tabStopOffsetLengthPairs] are relative to the supplied text.
+String buildSnippetStringWithTabStops(
+ String text,
+ List<int>? tabStopOffsetLengthPairs,
+) =>
+ _buildSnippetString(
+ text,
+ filePath: null,
+ tabStopOffsetLengthPairs: tabStopOffsetLengthPairs,
+ );
+
+/// Builds an LSP snippet string with supplied ranges as tab stops.
+///
+/// [tabStopOffsetLengthPairs] are relative to the supplied text.
+///
+/// [selectionOffset]/[selectionLength] form a tab stop that is always "number 0"
+/// which is the final tab stop.
+///
+/// [editGroups] are provided as absolute positions, where [text] is known to
+/// start at [editGroupsOffset] in the final document.
+String _buildSnippetString(
+ String text, {
+ required String? filePath,
+ List<int>? tabStopOffsetLengthPairs,
+ int? selectionOffset,
+ int? selectionLength,
+ List<server.LinkedEditGroup>? editGroups,
+ int editGroupsOffset = 0,
+}) {
+ tabStopOffsetLengthPairs ??= const [];
+ editGroups ??= const [];
+ assert(tabStopOffsetLengthPairs.length % 2 == 0);
+
+ /// Helper to create a [SnippetPlaceholder] for each position in a linked
+ /// edit group.
+ Iterable<SnippetPlaceholder> convertEditGroup(
+ int index,
+ server.LinkedEditGroup editGroup,
+ ) {
+ final validPositions = editGroup.positions.where((p) => p.file == filePath);
+ // Create a placeholder for each position in the group.
+ return validPositions.map(
+ (position) => SnippetPlaceholder(
+ // Make the position relative to the supplied text.
+ position.offset - editGroupsOffset,
+ editGroup.length,
+ suggestions: editGroup.suggestions
+ .map((suggestion) => suggestion.value)
+ .toList(),
+ // Use the index as an ID to keep all related positions together (so
+ // the remain "linked").
+ linkedGroupId: index,
+ ),
+ );
+ }
+
+ // Convert selection/tab stops/edit groups all into the same format
+ // (`_SnippetPlaceholder`) so they can be handled in a single pass through
+ // the text.
+ final placeholders = [
+ // Selection.
+ if (selectionOffset != null)
+ SnippetPlaceholder(selectionOffset, selectionLength ?? 0, isFinal: true),
+
+ // Tab stops.
+ for (var i = 0; i < tabStopOffsetLengthPairs.length - 1; i += 2)
+ SnippetPlaceholder(
+ tabStopOffsetLengthPairs[i],
+ tabStopOffsetLengthPairs[i + 1],
+ // If there's only a single tab stop (and no selection/editGroups), mark
+ // it as the final stop so it exit "snippet mode" when tabbed to.
+ isFinal: selectionOffset == null &&
+ editGroups.isEmpty &&
+ tabStopOffsetLengthPairs.length == 2,
+ ),
+
+ // Linked edit groups.
+ ...editGroups.expandIndexed(convertEditGroup),
+ ];
+
+ // Remove any groups outside of the range (it's possible the edit groups apply
+ // to a different edit in the collection).
+ placeholders.removeWhere((placeholder) =>
+ placeholder.offset < 0 ||
+ placeholder.offset + placeholder.length > text.length);
+
+ final builder = SnippetBuilder()..appendPlaceholders(text, placeholders);
+ return builder.value;
+}
+
+/// A helper for building for snippets using LSP/TextMate syntax.
+///
+/// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
+///
+/// - $1, $2, etc. are used for tab stops
+/// - ${1:foo} inserts a placeholder of foo
+/// - ${1|foo,bar|} inserts a placeholder of foo with a selection list
+/// containing "foo" and "bar"
+class SnippetBuilder {
+ /// The constant `$0` used do indicate a final tab stop in the snippet syntax.
+ static const finalTabStop = r'$0';
+
+ final _buffer = StringBuffer();
+
+ var _nextPlaceholder = 1;
+
+ /// The built snippet text using the LSP snippet syntax.
+ String get value => _buffer.toString();
+
+ /// Appends a placeholder with a set of choices to choose from.
+ ///
+ /// If there are 0 or 1 choices, a placeholder will be inserted instead.
+ ///
+ /// Returns the placeholder number used.
+ int appendChoice(Iterable<String> choices, {int? placeholderNumber}) {
+ final uniqueChoices = choices.where((item) => item.isNotEmpty).toSet();
+
+ // If there's only 0/1 items, we can downgrade this to a placeholder.
+ if (uniqueChoices.length <= 1) {
+ return appendPlaceholder(
+ uniqueChoices.firstOrNull ?? '',
+ placeholderNumber: placeholderNumber,
+ );
+ }
+
+ placeholderNumber = _usePlaceholerNumber(placeholderNumber);
+
+ final escapedChoices = uniqueChoices.map(escapeSnippetChoiceText).join(',');
+ _buffer.write('\${$placeholderNumber|$escapedChoices|}');
+
+ return placeholderNumber;
+ }
+
+ /// Appends a placeholder with the given text.
+ ///
+ /// If the text is empty, inserts a tab stop instead.
+ ///
+ /// Returns the placeholder number used.
+ int appendPlaceholder(String text, {int? placeholderNumber}) {
+ // If there's no text, we can downgrade this to a tab stop.
+ if (text.isEmpty) {
+ return appendTabStop(placeholderNumber: placeholderNumber);
+ }
+
+ placeholderNumber = _usePlaceholerNumber(placeholderNumber);
+
+ final escapedText = escapeSnippetVariableText(text);
+ _buffer.write('\${$placeholderNumber:$escapedText}');
+
+ return placeholderNumber;
+ }
+
+ /// Appends a tab stop.
+ ///
+ /// Returns the placeholder number used.
+ int appendTabStop({int? placeholderNumber}) {
+ placeholderNumber = _usePlaceholerNumber(placeholderNumber);
+
+ _buffer.write('\$$placeholderNumber');
+
+ return placeholderNumber;
+ }
+
+ /// Appends normal text (escaping it as required).
+ void appendText(String text) {
+ _buffer.write(escapeSnippetPlainText(text));
+ }
+
+ /// Generates the current and next placeholder numbers.
+ int _usePlaceholerNumber(int? placeholderNumber) {
+ // If a number was not supplied, use thenext available one.
+ placeholderNumber ??= _nextPlaceholder;
+ // If the number we used was the highest seen, set the next one after it.
+ _nextPlaceholder = math.max(_nextPlaceholder, placeholderNumber + 1);
+
+ return placeholderNumber;
+ }
+
+ /// Escapes a string use inside a "choice" in a snippet.
+ ///
+ /// Similar to [escapeSnippetPlainText], but choices are delimited/separated
+ /// by pipes and commas (`${1:|a,b,c|}`).
+ static String escapeSnippetChoiceText(String input) => _escapeCharacters(
+ input,
+ RegExp(r'[$}\\\|,]'), // Replace any of $ } \ | ,
+ );
+
+ /// Escapes a string to be used in an LSP edit that uses Snippet mode where the
+ /// text is outside of a snippet token.
+ ///
+ /// Snippets can contain special markup like `${a:b}` so `$` needs escaping
+ /// as does `\` so it's not interpreted as an escape.
+ static String escapeSnippetPlainText(String input) => _escapeCharacters(
+ input,
+ RegExp(r'[$\\]'), // Replace any of $ \
+ );
+
+ /// Escapes a string to be used inside a snippet token.
+ ///
+ /// Similar to [escapeSnippetPlainText] but additionally escapes `}` so that the
+ /// token is not ended early if the included text contains braces.
+ static String escapeSnippetVariableText(String input) => _escapeCharacters(
+ input,
+ RegExp(r'[$}\\]'), // Replace any of $ } \
+ );
+
+ /// Escapes [pattern] in [input] with backslashes.
+ static String _escapeCharacters(String input, Pattern pattern) =>
+ input.replaceAllMapped(pattern, (c) => '\\${c[0]}');
+}
+
+/// Information about an individual placeholder/tab stop in a piece of code.
+///
+/// Each placeholder represents a single position into the code, so a linked
+/// edit group with 2 positions will be represented as two instances of this
+/// class (with the same [linkedGroupId]).
+class SnippetPlaceholder {
+ final int offset;
+ final int length;
+ final List<String>? suggestions;
+ final int? linkedGroupId;
+ final bool isFinal;
+
+ SnippetPlaceholder(
+ this.offset,
+ this.length, {
+ this.suggestions,
+ this.linkedGroupId,
+ this.isFinal = false,
+ });
+}
+
+/// Helpers for [SnippetBuilder] that do not relate to building the main snippet
+/// syntax (for example, converting from intermediate structures).
+extension SnippetBuilderExtensions on SnippetBuilder {
+ void appendPlaceholders(String text, List<SnippetPlaceholder> placeholders) {
+ // Ensure placeholders are in the order they're visible in the source so
+ // tabbing through them doesn't appear to jump around.
+ placeholders.sortBy<num>((placeholder) => placeholder.offset);
+
+ // We need to use the same placeholder number for all placeholders in the
+ // same linked group, so the first time we see a linked item, store its
+ // placeholder number here, so subsequent placeholders for the same linked
+ // group can reuse it.
+ final placeholderIdForLinkedGroupId = <int, int>{};
+
+ var offset = 0;
+ for (final placeholder in placeholders) {
+ // Add any text that came before this placeholder to the result.
+ appendText(text.substring(offset, placeholder.offset));
+
+ final linkedGroupId = placeholder.linkedGroupId;
+ int? thisPaceholderNumber;
+ // Override the placeholder number if it's the final one (0) or needs to
+ // re-use an existing one for a linked group.
+ if (placeholder.isFinal) {
+ thisPaceholderNumber = 0;
+ } else if (linkedGroupId != null) {
+ thisPaceholderNumber = placeholderIdForLinkedGroupId[linkedGroupId];
+ }
+
+ // Append the placeholder/choices.
+ final placeholderText = text.substring(
+ placeholder.offset,
+ placeholder.offset + placeholder.length,
+ );
+ // appendChoice handles mapping empty/single suggestions to a normal
+ // placeholder.
+ thisPaceholderNumber = appendChoice(
+ [placeholderText, ...?placeholder.suggestions],
+ placeholderNumber: thisPaceholderNumber,
+ );
+
+ // Track where we're up to.
+ offset = placeholder.offset + placeholder.length;
+
+ // Store the placeholder number used for linked groups so it can be reused
+ // by subsequent references to it.
+ if (linkedGroupId != null) {
+ placeholderIdForLinkedGroupId[linkedGroupId] = thisPaceholderNumber;
+ }
+ }
+
+ // Add any remaining text that was after the last placeholder.
+ appendText(text.substring(offset));
+ }
+}
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 64be4e9..9b829c7 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -242,7 +242,8 @@
if (kind == engine.MatchKind.WRITE) {
return SearchResultKind.WRITE;
}
- if (kind == engine.MatchKind.INVOCATION) {
+ if (kind == engine.MatchKind.INVOCATION ||
+ kind == engine.MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS) {
return SearchResultKind.INVOCATION;
}
if (kind == engine.MatchKind.REFERENCE ||
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 47504a4..ba94d24 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -32,8 +32,8 @@
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/util/sdk.dart';
import 'package:args/args.dart';
-import 'package:cli_util/cli_util.dart';
import 'package:linter/src/rules.dart' as linter;
import 'package:telemetry/crash_reporting.dart';
import 'package:telemetry/telemetry.dart' as telemetry;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 8cdcb87..2fee0c2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
@@ -42,7 +43,7 @@
void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
{bool appendComma = false, int? replacementLength}) {
- var appendColon = !_isInNamedExpression();
+ var appendColon = !_isEditingNamedArgLabel();
var namedArgs = _namedArgs();
for (var parameter in parameters) {
if (parameter.isNamed) {
@@ -73,7 +74,9 @@
// If there's a replacement length and the preference is to replace,
// we should not include colons/commas.
appendColon: appendColon && !willReplace,
- appendComma: appendComma && !willReplace,
+ // Commas should always be suppressed when we're not inserting colons:
+ // ke^: Key()
+ appendComma: appendComma && appendColon && !willReplace,
replacementLength: replacementLength);
}
}
@@ -197,6 +200,11 @@
bool _isEditingNamedArgLabel() {
if (argumentList != null) {
var entity = request.target.entity;
+ if (entity is SimpleIdentifier &&
+ entity.isSynthetic &&
+ entity.token.next?.type == TokenType.COLON) {
+ return true;
+ }
if (entity is NamedExpression) {
var offset = request.offset;
if (entity.offset < offset && offset < entity.end) {
@@ -215,16 +223,6 @@
return newExpr != null && flutter.isWidgetCreation(newExpr);
}
- /// Return `true` if the [request] is inside of a [NamedExpression] name.
- bool _isInNamedExpression() {
- var entity = request.target.entity;
- if (entity is NamedExpression) {
- var name = entity.name;
- return name.offset < request.offset && request.offset < name.end;
- }
- return false;
- }
-
/// Return `true` if the completion target is in the middle or beginning of
/// the list of named arguments and is not preceded by a comma. This method
/// assumes that [_isAppendingToArgList] has been called and returned `false`.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index b2ef7d6d..4fbeca3 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/services/completion/dart/closure_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/combinator_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/documentation_cache.dart';
+import 'package:analysis_server/src/services/completion/dart/enum_constant_constructor_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
@@ -117,7 +118,7 @@
includedElementNames == null &&
includedSuggestionRelevanceTags == null));
- Future<List<CompletionSuggestion>> computeSuggestions(
+ Future<List<CompletionSuggestionBuilder>> computeSuggestions(
DartCompletionRequest request,
OperationPerformanceImpl performance, {
bool enableOverrideContributor = true,
@@ -126,12 +127,12 @@
request.checkAborted();
var pathContext = request.resourceProvider.pathContext;
if (!file_paths.isDart(pathContext, request.path)) {
- return const <CompletionSuggestion>[];
+ return const <CompletionSuggestionBuilder>[];
}
// Don't suggest in comments.
if (request.target.isCommentText) {
- return const <CompletionSuggestion>[];
+ return const <CompletionSuggestionBuilder>[];
}
request.checkAborted();
@@ -142,6 +143,7 @@
ArgListContributor(request, builder),
ClosureContributor(request, builder),
CombinatorContributor(request, builder),
+ EnumConstantConstructorContributor(request, builder),
ExtensionMemberContributor(request, builder),
FieldFormalContributor(request, builder),
KeywordContributor(request, builder),
@@ -503,8 +505,6 @@
/// Information provided by [NotImportedContributor] in addition to suggestions.
class NotImportedSuggestions {
- final Set<protocol.CompletionSuggestion> set = Set.identity();
-
/// This flag is set to `true` if the contributor decided to stop before it
/// processed all available libraries, e.g. we ran out of budget.
bool isIncomplete = false;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/enum_constant_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/enum_constant_constructor_contributor.dart
new file mode 100644
index 0000000..2680e24
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/enum_constant_constructor_contributor.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// A contributor that produces suggestions for constructors to be invoked
+/// in enum constants.
+class EnumConstantConstructorContributor extends DartCompletionContributor {
+ EnumConstantConstructorContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
+ @override
+ Future<void> computeSuggestions() async {
+ if (!request.featureSet.isEnabled(Feature.enhanced_enums)) {
+ return;
+ }
+
+ // TODO(scheglov) It seems unfortunate that we have to re-discover
+ // the location in contributors. This is the work of `OpType`, so why
+ // doesn't it provide all these enclosing `EnumConstantDeclaration`,
+ // `ConstructorSelector`, `EnumDeclaration`?
+ var node = request.target.containingNode;
+ if (node is! ConstructorSelector) {
+ return;
+ }
+
+ if (request.opType.completionLocation != 'ConstructorSelector_name') {
+ return;
+ }
+
+ var arguments = node.parent;
+ if (arguments is! EnumConstantArguments) {
+ return;
+ }
+
+ var enumConstant = arguments.parent;
+ if (enumConstant is! EnumConstantDeclaration) {
+ return;
+ }
+
+ var enumDeclaration = enumConstant.parent;
+ if (enumDeclaration is! EnumDeclaration) {
+ return;
+ }
+
+ var enumElement = enumDeclaration.declaredElement as ClassElement;
+ for (var constructor in enumElement.constructors) {
+ builder.suggestConstructor(
+ constructor,
+ hasClassName: true,
+ tearOff: true,
+ );
+ }
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
index 4408a7a..59a5f61 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
@@ -3,17 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/filtering/fuzzy_matcher.dart';
/// Filters and scores [suggestions] according to how well they match the
/// [pattern]. Sorts [suggestions] by the score, relevance, and name.
-List<CompletionSuggestion> fuzzyFilterSort({
+List<CompletionSuggestionBuilder> fuzzyFilterSort({
required String pattern,
- required List<CompletionSuggestion> suggestions,
+ required List<CompletionSuggestionBuilder> suggestions,
}) {
var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
- double score(CompletionSuggestion suggestion) {
+ double score(CompletionSuggestionBuilder suggestion) {
var suggestionTextToMatch = suggestion.completion;
if (suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
@@ -53,7 +54,7 @@
/// [CompletionSuggestion] scored using [FuzzyMatcher].
class _FuzzyScoredSuggestion {
- final CompletionSuggestion suggestion;
+ final CompletionSuggestionBuilder suggestion;
final double score;
_FuzzyScoredSuggestion(this.suggestion, this.score);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index 3277593..5ef87a7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
show SuggestionBuilder;
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
/// A contributor for calculating suggestions for imported top level members.
@@ -27,8 +28,11 @@
for (var importElement in imports) {
var libraryElement = importElement.importedLibrary;
if (libraryElement != null) {
- _buildSuggestions(importElement.namespace,
- prefix: importElement.prefix?.name);
+ _buildSuggestions(
+ libraryElement: libraryElement,
+ namespace: importElement.namespace,
+ prefix: importElement.prefix?.name,
+ );
if (libraryElement.isDartCore &&
request.opType.includeTypeNameSuggestions) {
builder.suggestName('Never');
@@ -37,10 +41,16 @@
}
}
- void _buildSuggestions(Namespace namespace, {String? prefix}) {
+ void _buildSuggestions({
+ required LibraryElement libraryElement,
+ required Namespace namespace,
+ String? prefix,
+ }) {
+ builder.libraryUriStr = libraryElement.source.uri.toString();
var visitor = LibraryElementSuggestionBuilder(request, builder, prefix);
for (var elem in namespace.definedNames.values) {
elem.accept(visitor);
}
+ builder.libraryUriStr = null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 1dbfe52..94c4ede 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -264,6 +264,29 @@
}
@override
+ void visitEnumDeclaration(EnumDeclaration node) {
+ if (!request.featureSet.isEnabled(Feature.enhanced_enums)) {
+ return;
+ }
+
+ if (entity == node.name) {
+ return;
+ }
+
+ var semicolon = node.semicolon;
+ if (request.offset <= node.leftBracket.offset) {
+ if (node.withClause == null) {
+ _addSuggestion(Keyword.WITH);
+ }
+ if (node.implementsClause == null) {
+ _addSuggestion(Keyword.IMPLEMENTS);
+ }
+ } else if (semicolon != null && semicolon.end <= request.offset) {
+ _addEnumBodyKeywords();
+ }
+ }
+
+ @override
void visitExpression(Expression node) {
_addExpressionKeywords(node);
}
@@ -292,6 +315,20 @@
@override
void visitFieldDeclaration(FieldDeclaration node) {
+ if (request.opType.completionLocation == 'FieldDeclaration_static') {
+ _addSuggestion(Keyword.CONST);
+ _addSuggestion(Keyword.DYNAMIC);
+ _addSuggestion(Keyword.FINAL);
+ _addSuggestion(Keyword.LATE);
+ return;
+ }
+
+ if (request.opType.completionLocation == 'FieldDeclaration_static_late') {
+ _addSuggestion(Keyword.DYNAMIC);
+ _addSuggestion(Keyword.FINAL);
+ return;
+ }
+
var fields = node.fields;
if (entity != fields) {
return;
@@ -313,6 +350,9 @@
request.featureSet.isEnabled(Feature.non_nullable)) {
_addSuggestion(Keyword.LATE);
}
+ if (node.fields.type == null) {
+ _addSuggestion(Keyword.DYNAMIC);
+ }
if (!node.isStatic) {
_addSuggestion(Keyword.STATIC);
}
@@ -860,6 +900,21 @@
}
}
+ void _addEnumBodyKeywords() {
+ _addSuggestions([
+ Keyword.CONST,
+ Keyword.DYNAMIC,
+ Keyword.FINAL,
+ Keyword.GET,
+ Keyword.LATE,
+ Keyword.OPERATOR,
+ Keyword.SET,
+ Keyword.STATIC,
+ Keyword.VAR,
+ Keyword.VOID
+ ]);
+ }
+
void _addExpressionKeywords(AstNode node) {
_addSuggestions([
Keyword.FALSE,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index d9675cb..b78b89e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -41,6 +41,7 @@
if (importElem.prefix?.name == elem.name) {
var library = importElem.importedLibrary;
if (library != null) {
+ builder.libraryUriStr = library.source.uri.toString();
for (var element in importElem.namespace.definedNames.values) {
if (typesOnly && isConstructor) {
// Suggest constructors from the imported libraries.
@@ -72,6 +73,7 @@
if (!typesOnly && importElem.isDeferred) {
builder.suggestLoadLibraryFunction(library.loadLibraryFunction);
}
+ builder.libraryUriStr = null;
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 51853fe..6aa8512 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -26,12 +26,12 @@
var node = request.target.containingNode;
if (node is ConstructorName) {
if (node.parent is ConstructorReference) {
- var element = node.type2.name.staticElement;
+ var element = node.type.name.staticElement;
if (element is ClassElement) {
_buildSuggestions(element);
}
} else {
- var type = node.type2.type;
+ var type = node.type.type;
if (type is InterfaceType) {
var element = type.element;
_buildSuggestions(element);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 8bbff4f..52e893e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -81,11 +81,9 @@
var exportNamespace = element.exportNamespace;
var exportElements = exportNamespace.definedNames.values.toList();
+ builder.libraryUriStr = file.uriStr;
builder.isNotImportedLibrary = true;
builder.laterReplacesEarlier = false;
- builder.suggestionAdded = (suggestion) {
- additionalData.set.add(suggestion);
- };
if (request.includeIdentifiers) {
_buildSuggestions(exportElements);
@@ -95,9 +93,9 @@
_extensions(exportElements),
);
+ builder.libraryUriStr = null;
builder.isNotImportedLibrary = false;
builder.laterReplacesEarlier = true;
- builder.suggestionAdded = null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 829a3e5..aeb07b2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -21,18 +21,122 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
-/// Wrapper around a potentially nullable value.
-///
-/// When the wrapper instance is provided for a property, the property
-/// value is replaced, even if the value to set is `null` itself.
-class CopyWithValue<T> {
- final T value;
+/// A container with enough information to do filtering, and if necessary
+/// build the [CompletionSuggestion] instance.
+abstract class CompletionSuggestionBuilder {
+ /// See [CompletionSuggestion.completion].
+ String get completion;
- CopyWithValue(this.value);
+ /// The key used to de-duplicate suggestions.
+ String get key => completion;
+
+ /// See [CompletionSuggestion.kind].
+ CompletionSuggestionKind get kind;
+
+ /// See [CompletionSuggestion.relevance].
+ int get relevance;
+
+ CompletionSuggestion build();
+}
+
+/// The implementation of [CompletionSuggestionBuilder] that is based on
+/// [ElementCompletionData] and location specific information.
+class CompletionSuggestionBuilderImpl implements CompletionSuggestionBuilder {
+ final ElementCompletionData element;
+
+ @override
+ final CompletionSuggestionKind kind;
+
+ @override
+ final int relevance;
+
+ final String? completionOverride;
+ final String? libraryUriStr;
+ final bool isNotImported;
+
+ CompletionSuggestionBuilderImpl({
+ required this.element,
+ required this.kind,
+ required this.completionOverride,
+ required this.relevance,
+ required this.libraryUriStr,
+ required this.isNotImported,
+ });
+
+ @override
+ String get completion => completionOverride ?? element.completion;
+
+ /// TODO(scheglov) implement better key for not-yet-imported
+ @override
+ String get key {
+ var key = completion;
+ if (element.element.kind == protocol.ElementKind.CONSTRUCTOR) {
+ key = '$key()';
+ }
+ return key;
+ }
+
+ @override
+ CompletionSuggestion build() {
+ return CompletionSuggestion(
+ kind,
+ relevance,
+ completion,
+ completion.length /*selectionOffset*/,
+ 0 /*selectionLength*/,
+ element.isDeprecated,
+ false /*isPotential*/,
+ element: element.element,
+ docSummary: element.documentation?.summary,
+ docComplete: element.documentation?.full,
+ declaringType: element.declaringType,
+ returnType: element.returnType,
+ requiredParameterCount: element.requiredParameterCount,
+ hasNamedParameters: element.hasNamedParameters,
+ parameterNames: element.parameterNames,
+ parameterTypes: element.parameterTypes,
+ defaultArgumentListString: element.defaultArgumentList?.text,
+ defaultArgumentListTextRanges: element.defaultArgumentList?.ranges,
+ libraryUri: libraryUriStr,
+ isNotImported: isNotImported ? true : null,
+ );
+ }
+}
+
+/// Information about an [Element] that does not depend on the location where
+/// this element is suggested. For some often used elements, such as classes,
+/// it might be cached, so created only once.
+class ElementCompletionData {
+ final String completion;
+ final bool isDeprecated;
+ final String? declaringType;
+ final String? returnType;
+ final List<String>? parameterNames;
+ final List<String>? parameterTypes;
+ final int? requiredParameterCount;
+ final bool? hasNamedParameters;
+ CompletionDefaultArgumentList? defaultArgumentList;
+ final _ElementDocumentation? documentation;
+ final protocol.Element element;
+
+ ElementCompletionData({
+ required this.completion,
+ required this.isDeprecated,
+ required this.declaringType,
+ required this.returnType,
+ required this.parameterNames,
+ required this.parameterTypes,
+ required this.requiredParameterCount,
+ required this.hasNamedParameters,
+ required this.defaultArgumentList,
+ required this.documentation,
+ required this.element,
+ });
}
/// This class provides suggestions based upon the visible instance members in
@@ -151,22 +255,6 @@
/// An object used to build a list of suggestions in response to a single
/// completion request.
class SuggestionBuilder {
- /// The cache of suggestions for [Element]s. We use it to avoid computing
- /// the same documentation, parameters, return type, etc for elements that
- /// are exactly the same (the same instances) as they were the last time.
- ///
- /// This cache works because:
- /// 1. Flutter applications usually reference many libraries, which they
- /// consume, but don't change. So, all their elements stay unchanged.
- /// 2. The analyzer keeps the same library instances loaded as the user
- /// types in the application, so the instances of all elements stay the
- /// same, and the cache works.
- /// 3. The analyzer does not patch elements (at least not after the linking
- /// process is done, and the elements are exposed to any client code). So,
- /// any type information, or documentation, stays the same. If this changes,
- /// we would need a signal, e.g. some modification counter on the element.
- static final _elementSuggestionCache = Expando<_CompletionSuggestionEntry>();
-
/// The completion request for which suggestions are being built.
final DartCompletionRequest request;
@@ -174,12 +262,13 @@
/// suggestions, or `null` if no notification should occur.
final SuggestionListener? listener;
- /// The function to be invoked when a new suggestion is added.
- void Function(protocol.CompletionSuggestion)? suggestionAdded;
-
/// A map from a completion identifier to a completion suggestion.
- final Map<String, CompletionSuggestion> _suggestionMap =
- <String, CompletionSuggestion>{};
+ final Map<String, CompletionSuggestionBuilder> _suggestionMap = {};
+
+ /// The URI of the library from which suggestions are being added.
+ /// This URI is not necessary the same as the URI that declares an element,
+ /// because of exports.
+ String? libraryUriStr;
/// This flag is set to `true` while adding suggestions for top-level
/// elements from not-yet-imported libraries.
@@ -211,7 +300,8 @@
/// Return an iterable that can be used to access the completion suggestions
/// that have been built.
- Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values;
+ Iterable<CompletionSuggestionBuilder> get suggestions =>
+ _suggestionMap.values;
/// Return the name of the member containing the completion location, or
/// `null` if the completion location isn't within a member or if the target
@@ -279,11 +369,12 @@
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
accessor,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -303,12 +394,12 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
- elementKind: protocol.ElementKind.PARAMETER,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -318,12 +409,13 @@
void suggestClass(ClassElement classElement, {String? prefix}) {
var relevance = _computeTopLevelRelevance(classElement,
elementType: _instantiateClassElement(classElement));
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
classElement,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -368,16 +460,20 @@
);
}
- _add(createSuggestion(
- completion: blockBuffer.toString(),
- displayText: '$parametersString {}',
- selectionOffset: blockSelectionOffset,
- ));
- _add(createSuggestion(
- completion: expressionBuffer.toString(),
- displayText: '$parametersString =>',
- selectionOffset: expressionSelectionOffset,
- ));
+ _addSuggestion(
+ createSuggestion(
+ completion: blockBuffer.toString(),
+ displayText: '$parametersString {}',
+ selectionOffset: blockSelectionOffset,
+ ),
+ );
+ _addSuggestion(
+ createSuggestion(
+ completion: expressionBuffer.toString(),
+ displayText: '$parametersString =>',
+ selectionOffset: expressionSelectionOffset,
+ ),
+ );
}
/// Add a suggestion for a [constructor]. If a [kind] is provided it will be
@@ -421,11 +517,16 @@
var returnType = _instantiateClassElement(enclosingClass);
var relevance =
_computeTopLevelRelevance(constructor, elementType: returnType);
- _add(_createSuggestion(constructor,
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ constructor,
completion: completion,
kind: kind,
prefix: prefix,
- relevance: relevance));
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a top-level [element]. If a [kind] is provided it
@@ -460,13 +561,14 @@
var completion = '$enumName.$constantName';
var relevance =
_computeTopLevelRelevance(constant, elementType: constant.type);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
constant,
completion: completion,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -479,8 +581,15 @@
String? prefix}) {
var relevance = _computeTopLevelRelevance(extension,
elementType: extension.extendedType);
- _add(_createSuggestion(extension,
- kind: kind, prefix: prefix, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ extension,
+ kind: kind,
+ prefix: prefix,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a [field]. If the field is being referenced with a
@@ -509,11 +618,12 @@
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
field,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -522,11 +632,12 @@
void suggestFieldFormalParameter(FieldElement field) {
// TODO(brianwilkerson) Add a parameter (`bool includePrefix`) indicating
// whether to include the `this.` prefix in the completion.
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
field,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: Relevance.fieldFormalParameter,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -539,22 +650,24 @@
typeParameters: null,
parameters: '()',
returnType: 'void');
- _add(CompletionSuggestion(
- CompletionSuggestionKind.INVOCATION,
- Relevance.callFunction,
- FunctionElement.CALL_METHOD_NAME,
- FunctionElement.CALL_METHOD_NAME.length,
- 0,
- false,
- false,
- displayText: 'call()',
- element: element,
- returnType: 'void',
- parameterNames: [],
- parameterTypes: [],
- requiredParameterCount: 0,
- hasNamedParameters: false,
- ));
+ _addSuggestion(
+ CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ Relevance.callFunction,
+ FunctionElement.CALL_METHOD_NAME,
+ FunctionElement.CALL_METHOD_NAME.length,
+ 0,
+ false,
+ false,
+ displayText: 'call()',
+ element: element,
+ returnType: 'void',
+ parameterNames: [],
+ parameterTypes: [],
+ requiredParameterCount: 0,
+ hasNamedParameters: false,
+ ),
+ );
}
/// Add a suggestion for a [keyword]. The [offset] is the offset from the
@@ -574,8 +687,8 @@
contextType: contextType,
keyword: keywordFeature,
);
- _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
- keyword, offset ?? keyword.length, 0, false, false));
+ _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.KEYWORD,
+ relevance, keyword, offset ?? keyword.length, 0, false, false));
}
/// Add a suggestion for a [label].
@@ -588,7 +701,7 @@
Relevance.label, completion, completion.length, 0, false, false);
suggestion.element = createLocalElement(
request.source, protocol.ElementKind.LABEL, label.label);
- _add(suggestion);
+ _addSuggestion(suggestion);
}
}
@@ -598,11 +711,12 @@
// TODO(brianwilkerson) This might want to use the context type rather than
// a fixed value.
var relevance = Relevance.loadLibrary;
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
function,
kind: CompletionSuggestionKind.INVOCATION,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -628,11 +742,12 @@
isConstant: isConstant,
localVariableDistance: localVariableDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
variable,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -675,46 +790,55 @@
inheritanceDistance: inheritanceDistance,
);
- var suggestion =
- _createSuggestion(method, kind: kind, relevance: relevance);
- if (suggestion != null) {
- var enclosingElement = method.enclosingElement;
- if (method.name == 'setState' &&
- enclosingElement is ClassElement &&
- flutter.isExactState(enclosingElement)) {
- // TODO(brianwilkerson) Make this more efficient by creating the correct
- // suggestion in the first place.
- // Find the line indentation.
- var indent = getRequestLineIndent(request);
+ var enclosingElement = method.enclosingElement;
+ if (method.name == 'setState' &&
+ enclosingElement is ClassElement &&
+ flutter.isExactState(enclosingElement)) {
+ // TODO(brianwilkerson) Make this more efficient by creating the correct
+ // suggestion in the first place.
+ // Find the line indentation.
+ var indent = getRequestLineIndent(request);
- // Let the user know that we are going to insert a complete statement.
- suggestion.displayText = 'setState(() {});';
+ // Build the completion and the selection offset.
+ var buffer = StringBuffer();
+ buffer.writeln('setState(() {');
+ buffer.write('$indent ');
+ var selectionOffset = buffer.length;
+ buffer.writeln();
+ buffer.write('$indent});');
- // Build the completion and the selection offset.
- var buffer = StringBuffer();
- buffer.writeln('setState(() {');
- buffer.write('$indent ');
- suggestion.selectionOffset = buffer.length;
- buffer.writeln();
- buffer.write('$indent});');
- suggestion.completion = buffer.toString();
-
- // There are no arguments to fill.
- suggestion.parameterNames = null;
- suggestion.parameterTypes = null;
- suggestion.requiredParameterCount = null;
- suggestion.hasNamedParameters = null;
- }
- _add(suggestion);
+ _addSuggestion(
+ CompletionSuggestion(
+ kind,
+ relevance,
+ buffer.toString(),
+ selectionOffset,
+ 0,
+ false,
+ false,
+ // Let the user know that we are going to insert a complete statement.
+ displayText: 'setState(() {});',
+ ),
+ );
+ return;
}
+
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ method,
+ kind: kind,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to use the [name] at a declaration site.
void suggestName(String name) {
// TODO(brianwilkerson) Explore whether there are any features of the name
// that can be used to provide better relevance scores.
- _add(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, 500, name,
- name.length, 0, false, false));
+ _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
+ 500, name, name.length, 0, false, false));
}
/// Add a suggestion to add a named argument corresponding to the [parameter].
@@ -783,7 +907,8 @@
suggestion.element =
convertElement(parameter, withNullability: _isNonNullableByDefault);
}
- _add(suggestion);
+
+ _addSuggestion(suggestion);
}
/// Add a suggestion to replace the [targetId] with an override of the given
@@ -842,7 +967,7 @@
displayText: displayText);
suggestion.element = protocol.convertElement(element,
withNullability: _isNonNullableByDefault);
- _add(suggestion);
+ _addSuggestion(suggestion);
}
/// Add a suggestion for a [parameter].
@@ -861,11 +986,12 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -879,19 +1005,25 @@
var relevance = _computeRelevance(
elementKind: elementKind,
);
- _add(_createSuggestion(library,
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ library,
completion: prefix,
kind: CompletionSuggestionKind.IDENTIFIER,
- relevance: relevance));
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to reference a [parameter] in a super formal parameter.
void suggestSuperFormalParameter(ParameterElement parameter) {
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: Relevance.superFormalParameter,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -904,8 +1036,15 @@
String? prefix}) {
var relevance =
_computeTopLevelRelevance(function, elementType: function.returnType);
- _add(_createSuggestion(function,
- kind: kind, prefix: prefix, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ function,
+ kind: kind,
+ prefix: prefix,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a top-level property [accessor]. If a [kind] is
@@ -951,12 +1090,13 @@
startsWithDollar: startsWithDollar,
superMatches: superMatches,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
accessor,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -970,12 +1110,13 @@
assert(variable.enclosingElement is CompilationUnitElement);
var relevance =
_computeTopLevelRelevance(variable, elementType: variable.type);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
variable,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -986,12 +1127,13 @@
void suggestTypeAlias(TypeAliasElement typeAlias, {String? prefix}) {
var relevance = _computeTopLevelRelevance(typeAlias,
elementType: _instantiateTypeAlias(typeAlias));
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
typeAlias,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -1006,34 +1148,46 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(_createSuggestion(parameter,
- kind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ parameter,
+ kind: CompletionSuggestionKind.IDENTIFIER,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to use the [uri] in an import, export, or part directive.
void suggestUri(String uri) {
var relevance =
uri == 'dart:core' ? Relevance.importDartCore : Relevance.import;
- _add(CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
- uri.length, 0, false, false));
+ _addSuggestion(
+ CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
+ uri.length, 0, false, false),
+ );
}
/// Add the given [suggestion] if it isn't `null` and if it isn't shadowed by
/// a previously added suggestion.
- void _add(protocol.CompletionSuggestion? suggestion) {
+ void _addBuilder(CompletionSuggestionBuilder? suggestion) {
if (suggestion != null) {
- var key = suggestion.completion;
- if (suggestion.element?.kind == protocol.ElementKind.CONSTRUCTOR) {
- key = '$key()';
- }
+ var key = suggestion.key;
listener?.builtSuggestion(suggestion);
if (laterReplacesEarlier || !_suggestionMap.containsKey(key)) {
_suggestionMap[key] = suggestion;
- suggestionAdded?.call(suggestion);
}
}
}
+ /// Add the given [suggestion] if it isn't shadowed by a previously added
+ /// suggestion.
+ void _addSuggestion(protocol.CompletionSuggestion suggestion) {
+ _addBuilder(
+ ValueCompletionSuggestionBuilder(suggestion),
+ );
+ }
+
/// Compute the value of the _element kind_ feature for the given [element] in
/// the completion context.
double _computeElementKind(Element element, {double? distance}) {
@@ -1119,112 +1273,154 @@
);
}
- /// Return a suggestion based on the [element], or `null` if a suggestion is
- /// not appropriate for the element. If the completion should be something
+ /// Return a [CompletionSuggestionBuilder] based on the [element], or `null`
+ /// if the element cannot be suggested. If the completion should be something
/// different than the name of the element, then the [completion] should be
/// supplied. If an [elementKind] is provided, then it will be used rather
/// than the kind normally used for the element. If a [prefix] is provided,
/// then the element name (or completion) will be prefixed. The [relevance] is
/// the relevance of the suggestion.
- CompletionSuggestion? _createSuggestion(Element element,
- {String? completion,
- protocol.ElementKind? elementKind,
- required CompletionSuggestionKind kind,
- String? prefix,
- required int relevance}) {
- var inputs = _CompletionSuggestionInputs(
- completion: completion,
- elementKind: elementKind,
- kind: kind,
- prefix: prefix,
- );
-
- var cacheEntry = _elementSuggestionCache[element];
- if (cacheEntry != null) {
- if (cacheEntry.inputs == inputs) {
- final suggestion = cacheEntry.suggestion;
- suggestion.relevance = relevance;
- return suggestion;
- }
- }
-
- var suggestion = _createSuggestion0(
- element,
- completion: completion,
- elementKind: elementKind,
- kind: kind,
- prefix: prefix,
- relevance: relevance,
- );
- if (suggestion == null) {
+ CompletionSuggestionBuilder? _createCompletionSuggestionBuilder(
+ Element element, {
+ String? completion,
+ required CompletionSuggestionKind kind,
+ required int relevance,
+ required bool isNotImported,
+ String? prefix,
+ }) {
+ var elementData = _getElementCompletionData(element);
+ if (elementData == null) {
return null;
}
- _elementSuggestionCache[element] = _CompletionSuggestionEntry(
- inputs: inputs,
- suggestion: suggestion,
+ if (prefix != null) {
+ completion ??= elementData.completion;
+ completion = prefix + '.' + completion;
+ }
+
+ return CompletionSuggestionBuilderImpl(
+ element: elementData,
+ kind: kind,
+ completionOverride: completion,
+ relevance: relevance,
+ libraryUriStr: libraryUriStr,
+ isNotImported: isNotImported,
);
- return suggestion;
}
- /// The non-caching implementation of [_createSuggestion].
- CompletionSuggestion? _createSuggestion0(
- Element element, {
- required String? completion,
- required protocol.ElementKind? elementKind,
- required CompletionSuggestionKind kind,
- required String? prefix,
- required int relevance,
- }) {
+ /// The non-caching implementation of [_getElementCompletionData].
+ ElementCompletionData? _createElementCompletionData(Element element) {
+ // Do not include operators in suggestions.
if (element is ExecutableElement && element.isOperator) {
- // Do not include operators in suggestions
return null;
}
- completion ??= element.displayName;
- if (completion.isEmpty) {
- return null;
- }
- if (prefix != null && prefix.isNotEmpty) {
- completion = '$prefix.$completion';
- }
- var suggestion = CompletionSuggestion(kind, relevance, completion,
- completion.length, 0, element.hasOrInheritsDeprecated, false);
- _setDocumentation(suggestion, element);
- var suggestedElement = suggestion.element = protocol.convertElement(element,
- withNullability: _isNonNullableByDefault);
- if (elementKind != null) {
- suggestedElement.kind = elementKind;
- }
+ var completion = element.displayName;
+ var documentation = _getDocumentation(element);
+
+ var suggestedElement = protocol.convertElement(
+ element,
+ withNullability: _isNonNullableByDefault,
+ );
+
var enclosingElement = element.enclosingElement;
+
+ String? declaringType;
if (enclosingElement is ClassElement) {
- suggestion.declaringType = enclosingElement.displayName;
+ declaringType = enclosingElement.displayName;
}
- suggestion.returnType =
- getReturnTypeString(element, withNullability: _isNonNullableByDefault);
+
+ var returnType = getReturnTypeString(
+ element,
+ withNullability: _isNonNullableByDefault,
+ );
+
+ List<String>? parameterNames;
+ List<String>? parameterTypes;
+ int? requiredParameterCount;
+ bool? hasNamedParameters;
+ CompletionDefaultArgumentList? defaultArgumentList;
if (element is ExecutableElement && element is! PropertyAccessorElement) {
- suggestion.parameterNames = element.parameters
- .map((ParameterElement parameter) => parameter.name)
- .toList();
- suggestion.parameterTypes =
- element.parameters.map((ParameterElement parameter) {
- var paramType = parameter.type;
- return paramType.getDisplayString(
- withNullability: _isNonNullableByDefault);
+ parameterNames = element.parameters.map((parameter) {
+ return parameter.name;
+ }).toList();
+ parameterTypes = element.parameters.map((ParameterElement parameter) {
+ return parameter.type.getDisplayString(
+ withNullability: _isNonNullableByDefault,
+ );
}).toList();
var requiredParameters = element.parameters
.where((ParameterElement param) => param.isRequiredPositional);
- suggestion.requiredParameterCount = requiredParameters.length;
+ requiredParameterCount = requiredParameters.length;
var namedParameters =
element.parameters.where((ParameterElement param) => param.isNamed);
- suggestion.hasNamedParameters = namedParameters.isNotEmpty;
+ hasNamedParameters = namedParameters.isNotEmpty;
- addDefaultArgDetails(
- suggestion, element, requiredParameters, namedParameters);
+ defaultArgumentList = computeCompletionDefaultArgumentList(
+ element, requiredParameters, namedParameters);
}
- return suggestion;
+
+ return ElementCompletionData(
+ completion: completion,
+ isDeprecated: element.hasOrInheritsDeprecated,
+ declaringType: declaringType,
+ returnType: returnType,
+ parameterNames: parameterNames,
+ parameterTypes: parameterTypes,
+ requiredParameterCount: requiredParameterCount,
+ hasNamedParameters: hasNamedParameters,
+ documentation: documentation,
+ defaultArgumentList: defaultArgumentList,
+ element: suggestedElement,
+ );
+ }
+
+ /// If the [element] has a documentation comment, return it.
+ _ElementDocumentation? _getDocumentation(Element element) {
+ var documentationCache = request.documentationCache;
+ var data = documentationCache?.dataFor(element);
+ if (data != null) {
+ return _ElementDocumentation(
+ full: data.full,
+ summary: data.summary,
+ );
+ }
+ var doc = DartUnitHoverComputer.computeDocumentation(
+ request.dartdocDirectiveInfo,
+ element,
+ includeSummary: true,
+ );
+ if (doc is DocumentationWithSummary) {
+ return _ElementDocumentation(
+ full: doc.full,
+ summary: doc.summary,
+ );
+ }
+ if (doc is Documentation) {
+ return _ElementDocumentation(
+ full: doc.full,
+ summary: null,
+ );
+ }
+ return null;
+ }
+
+ /// Return [ElementCompletionData] for the [element], or `null` if the
+ /// element cannot be suggested for completion.
+ ElementCompletionData? _getElementCompletionData(Element element) {
+ ElementCompletionData? result;
+
+ var hasCompletionData = element.ifTypeOrNull<HasCompletionData>();
+ if (hasCompletionData != null) {
+ result = hasCompletionData.completionData.ifTypeOrNull();
+ }
+
+ result ??= _createElementCompletionData(element);
+
+ hasCompletionData?.completionData = result;
+ return result;
}
/// Return the type associated with the [accessor], maybe `null` if an
@@ -1300,7 +1496,7 @@
abstract class SuggestionListener {
/// Invoked when a suggestion has been built.
- void builtSuggestion(protocol.CompletionSuggestion suggestion);
+ void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder);
/// Invoked with the values of the features that were computed in the process
/// of building a suggestion. This method is invoked prior to invoking
@@ -1329,80 +1525,44 @@
void missingElementKindTableFor(String completionLocation);
}
-/// The entry of the element to suggestion cache.
-class _CompletionSuggestionEntry {
- final _CompletionSuggestionInputs inputs;
+/// [CompletionSuggestionBuilder] that is based on a [CompletionSuggestion].
+class ValueCompletionSuggestionBuilder implements CompletionSuggestionBuilder {
+ final CompletionSuggestion _suggestion;
- /// The suggestion computed for the element and [inputs].
- final CompletionSuggestion suggestion;
-
- _CompletionSuggestionEntry({
- required this.inputs,
- required this.suggestion,
- });
-}
-
-/// The inputs, other than the [Element], that were provided to create an
-/// instance of [CompletionSuggestion].
-class _CompletionSuggestionInputs {
- final String? completion;
- final protocol.ElementKind? elementKind;
- final CompletionSuggestionKind kind;
- final String? prefix;
-
- _CompletionSuggestionInputs({
- required this.completion,
- required this.elementKind,
- required this.kind,
- required this.prefix,
- });
+ ValueCompletionSuggestionBuilder(this._suggestion);
@override
- bool operator ==(Object other) {
- return other is _CompletionSuggestionInputs &&
- other.completion == completion &&
- other.elementKind == elementKind &&
- other.kind == kind &&
- other.prefix == prefix;
+ String get completion => _suggestion.completion;
+
+ @override
+ String get key => completion;
+
+ @override
+ protocol.CompletionSuggestionKind get kind => _suggestion.kind;
+
+ @override
+ int get relevance => _suggestion.relevance;
+
+ @override
+ CompletionSuggestion build() {
+ return _suggestion;
}
}
-extension CompletionSuggestionExtension on CompletionSuggestion {
- CompletionSuggestion copyWith({
- CopyWithValue<bool?>? isNotImported,
- }) {
- return protocol.CompletionSuggestion(
- kind,
- relevance,
- completion,
- selectionOffset,
- selectionLength,
- isDeprecated,
- isPotential,
- displayText: displayText,
- replacementOffset: replacementOffset,
- replacementLength: replacementLength,
- docSummary: docSummary,
- docComplete: docComplete,
- declaringType: declaringType,
- defaultArgumentListString: defaultArgumentListString,
- defaultArgumentListTextRanges: defaultArgumentListTextRanges,
- element: element,
- returnType: returnType,
- parameterNames: parameterNames,
- parameterTypes: parameterTypes,
- requiredParameterCount: requiredParameterCount,
- hasNamedParameters: hasNamedParameters,
- parameterName: parameterName,
- parameterType: parameterType,
- isNotImported: isNotImported.orElse(this.isNotImported),
- );
- }
+class _ElementDocumentation {
+ final String full;
+ final String? summary;
+
+ _ElementDocumentation({
+ required this.full,
+ required this.summary,
+ });
}
-extension _CopyWithValueExtension<T> on CopyWithValue<T>? {
- T orElse(T defaultValue) {
+extension on Object? {
+ /// If the target is [T], return it, otherwise `null`.
+ T? ifTypeOrNull<T>() {
final self = this;
- return self != null ? self.value : defaultValue;
+ return self is T ? self : null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index eef975c..279afd7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -25,13 +25,55 @@
return b.relevance.compareTo(a.relevance);
};
-/// Add default argument list text and ranges based on the given
+String buildClosureParameters(FunctionType type) {
+ var buffer = StringBuffer();
+ buffer.write('(');
+
+ var hasNamed = false;
+ var hasOptionalPositional = false;
+ var parameters = type.parameters;
+ var existingNames = parameters.map((p) => p.name).toSet();
+ for (var i = 0; i < parameters.length; ++i) {
+ var parameter = parameters[i];
+ if (i != 0) {
+ buffer.write(', ');
+ }
+ if (parameter.isNamed && !hasNamed) {
+ hasNamed = true;
+ buffer.write('{');
+ } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
+ hasOptionalPositional = true;
+ buffer.write('[');
+ }
+ var name = parameter.name;
+ if (name.isEmpty) {
+ name = 'p$i';
+ var index = 1;
+ while (existingNames.contains(name)) {
+ name = 'p${i}_$index';
+ index++;
+ }
+ }
+ buffer.write(name);
+ }
+
+ if (hasNamed) {
+ buffer.write('}');
+ } else if (hasOptionalPositional) {
+ buffer.write(']');
+ }
+
+ buffer.write(')');
+ return buffer.toString();
+}
+
+/// Compute default argument list text and ranges based on the given
/// [requiredParams] and [namedParams].
-void addDefaultArgDetails(
- CompletionSuggestion suggestion,
- Element element,
- Iterable<ParameterElement> requiredParams,
- Iterable<ParameterElement> namedParams) {
+CompletionDefaultArgumentList computeCompletionDefaultArgumentList(
+ Element element,
+ Iterable<ParameterElement> requiredParams,
+ Iterable<ParameterElement> namedParams,
+) {
var sb = StringBuffer();
var ranges = <int>[];
@@ -95,50 +137,10 @@
}
}
- suggestion.defaultArgumentListString = sb.isNotEmpty ? sb.toString() : null;
- suggestion.defaultArgumentListTextRanges = ranges.isNotEmpty ? ranges : null;
-}
-
-String buildClosureParameters(FunctionType type) {
- var buffer = StringBuffer();
- buffer.write('(');
-
- var hasNamed = false;
- var hasOptionalPositional = false;
- var parameters = type.parameters;
- var existingNames = parameters.map((p) => p.name).toSet();
- for (var i = 0; i < parameters.length; ++i) {
- var parameter = parameters[i];
- if (i != 0) {
- buffer.write(', ');
- }
- if (parameter.isNamed && !hasNamed) {
- hasNamed = true;
- buffer.write('{');
- } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
- hasOptionalPositional = true;
- buffer.write('[');
- }
- var name = parameter.name;
- if (name.isEmpty) {
- name = 'p$i';
- var index = 1;
- while (existingNames.contains(name)) {
- name = 'p${i}_$index';
- index++;
- }
- }
- buffer.write(name);
- }
-
- if (hasNamed) {
- buffer.write('}');
- } else if (hasOptionalPositional) {
- buffer.write(']');
- }
-
- buffer.write(')');
- return buffer.toString();
+ return CompletionDefaultArgumentList(
+ text: sb.isNotEmpty ? sb.toString() : null,
+ ranges: ranges.isNotEmpty ? ranges : null,
+ );
}
/// Create a new protocol Element for inclusion in a completion suggestion.
@@ -246,6 +248,16 @@
return type.getDisplayString(withNullability: false);
}
+class CompletionDefaultArgumentList {
+ final String? text;
+ final List<int>? ranges;
+
+ CompletionDefaultArgumentList({
+ required this.text,
+ required this.ranges,
+ });
+}
+
/// A tuple of text to insert and an (optional) location for the cursor.
class DefaultArgument {
/// The text to insert.
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index c7233ba..0e0b1c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -56,6 +56,11 @@
30,
'Assign value to new local variable',
);
+ static const CONVERT_CLASS_TO_ENUM = AssistKind(
+ 'dart.assist.convert.classToEnum',
+ 30,
+ 'Convert class to an enum',
+ );
static const CONVERT_CLASS_TO_MIXIN = AssistKind(
'dart.assist.convert.classToMixin',
30,
@@ -196,6 +201,11 @@
30,
'Convert to a spread',
);
+ static const CONVERT_TO_SUPER_INITIALIZING_PARAMETER = AssistKind(
+ 'dart.assist.convert.toSuperInitializingParameter',
+ 30,
+ 'Convert to a super initializing parameter',
+ );
static const ENCAPSULATE_FIELD = AssistKind(
'dart.assist.encapsulateField',
30,
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 2e8d400..70835d5 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -12,6 +12,7 @@
import 'package:analysis_server/src/services/correction/dart/add_type_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/assign_to_local_variable.dart';
import 'package:analysis_server/src/services/correction/dart/convert_add_all_to_spread.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_class_to_enum.dart';
import 'package:analysis_server/src/services/correction/dart/convert_class_to_mixin.dart';
import 'package:analysis_server/src/services/correction/dart/convert_conditional_expression_to_if_element.dart';
import 'package:analysis_server/src/services/correction/dart/convert_documentation_into_block.dart';
@@ -38,6 +39,7 @@
import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_super_initializing_parameter.dart';
import 'package:analysis_server/src/services/correction/dart/encapsulate_field.dart';
import 'package:analysis_server/src/services/correction/dart/exchange_operands.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_children.dart';
@@ -90,6 +92,7 @@
AddTypeAnnotation.newInstanceBulkFixable,
AssignToLocalVariable.newInstance,
ConvertAddAllToSpread.newInstance,
+ ConvertClassToEnum.newInstance,
ConvertClassToMixin.newInstance,
ConvertConditionalExpressionToIfElement.newInstance,
ConvertDocumentationIntoBlock.newInstance,
@@ -104,19 +107,20 @@
ConvertMapFromIterableToForLiteral.newInstance,
ConvertPartOfToUri.newInstance,
ConvertToDoubleQuotes.newInstance,
- ConvertToFieldParameter.newInstance,
- ConvertToMultilineString.newInstance,
- ConvertToNormalParameter.newInstance,
- ConvertToSingleQuotes.newInstance,
ConvertToExpressionFunctionBody.newInstance,
+ ConvertToFieldParameter.newInstance,
ConvertToGenericFunctionSyntax.newInstance,
ConvertToIntLiteral.newInstance,
ConvertToListLiteral.newInstance,
ConvertToMapLiteral.newInstance,
+ ConvertToMultilineString.newInstance,
+ ConvertToNormalParameter.newInstance,
ConvertToNullAware.newInstance,
ConvertToPackageImport.newInstance,
ConvertToRelativeImport.newInstance,
ConvertToSetLiteral.newInstance,
+ ConvertToSingleQuotes.newInstance,
+ ConvertToSuperInitializingParameter.newInstance,
EncapsulateField.newInstance,
ExchangeOperands.newInstance,
FlutterConvertToChildren.newInstance,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index 79f8ef3..621744c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -541,16 +541,15 @@
return false;
}
- /// Return `true` if the [node] might be a type name.
- bool mightBeTypeIdentifier(AstNode node) {
+ /// If the [node] might be a type name, return its name.
+ String? nameOfType(AstNode node) {
if (node is SimpleIdentifier) {
- var parent = node.parent;
- if (parent is NamedType) {
- return true;
+ var name = node.name;
+ if (node.parent is NamedType || _isNameOfType(name)) {
+ return name;
}
- return _isNameOfType(node.name);
}
- return false;
+ return null;
}
/// Replace all occurrences of the [oldIndent] with the [newIndent] within the
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart b/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
index 2ec24e4..f474802 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
@@ -74,9 +74,9 @@
node = node.identifier;
}
// Process if looks like a type.
- if (mightBeTypeIdentifier(node)) {
+ var name = nameOfType(node);
+ if (name != null) {
// Prepare for selecting the closest element.
- var name = (node as SimpleIdentifier).name;
var finder = _ClosestElementFinder(
name, (Element element) => element is ClassElement);
// Check elements of this library.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_class_to_enum.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_class_to_enum.dart
new file mode 100644
index 0000000..9530b09
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_class_to_enum.dart
@@ -0,0 +1,769 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analysis_server/src/utilities/extensions/range_factory.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:collection/collection.dart';
+
+class ConvertClassToEnum extends CorrectionProducer {
+ @override
+ AssistKind get assistKind => DartAssistKind.CONVERT_CLASS_TO_ENUM;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ if (!libraryElement.featureSet.isEnabled(Feature.enhanced_enums)) {
+ // If the library doesn't support enhanced_enums then the class can't be
+ // converted.
+ return;
+ }
+ if (libraryElement.units.length > 1) {
+ // If the library has any part files, then the class can't be converted
+ // because we don't currently have a performant way to access the ASTs for
+ // the parts to check for invocations of the constructors or subclasses of
+ // the class.
+ return;
+ }
+ var node = this.node;
+ if (node is! SimpleIdentifier) {
+ return;
+ }
+ var parent = node.parent;
+ if (parent is ClassDeclaration && parent.name == node) {
+ var description = _EnumDescription.fromClass(parent);
+ if (description != null) {
+ await builder.addDartFileEdit(file, (builder) {
+ description.applyChanges(builder, utils);
+ });
+ }
+ }
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+ static ConvertClassToEnum newInstance() => ConvertClassToEnum();
+}
+
+/// A superclass for the [_EnumVisitor] and [_NonEnumVisitor].
+class _BaseVisitor extends RecursiveAstVisitor<void> {
+ /// The element representing the enum declaration that's being visited.
+ final ClassElement classElement;
+
+ _BaseVisitor(this.classElement);
+
+ /// Return `true` if the given [node] is an invocation of a generative
+ /// constructor from the class being converted.
+ bool invokesGenerativeConstructor(InstanceCreationExpression node) {
+ var constructorElement = node.constructorName.staticElement;
+ return constructorElement != null &&
+ !constructorElement.isFactory &&
+ constructorElement.enclosingElement == classElement;
+ }
+}
+
+/// An exception thrown by the visitors if a condition is found that prevents
+/// the class from being converted.
+class _CannotConvertException implements Exception {
+ final String message;
+
+ _CannotConvertException(this.message);
+}
+
+/// A representation of a static field in the class being converted that will be
+/// replaced by an enum constant.
+class _ConstantField extends _Field {
+ /// The element representing the constructor used to initialize the field.
+ ConstructorElement constructorElement;
+
+ /// The invocation of the constructor.
+ final InstanceCreationExpression instanceCreation;
+
+ /// The value of the index field.
+ final int indexValue;
+
+ _ConstantField(
+ FieldElement element,
+ VariableDeclaration declaration,
+ VariableDeclarationList declarationList,
+ FieldDeclaration fieldDeclaration,
+ this.instanceCreation,
+ this.constructorElement,
+ this.indexValue)
+ : super(element, declaration, declarationList, fieldDeclaration);
+}
+
+/// Information about a single constructor in the class being converted.
+class _Constructor {
+ /// The declaration of the constructor.
+ final ConstructorDeclaration declaration;
+
+ /// The element representing the constructor.
+ final ConstructorElement element;
+
+ _Constructor(this.declaration, this.element);
+}
+
+/// Information about the constructors in the class being converted.
+class _Constructors {
+ /// A map from elements to constructors.
+ final Map<ConstructorElement, _Constructor> byElement = {};
+
+ _Constructors();
+
+ /// Return the constructors in this collection.
+ Iterable<_Constructor> get constructors => byElement.values;
+
+ /// Add the given [constructor] to this collection.
+ void add(_Constructor constructor) {
+ byElement[constructor.element] = constructor;
+ }
+
+ /// Return the constructor with the given [element].
+ _Constructor? forElement(ConstructorElement element) {
+ return byElement[element];
+ }
+}
+
+/// A description of how to convert the class to an enum.
+class _EnumDescription {
+ /// The class declaration being converted.
+ final ClassDeclaration classDeclaration;
+
+ /// A map from constructor declarations to information about the parameter
+ /// corresponding to the index field. The map is `null` if there is no index
+ /// field.
+ final Map<_Constructor, _Parameter>? constructorMap;
+
+ /// A list of the declarations to be converted into enum constants.
+ final _Fields fields;
+
+ /// A list of the indexes of members that need to be deleted.
+ final List<int> membersToDelete;
+
+ _EnumDescription({
+ required this.classDeclaration,
+ required this.constructorMap,
+ required this.fields,
+ required this.membersToDelete,
+ });
+
+ /// Return the offset immediately following the opening brace for the class
+ /// body.
+ int get bodyOffset => classDeclaration.leftBracket.end;
+
+ /// Use the [builder] and correction [utils] to apply the change necessary to
+ /// convert the class to an enum.
+ void applyChanges(DartFileEditBuilder builder, CorrectionUtils utils) {
+ // Replace the keyword.
+ builder.addSimpleReplacement(
+ range.token(classDeclaration.classKeyword), 'enum');
+
+ // Remove the extends clause if there is one.
+ final extendsClause = classDeclaration.extendsClause;
+ if (extendsClause != null) {
+ var followingToken = extendsClause.endToken.next!;
+ builder.addDeletion(range.startStart(extendsClause, followingToken));
+ }
+
+ // Compute the declarations of the enum constants and delete the fields
+ // being converted.
+ var members = classDeclaration.members;
+ var indent = utils.getIndent(1);
+ var eol = utils.endOfLine;
+ var constantsBuffer = StringBuffer();
+ var fieldsToConvert = fields.fieldsToConvert;
+ fieldsToConvert
+ .sort((first, second) => first.indexValue.compareTo(second.indexValue));
+ for (var field in fieldsToConvert) {
+ // Compute the declaration of the corresponding enum constant.
+ if (constantsBuffer.isNotEmpty) {
+ constantsBuffer.write(',$eol$indent');
+ }
+ constantsBuffer.write(field.name);
+ var invocation = field.instanceCreation;
+ var constructorNameNode = invocation.constructorName;
+ var invokedConstructorElement = field.constructorElement;
+ var invokedConstructor = constructorMap?.keys.firstWhere(
+ (constructor) => constructor.element == invokedConstructorElement);
+ var parameterData = constructorMap?[invokedConstructor];
+ var typeArguments = constructorNameNode.type.typeArguments;
+ if (typeArguments != null) {
+ constantsBuffer.write(utils.getNodeText(typeArguments));
+ }
+ var constructorName = constructorNameNode.name?.name;
+ if (constructorName != null) {
+ constantsBuffer.write('.$constructorName');
+ }
+ var argumentList = invocation.argumentList;
+ var arguments = argumentList.arguments;
+ var argumentCount = arguments.length - (parameterData == null ? 0 : 1);
+ if (argumentCount == 0) {
+ if (typeArguments != null || constructorName != null) {
+ constantsBuffer.write('()');
+ }
+ } else if (parameterData == null) {
+ constantsBuffer.write(utils.getNodeText(argumentList));
+ } else {
+ constantsBuffer.write('(');
+ var index = parameterData.index;
+ var last = arguments.length - 1;
+ if (index == 0) {
+ var offset = arguments[1].offset;
+ var length = arguments[last].end - offset;
+ constantsBuffer.write(utils.getText(offset, length));
+ } else if (index == last) {
+ var offset = arguments[0].offset;
+ int length;
+ if (arguments[last].endToken.next?.type == TokenType.COMMA) {
+ length = arguments[last].offset - offset;
+ } else {
+ length = arguments[last - 1].end - offset;
+ }
+ constantsBuffer.write(utils.getText(offset, length));
+ } else {
+ var offset = arguments[0].offset;
+ var length = arguments[index].offset - offset;
+ constantsBuffer.write(utils.getText(offset, length));
+
+ offset = arguments[index + 1].offset;
+ length = argumentList.endToken.offset - offset;
+ constantsBuffer.write(utils.getText(offset, length));
+ }
+ constantsBuffer.write(')');
+ }
+
+ // Delete the static field that was converted to an enum constant.
+ _deleteField(builder, field, members);
+ }
+
+ // Remove the index field.
+ var indexField = fields.indexField;
+ if (indexField != null) {
+ _deleteField(builder, indexField, members);
+ }
+
+ // Update the constructors.
+ var removedConstructor = _removeUnnamedConstructor();
+ _transformConstructors(builder, removedConstructor);
+
+ // Special case replacing all of the members.
+ if (membersToDelete.length == members.length) {
+ builder.addSimpleReplacement(range.startEnd(members.first, members.last),
+ constantsBuffer.toString());
+ return;
+ }
+
+ // Insert the declarations of the enum constants.
+ var semicolon = ';';
+ var prefix = '$eol$indent';
+ var suffix = '$semicolon$eol';
+ builder.addSimpleInsertion(bodyOffset, '$prefix$constantsBuffer$suffix');
+
+ // Delete any members that are no longer needed.
+ membersToDelete.sort();
+ for (var range in range.nodesInList(members, membersToDelete)) {
+ builder.addDeletion(range);
+ }
+ }
+
+ /// Use the [builder] to delete the [field].
+ void _deleteField(DartFileEditBuilder builder, _Field field,
+ NodeList<ClassMember> members) {
+ var variableList = field.declarationList;
+ if (variableList.variables.length == 1) {
+ membersToDelete.add(members.indexOf(field.fieldDeclaration));
+ } else {
+ builder.addDeletion(
+ range.nodeInList(variableList.variables, field.declaration));
+ }
+ }
+
+ /// If the unnamed constructor is the only constructor, and if it has no
+ /// parameters other than potentially the index field, then remove it.
+ ConstructorDeclaration? _removeUnnamedConstructor() {
+ var members = classDeclaration.members;
+ var constructors = members.whereType<ConstructorDeclaration>().toList();
+ if (constructors.length != 1) {
+ return null;
+ }
+ var constructor = constructors[0];
+ var name = constructor.name?.name;
+ if (name != null && name != 'new') {
+ return null;
+ }
+ var parameters = constructor.parameters.parameters;
+ // If there's only one constructor, then there can only be one entry in the
+ // constructor map.
+ var parameterData = constructorMap?.entries.first.value;
+ // `parameterData` should only be `null` if there is no index field.
+ var updatedParameterCount =
+ parameters.length - (parameterData == null ? 0 : 1);
+ if (updatedParameterCount != 0) {
+ return null;
+ }
+ membersToDelete.add(members.indexOf(constructor));
+ return constructor;
+ }
+
+ /// Transform the used constructors by removing the parameter corresponding to
+ /// the index field.
+ void _transformConstructors(
+ DartFileEditBuilder builder, ConstructorDeclaration? removedConstructor) {
+ final constructorMap = this.constructorMap;
+ if (constructorMap == null) {
+ return;
+ }
+ for (var constructor in constructorMap.keys) {
+ if (constructor.declaration != removedConstructor) {
+ var parameterData = constructorMap[constructor];
+ if (parameterData != null) {
+ var parameters = constructor.declaration.parameters.parameters;
+ builder.addDeletion(
+ range.nodeInList(parameters, parameters[parameterData.index]));
+ }
+ }
+ }
+ }
+
+ /// If the given [node] can be converted into an enum, then return a
+ /// description of the conversion work to be done. Otherwise, return `null`.
+ static _EnumDescription? fromClass(ClassDeclaration node) {
+ // The class must be a concrete class.
+ var classElement = node.declaredElement;
+ if (classElement == null || classElement.isAbstract) {
+ return null;
+ }
+
+ // The class must be a subclass of Object, whether implicitly or explicitly.
+ var extendsClause = node.extendsClause;
+ if (extendsClause != null &&
+ extendsClause.superclass.type?.isDartCoreObject == false) {
+ return null;
+ }
+
+ // The class must either be private or must only have private constructors.
+ var constructors = _validateConstructors(node, classElement);
+ if (constructors == null) {
+ return null;
+ }
+
+ // The class must not override either `==` or `hashCode`.
+ if (!_validateMethods(node)) {
+ return null;
+ }
+
+ // There must be at least one static field that can be converted into an
+ // enum constant.
+ //
+ // The instance fields must all be final.
+ var fields = _validateFields(node, classElement);
+ if (fields == null || fields.fieldsToConvert.isEmpty) {
+ return null;
+ }
+
+ var visitor = _EnumVisitor(classElement, fields.fieldsToConvert);
+ try {
+ node.accept(visitor);
+ } on _CannotConvertException {
+ return null;
+ }
+
+ // Within the defining library,
+ // - there can't be any subclasses of the class to be converted,
+ // - there can't be any invocations of any constructor from that class.
+ try {
+ node.root.accept(_NonEnumVisitor(classElement));
+ } on _CannotConvertException {
+ return null;
+ }
+
+ var usedConstructors = _computeUsedConstructors(constructors, fields);
+ var constructorMap = _indexFieldData(usedConstructors, fields);
+ if (fields.indexField != null && constructorMap == null) {
+ return null;
+ }
+
+ var membersToDelete = <int>[];
+ return _EnumDescription(
+ classDeclaration: node,
+ constructorMap: constructorMap,
+ fields: fields,
+ membersToDelete: membersToDelete,
+ );
+ }
+
+ /// Return the subset of [constructors] that are invoked by the [fields] to be
+ /// converted.
+ static _Constructors _computeUsedConstructors(
+ _Constructors constructors, _Fields fields) {
+ var usedElements = <ConstructorElement>{};
+ for (var field in fields.fieldsToConvert) {
+ usedElements.add(field.constructorElement);
+ }
+ var usedConstructors = _Constructors();
+ for (var element in usedElements) {
+ var constructor = constructors.forElement(element);
+ if (constructor != null) {
+ usedConstructors.add(constructor);
+ }
+ }
+ return usedConstructors;
+ }
+
+ /// If the index field can be removed, return a map describing the changes
+ /// that need to be made to both the constructors and the invocations of those
+ /// constructors. Otherwise, return `null`.
+ static Map<_Constructor, _Parameter>? _indexFieldData(
+ _Constructors usedConstructors, _Fields fields) {
+ var indexField = fields.indexField;
+ if (indexField == null) {
+ return null;
+ }
+ // Ensure that the index field has a corresponding field formal initializer
+ // in each of the used constructors.
+ var constructorMap = <_Constructor, _Parameter>{};
+ for (var constructor in usedConstructors.constructors) {
+ var parameterData = _indexParameter(constructor, indexField);
+ if (parameterData == null) {
+ return null;
+ }
+ constructorMap[constructor] = parameterData;
+ }
+
+ var fieldsToConvert = fields.fieldsToConvert;
+ var values = <int>{};
+ for (var field in fieldsToConvert) {
+ var constructorElement = field.constructorElement;
+ var constructor = usedConstructors.forElement(constructorElement);
+ if (constructor == null) {
+ // We should never reach this point.
+ return null;
+ }
+ var parameterData = constructorMap[constructor];
+ if (parameterData == null) {
+ // We should never reach this point.
+ return null;
+ }
+ var arguments = field.instanceCreation.argumentList.arguments;
+ var argument = parameterData.getArgument(arguments);
+ if (argument is! IntegerLiteral) {
+ return null;
+ }
+ var value = argument.value;
+ if (value == null) {
+ return null;
+ }
+ if (!values.add(value)) {
+ // Duplicate value.
+ return null;
+ }
+ }
+ var sortedValues = values.toList()..sort();
+ if (sortedValues.length == fieldsToConvert.length &&
+ sortedValues.first == 0 &&
+ sortedValues.last == fieldsToConvert.length - 1) {
+ return constructorMap;
+ }
+ return null;
+ }
+
+ static _Parameter? _indexParameter(
+ _Constructor constructor, _Field? indexField) {
+ if (indexField == null) {
+ return null;
+ }
+ var parameters = constructor.declaration.parameters.parameters;
+ var indexFieldElement = indexField.element;
+ for (var i = 0; i < parameters.length; i++) {
+ var element = parameters[i].declaredElement;
+ if (element is FieldFormalParameterElement) {
+ if (element.field == indexFieldElement) {
+ if (element.isPositional) {
+ return _Parameter(i, element);
+ } else {
+ return _Parameter(i, element);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /// Return a representation of all of the constructors declared by the
+ /// [classDeclaration], or `null` if the class can't be converted.
+ ///
+ /// The [classElement] must be the element declared by the [classDeclaration].
+ static _Constructors? _validateConstructors(
+ ClassDeclaration classDeclaration, ClassElement classElement) {
+ var constructors = _Constructors();
+ for (var member in classDeclaration.members) {
+ if (member is ConstructorDeclaration) {
+ var constructor = member.declaredElement;
+ if (constructor is ConstructorElement) {
+ if (!classElement.isPrivate && !constructor.isPrivate) {
+ // Public constructor in public enum.
+ return null;
+ } else if (!constructor.isFactory && !constructor.isConst) {
+ // Non-const constructor.
+ return null;
+ }
+ constructors.add(_Constructor(member, constructor));
+ } else {
+ // Not resolved.
+ return null;
+ }
+ }
+ }
+ return constructors;
+ }
+
+ /// Return a representation of all of the constructors declared by the
+ /// [classDeclaration], or `null` if the class can't be converted.
+ ///
+ /// The [classElement] must be the element declared by the [classDeclaration].
+ static _Fields? _validateFields(
+ ClassDeclaration classDeclaration, ClassElement classElement) {
+ var potentialFieldsToConvert = <DartObject, List<_ConstantField>>{};
+ _Field? indexField;
+
+ for (var member in classDeclaration.members) {
+ if (member is FieldDeclaration) {
+ var fieldList = member.fields;
+ var fields = fieldList.variables;
+ if (member.isStatic) {
+ for (var field in fields) {
+ var fieldElement = field.declaredElement;
+ if (fieldElement is FieldElement) {
+ var fieldType = fieldElement.type;
+ // The field can be converted to be an enum constant if it
+ // - is a const field,
+ // - has a type equal to the type of the class, and
+ // - is initialized by an instance creation expression defined in this
+ // class.
+ if (fieldElement.isConst &&
+ fieldType is InterfaceType &&
+ fieldType.element == classElement) {
+ var initializer = field.initializer;
+ if (initializer is InstanceCreationExpression) {
+ var constructorElement =
+ initializer.constructorName.staticElement;
+ if (constructorElement != null &&
+ !constructorElement.isFactory &&
+ constructorElement.enclosingElement == classElement) {
+ var fieldValue = fieldElement.computeConstantValue();
+ if (fieldValue != null) {
+ if (fieldList.variables.length != 1) {
+ // Too many constants in the field declaration.
+ return null;
+ }
+ potentialFieldsToConvert
+ .putIfAbsent(fieldValue, () => [])
+ .add(_ConstantField(
+ fieldElement,
+ field,
+ fieldList,
+ member,
+ initializer,
+ constructorElement,
+ fieldValue.getField('index')?.toIntValue() ??
+ -1));
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ for (var field in fields) {
+ if (!field.isFinal) {
+ // Non-final instance field.
+ return null;
+ }
+ var fieldElement = field.declaredElement;
+ if (fieldElement is FieldElement) {
+ var fieldType = fieldElement.type;
+ if (fieldElement.name == 'index' && fieldType.isDartCoreInt) {
+ indexField = _Field(fieldElement, field, fieldList, member);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var fieldsToConvert = <_ConstantField>[];
+ for (var list in potentialFieldsToConvert.values) {
+ if (list.length == 1) {
+ fieldsToConvert.add(list[0]);
+ } else {
+ // TODO(brianwilkerson) We could potentially handle the case where
+ // there's only one non-deprecated field in the list. We'd need to
+ // change the return type for this method so that we could return two
+ // lists: the list of fields to convert and the list of fields whose
+ // initializer needs to be updated to refer to the constant.
+ return null;
+ }
+ }
+ return _Fields(fieldsToConvert, indexField);
+ }
+
+ /// Return `true` if the [classDeclaration] does not contain any methods that
+ /// prevent it from being converted.
+ static bool _validateMethods(ClassDeclaration classDeclaration) {
+ for (var member in classDeclaration.members) {
+ if (member is MethodDeclaration) {
+ if (member.name.name == '==' || member.name.name == 'hashCode') {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
+
+/// A visitor used to visit the class being converted. This visitor throws an
+/// exception if a constructor for the class is invoked anywhere other than the
+/// top-level expression of an initializer for one of the fields being converted.
+class _EnumVisitor extends _BaseVisitor {
+ /// The declarations of the fields that are to be converted.
+ final List<VariableDeclaration> fieldsToConvert;
+
+ /// A flag indicating whether we are currently visiting the children of a
+ /// field declaration that will be converted to be a constant.
+ bool inConstantDeclaration = false;
+
+ /// Initialize a newly created visitor to visit the class declaration
+ /// corresponding to the given [classElement].
+ _EnumVisitor(ClassElement classElement, List<_ConstantField> fieldsToConvert)
+ : fieldsToConvert =
+ fieldsToConvert.map((field) => field.declaration).toList(),
+ super(classElement);
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (!inConstantDeclaration) {
+ if (invokesGenerativeConstructor(node)) {
+ throw _CannotConvertException(
+ 'Constructor used outside constant initializer');
+ }
+ }
+ inConstantDeclaration = false;
+ super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ void visitVariableDeclaration(VariableDeclaration node) {
+ if (fieldsToConvert.contains(node)) {
+ inConstantDeclaration = true;
+ }
+ super.visitVariableDeclaration(node);
+ inConstantDeclaration = false;
+ }
+}
+
+/// A representation of a field of interest in the class being converted.
+class _Field {
+ /// The element representing the field.
+ final FieldElement element;
+
+ /// The declaration of the field.
+ final VariableDeclaration declaration;
+
+ /// The list containing the [declaration]
+ final VariableDeclarationList declarationList;
+
+ /// The field declaration containing the [declarationList].
+ final FieldDeclaration fieldDeclaration;
+
+ _Field(this.element, this.declaration, this.declarationList,
+ this.fieldDeclaration);
+
+ /// Return the name of the field.
+ String get name => declaration.name.name;
+}
+
+/// A representation of all the fields of interest in the class being converted.
+class _Fields {
+ /// The fields to be converted into enum constants.
+ List<_ConstantField> fieldsToConvert;
+
+ /// The index field, or `null` if there is no index field.
+ _Field? indexField;
+
+ _Fields(this.fieldsToConvert, this.indexField);
+}
+
+/// A visitor that visits everything in the library other than the class being
+/// converted. This visitor throws an exception if the class can't be converted
+/// because
+/// - there is a subclass of the class, or
+/// - there is an invocation of one of the constructors of the class.
+class _NonEnumVisitor extends _BaseVisitor {
+ /// Initialize a newly created visitor to visit everything except the class
+ /// declaration corresponding to the given [classElement].
+ _NonEnumVisitor(ClassElement classElement) : super(classElement);
+
+ @override
+ void visitClassDeclaration(ClassDeclaration node) {
+ var element = node.declaredElement;
+ if (element == null) {
+ throw _CannotConvertException('Unresolved');
+ }
+ if (element != classElement) {
+ if (element.supertype?.element == classElement) {
+ throw _CannotConvertException('Class is extended');
+ } else if (element.interfaces
+ .map((e) => e.element)
+ .contains(classElement)) {
+ throw _CannotConvertException('Class is implemented');
+ } else if (element.mixins.map((e) => e.element).contains(classElement)) {
+ // This case won't occur unless there's an error in the source code, but
+ // it's easier to check for the condition than it is to check for the
+ // diagnostic.
+ throw _CannotConvertException('Class is mixed in');
+ }
+ super.visitClassDeclaration(node);
+ }
+ }
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (invokesGenerativeConstructor(node)) {
+ throw _CannotConvertException(
+ 'Constructor used outside class being converted');
+ }
+ super.visitInstanceCreationExpression(node);
+ }
+}
+
+/// An object used to access information about a specific parameter, including
+/// its index in the parameter list as well as any associated argument in an
+/// argument list.
+class _Parameter {
+ /// The index of this parameter in the enclosing constructor's parameter list.
+ final int index;
+
+ /// The element associated with the parameter.
+ final ParameterElement element;
+
+ _Parameter(this.index, this.element);
+
+ /// Return the expression representing the argument associated with this
+ /// parameter, or `null` if there is no such argument.
+ Expression? getArgument(NodeList<Expression> arguments) {
+ return arguments.firstWhereOrNull(
+ (argument) => argument.staticParameterElement == element);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_list_literal.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_list_literal.dart
index 4e1c0eb..8d9d8d4 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_list_literal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_list_literal.dart
@@ -49,7 +49,7 @@
//
// Extract the information needed to build the edit.
//
- var constructorTypeArguments = creation.constructorName.type2.typeArguments;
+ var constructorTypeArguments = creation.constructorName.type.typeArguments;
//
// Build the edit.
//
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_map_literal.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_map_literal.dart
index 1704cda..cbc6f18 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_map_literal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_map_literal.dart
@@ -51,7 +51,7 @@
//
// Extract the information needed to build the edit.
//
- var constructorTypeArguments = creation.constructorName.type2.typeArguments;
+ var constructorTypeArguments = creation.constructorName.type.typeArguments;
//
// Build the edit.
//
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_package_import.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_package_import.dart
index 93e6460..7d3b150 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_package_import.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_package_import.dart
@@ -43,14 +43,14 @@
}
var importUri = uriSource.uri;
- if (importUri.scheme != 'package') {
+ if (!importUri.isScheme('package')) {
return;
}
// Don't offer to convert a 'package:' URI to itself.
try {
var uriContent = importDirective.uriContent;
- if (uriContent == null || Uri.parse(uriContent).scheme == 'package') {
+ if (uriContent == null || Uri.parse(uriContent).isScheme('package')) {
return;
}
} on FormatException {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart
new file mode 100644
index 0000000..0ccd810
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class ConvertToRawString extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.CONVERT_TO_RAW_STRING;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.CONVERT_TO_RAW_STRING_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var stringLiteral = node;
+ if ((stringLiteral is! SimpleStringLiteral) || stringLiteral.isRaw) {
+ return;
+ }
+
+ var literal = stringLiteral.literal;
+ var deletionOffsets = <int>[];
+ for (var offset = stringLiteral.contentsOffset;
+ offset < stringLiteral.contentsEnd;
+ offset++) {
+ var character = literal.lexeme[offset - literal.offset];
+ if (character == r'\') {
+ deletionOffsets.add(offset);
+ offset++;
+ }
+ }
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleInsertion(stringLiteral.offset, 'r');
+ for (var offset in deletionOffsets) {
+ builder.addDeletion(SourceRange(offset, 1));
+ }
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static ConvertToRawString newInstance() => ConvertToRawString();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_relative_import.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_relative_import.dart
index 7acecb5..49bedd1 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_relative_import.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_relative_import.dart
@@ -45,7 +45,7 @@
// Ignore if the uri is not a package: uri.
var sourceUri = resolvedResult.uri;
- if (sourceUri.scheme != 'package') {
+ if (!sourceUri.isScheme('package')) {
return;
}
@@ -61,7 +61,7 @@
}
// Ignore if import uri is not a package: uri.
- if (importUri.scheme != 'package') {
+ if (!importUri.isScheme('package')) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_set_literal.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_set_literal.dart
index 8ebe7c7..158a890 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_set_literal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_set_literal.dart
@@ -66,7 +66,7 @@
//
var name = creation.constructorName.name;
var constructorTypeArguments =
- creation.constructorName.type2.typeArguments;
+ creation.constructorName.type.typeArguments;
TypeArgumentList? elementTypeArguments;
SourceRange? elementsRange;
if (name == null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_initializing_parameter.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_initializing_parameter.dart
new file mode 100644
index 0000000..b26d127
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_initializing_parameter.dart
@@ -0,0 +1,360 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertToSuperInitializingParameter extends CorrectionProducer {
+ @override
+ AssistKind get assistKind =>
+ DartAssistKind.CONVERT_TO_SUPER_INITIALIZING_PARAMETER;
+
+ /// If the selected node is the name of either a simple formal parameter or a
+ /// function-typed formal parameter, either with or without a default value,
+ /// then return the formal parameter. Otherwise return `null`.
+ FormalParameter? get _formalParameter {
+ final node = this.node;
+ if (node is SimpleIdentifier) {
+ var parent = node.parent;
+ if (parent is NormalFormalParameter &&
+ (parent is SimpleFormalParameter ||
+ parent is FunctionTypedFormalParameter) &&
+ parent.identifier == node) {
+ var grandparent = parent.parent;
+ if (grandparent is DefaultFormalParameter) {
+ return grandparent;
+ }
+ return parent;
+ }
+ }
+ return null;
+ }
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ if (!libraryElement.featureSet.isEnabled(Feature.super_parameters)) {
+ // If the library doesn't support super_parameters then the change isn't
+ // appropriate.
+ return;
+ }
+ var parameter = _formalParameter;
+ if (parameter == null) {
+ // If the user hasn't selected a formal parameter to convert then there
+ // is nothing to change.
+ return;
+ }
+ var parameterList = parameter.parent;
+ if (parameterList is! FormalParameterList) {
+ // This is here to safely cast the parent. This branch should never be
+ // reached.
+ return;
+ }
+ var constructor = parameterList.parent;
+ if (constructor is! ConstructorDeclaration) {
+ // If this isn't a parameter in a constructor declaration then the change
+ // isn't appropriate.
+ return;
+ }
+ var superInvocation = _superInvocation(constructor);
+ if (superInvocation == null) {
+ // If there isn't an explicit invocation of the super constructor then the
+ // change isn't appropriate.
+ return;
+ }
+ var superConstructor = superInvocation.staticElement;
+ if (superConstructor == null) {
+ // If the super constructor wasn't resolved then we can't apply the
+ // change.
+ return;
+ }
+ var thisParameter = parameter.declaredElement;
+ if (thisParameter == null) {
+ return;
+ }
+
+ _ParameterData? data;
+ if (parameter.isPositional) {
+ data = _dataForPositionalParameter(
+ parameter, thisParameter, superConstructor, superInvocation);
+ } else if (parameter.isNamed) {
+ data = _dataForNamedParameter(
+ parameter, thisParameter, superConstructor, superInvocation);
+ }
+ if (data == null) {
+ return;
+ }
+
+ final parameterData = data;
+ await builder.addDartFileEdit(file, (builder) {
+ var typeToDelete = parameterData.typeToDelete;
+ if (typeToDelete == null) {
+ builder.addSimpleInsertion(parameter.identifier!.offset, 'super.');
+ } else {
+ var primaryRange = typeToDelete.primaryRange;
+ if (primaryRange == null) {
+ builder.addSimpleInsertion(parameter.identifier!.offset, 'super.');
+ } else {
+ builder.addSimpleReplacement(primaryRange, 'super.');
+ }
+ var parameterRange = typeToDelete.parameterRange;
+ if (parameterRange != null) {
+ builder.addDeletion(parameterRange);
+ }
+ }
+ parameterData.argumentUpdate.addDeletion(builder);
+ var defaultValueRange = parameterData.defaultValueRange;
+ if (defaultValueRange != null) {
+ builder.addDeletion(defaultValueRange);
+ }
+ });
+ }
+
+ ParameterElement? _correspondingNamedParameter(
+ ConstructorElement superConstructor, ParameterElement thisParameter) {
+ for (var superParameter in superConstructor.parameters) {
+ if (superParameter.isNamed && superParameter.name == thisParameter.name) {
+ return superParameter;
+ }
+ }
+ return null;
+ }
+
+ /// Return `true` if the named [parameter] can be converted into a super
+ /// initializing formal parameter.
+ _ParameterData? _dataForNamedParameter(
+ FormalParameter parameter,
+ ParameterElement thisParameter,
+ ConstructorElement superConstructor,
+ SuperConstructorInvocation superInvocation) {
+ var superParameter =
+ _correspondingNamedParameter(superConstructor, thisParameter);
+ if (superParameter == null) {
+ return null;
+ }
+ // Validate that the parameter is used in the super constructor invocation.
+ _ArgumentUpdate? argumentUpdate;
+ var arguments = superInvocation.argumentList.arguments;
+ for (var argument in arguments) {
+ if (argument is NamedExpression &&
+ argument.name.label.name == thisParameter.name) {
+ var expression = argument.expression;
+ if (expression is SimpleIdentifier &&
+ expression.staticElement == thisParameter) {
+ argumentUpdate = _RemoveArgument(argument);
+ break;
+ }
+ }
+ }
+ if (argumentUpdate == null) {
+ // If the selected parameter isn't being passed to the super constructor,
+ // then the change isn't appropriate.
+ return null;
+ } else if (arguments.length == 1) {
+ // If the selected parameter is the only parameter being passed to the
+ // super constructor then we no longer need to invoke the super
+ // constructor.
+ argumentUpdate = _RemoveInvocation(superInvocation);
+ }
+ // Compare the types.
+ var superType = superParameter.type;
+ var thisType = thisParameter.type;
+ if (!typeSystem.isAssignableTo(superType, thisType)) {
+ // If the type of the selected parameter can't be assigned to the super
+ // parameter, the the change isn't appropriate.
+ return null;
+ }
+ // Return the data.
+ return _ParameterData(
+ argumentUpdate: argumentUpdate,
+ defaultValueRange:
+ _defaultValueRange(parameter, superParameter, thisParameter),
+ typeToDelete: superType == thisType ? _type(parameter) : null,
+ );
+ }
+
+ /// Return `true` if the positional [parameter] can be converted into a super
+ /// initializing formal parameter.
+ _ParameterData? _dataForPositionalParameter(
+ FormalParameter parameter,
+ ParameterElement thisParameter,
+ ConstructorElement superConstructor,
+ SuperConstructorInvocation superInvocation) {
+ var positionalArguments = _positionalArguments(superInvocation);
+ if (positionalArguments.length != 1) {
+ // If there's more than one positional parameter then they would all need
+ // to be converted at the same time. If there's less than one, the the
+ // selected parameter isn't being passed to the super constructor.
+ return null;
+ }
+ var argument = positionalArguments[0];
+ if (argument is! SimpleIdentifier ||
+ argument.staticElement != parameter.declaredElement) {
+ // If the selected parameter isn't the one being passed to the super
+ // constructor then the change isn't appropriate.
+ return null;
+ }
+ var positionalParameters = superConstructor.parameters
+ .where((param) => param.isPositional)
+ .toList();
+ if (positionalParameters.isEmpty) {
+ return null;
+ }
+ var superParameter = positionalParameters[0];
+ _ArgumentUpdate? argumentUpdate;
+ if (superInvocation.argumentList.arguments.length == 1) {
+ argumentUpdate = _RemoveInvocation(superInvocation);
+ } else {
+ argumentUpdate = _RemoveArgument(argument);
+ }
+ // Compare the types.
+ var superType = superParameter.type;
+ var thisType = thisParameter.type;
+ if (!typeSystem.isSubtypeOf(thisType, superType)) {
+ // If the type of the selected parameter can't be assigned to the super
+ // parameter, the the change isn't appropriate.
+ return null;
+ }
+ // Return the data.
+ return _ParameterData(
+ argumentUpdate: argumentUpdate,
+ defaultValueRange:
+ _defaultValueRange(parameter, superParameter, thisParameter),
+ typeToDelete: superType == thisType ? _type(parameter) : null,
+ );
+ }
+
+ /// Return the range of the default value associated with the [parameter], or
+ /// `null` if the parameter doesn't have a default value or if the default
+ /// value is not the same as the default value in the super constructor.
+ SourceRange? _defaultValueRange(FormalParameter parameter,
+ ParameterElement superParameter, ParameterElement thisParameter) {
+ if (parameter is DefaultFormalParameter) {
+ var defaultValue = parameter.defaultValue;
+ if (defaultValue != null) {
+ var superDefault = superParameter.computeConstantValue();
+ var thisDefault = thisParameter.computeConstantValue();
+ if (superDefault != null && superDefault == thisDefault) {
+ return range.endEnd(parameter.identifier!, defaultValue);
+ }
+ }
+ }
+ return null;
+ }
+
+ List<Expression> _positionalArguments(SuperConstructorInvocation invocation) {
+ return invocation.argumentList.arguments
+ .where((argument) => argument is! NamedExpression)
+ .toList();
+ }
+
+ SuperConstructorInvocation? _superInvocation(
+ ConstructorDeclaration constructor) {
+ var initializers = constructor.initializers;
+ // Search all of the initializers in case the code is invalid, but start
+ // from the end because the code will usually be correct.
+ for (var i = initializers.length - 1; i >= 0; i--) {
+ var initializer = initializers[i];
+ if (initializer is SuperConstructorInvocation) {
+ return initializer;
+ }
+ }
+ return null;
+ }
+
+ _TypeData? _type(FormalParameter parameter) {
+ if (parameter is DefaultFormalParameter) {
+ return _type(parameter.parameter);
+ } else if (parameter is SimpleFormalParameter) {
+ var typeAnnotation = parameter.type;
+ if (typeAnnotation != null) {
+ return _TypeData(
+ primaryRange:
+ range.startStart(typeAnnotation, parameter.identifier!));
+ }
+ } else if (parameter is FunctionTypedFormalParameter) {
+ var returnType = parameter.returnType;
+ return _TypeData(
+ primaryRange: returnType != null
+ ? range.startStart(returnType, parameter.identifier)
+ : null,
+ parameterRange: range.node(parameter.parameters));
+ }
+ return null;
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+ static ConvertToSuperInitializingParameter newInstance() =>
+ ConvertToSuperInitializingParameter();
+}
+
+abstract class _ArgumentUpdate {
+ void addDeletion(DartFileEditBuilder builder);
+}
+
+class _ParameterData {
+ /// Information used to remove the argument from the super constructor
+ /// invocation.
+ final _ArgumentUpdate argumentUpdate;
+
+ /// Information about the type annotation that should be deleted, or `null` if
+ /// there is no type annotation to delete or if the type should not be
+ /// deleted.
+ final _TypeData? typeToDelete;
+
+ /// The range of the default value that is to be deleted, or `null` if there
+ /// is no default value, the default value isn't to be deleted.
+ final SourceRange? defaultValueRange;
+
+ /// Initialize a newly create data object.
+ _ParameterData(
+ {required this.argumentUpdate,
+ required this.typeToDelete,
+ required this.defaultValueRange});
+}
+
+class _RemoveArgument extends _ArgumentUpdate {
+ final Expression argument;
+
+ _RemoveArgument(this.argument);
+
+ @override
+ void addDeletion(DartFileEditBuilder builder) {
+ var argumentList = argument.parent as ArgumentList;
+ var index = argumentList.arguments.indexOf(argument);
+ builder.addDeletion(range.argumentRange(argumentList, index, index, true));
+ }
+}
+
+class _RemoveInvocation extends _ArgumentUpdate {
+ final SuperConstructorInvocation invocation;
+
+ _RemoveInvocation(this.invocation);
+
+ @override
+ void addDeletion(DartFileEditBuilder builder) {
+ var declaration = invocation.parent as ConstructorDeclaration;
+ var initializerList = declaration.initializers;
+ if (initializerList.length == 1) {
+ builder.addDeletion(range.endEnd(declaration.parameters, invocation));
+ } else {
+ builder.addDeletion(range.nodeInList(initializerList, invocation));
+ }
+ }
+}
+
+class _TypeData {
+ SourceRange? primaryRange;
+
+ SourceRange? parameterRange;
+
+ _TypeData({required this.primaryRange, this.parameterRange});
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_class.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_class.dart
index 9c01f35..9998f30 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_class.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_class.dart
@@ -48,10 +48,13 @@
} else {
return;
}
- if (!mightBeTypeIdentifier(nameNode)) {
+
+ final className = nameOfType(nameNode);
+ if (className == null) {
return;
}
- className = nameNode.name;
+ this.className = className;
+
// prepare environment
Element targetUnit;
var prefix = '';
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
index e476729..1e367b0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
@@ -63,7 +63,7 @@
}
// prepare target interface type
- var targetType = _constructorName.type2.type;
+ var targetType = _constructorName.type.type;
if (targetType is! InterfaceType) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_mixin.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_mixin.dart
index b9934c4..4769c4a 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_mixin.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_mixin.dart
@@ -49,7 +49,7 @@
} else {
return;
}
- if (!mightBeTypeIdentifier(nameNode)) {
+ if (nameOfType(nameNode) == null) {
return;
}
// prepare environment
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
index 34ecd3a..e57083d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
@@ -23,7 +23,7 @@
@override
Future<void> compute(ChangeBuilder builder) async {
var widgetClass = node.thisOrAncestorOfType<ClassDeclaration>();
- var superclass = widgetClass?.extendsClause?.superclass2;
+ var superclass = widgetClass?.extendsClause?.superclass;
if (widgetClass == null || superclass == null) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index 94a7a71..552f56e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -44,6 +44,16 @@
var widgetExpressions = <Expression>[];
if (analyzer.hasSelectedNodes) {
for (var selectedNode in analyzer.selectedNodes) {
+ // If the user has selected exactly a Widget constructor name (without
+ // the argument list), expand the selection.
+ //
+ // Text('foo')
+ // [^^^^]
+ var parent = selectedNode.parent;
+ if (selectedNode is ConstructorName &&
+ parent is InstanceCreationExpression) {
+ selectedNode = parent;
+ }
if (selectedNode is! Expression ||
!flutter.isWidgetExpression(selectedNode)) {
return;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/ignore_diagnostic.dart b/pkg/analysis_server/lib/src/services/correction/dart/ignore_diagnostic.dart
index 7b1fbde..a876fd0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/ignore_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/ignore_diagnostic.dart
@@ -25,9 +25,6 @@
String ignoreCommentType,
) async {
final lineInfo = unit.lineInfo;
- if (lineInfo == null) {
- return;
- }
await builder.addDartFileEdit(file, (builder) {
final offset = insertDesc.offset;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
index 98cc241..d39f695 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
@@ -104,10 +104,8 @@
targetNode = name;
}
}
- if (mightBeTypeIdentifier(targetNode)) {
- var typeName = (targetNode is SimpleIdentifier)
- ? targetNode.name
- : (targetNode as PrefixedIdentifier).prefix.name;
+ var typeName = nameOfType(targetNode);
+ if (typeName != null) {
yield* _importLibraryForElement(typeName, const [
ElementKind.CLASS,
ElementKind.ENUM,
@@ -124,17 +122,13 @@
}
@override
- bool mightBeTypeIdentifier(AstNode node) {
- if (super.mightBeTypeIdentifier(node)) {
- return true;
- }
+ String? nameOfType(AstNode node) {
if (node is PrefixedIdentifier) {
- var parent = node.parent;
- if (parent is NamedType) {
- return true;
+ if (node.parent is NamedType) {
+ return node.prefix.name;
}
}
- return false;
+ return super.nameOfType(node);
}
Stream<CorrectionProducer> _importExtensionInLibrary(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
index 297bf72..6f25968 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
@@ -38,6 +38,8 @@
await _forFunctionTypedFormalParameter(builder, node, parent);
} else if (node is SimpleIdentifier && parent is FieldFormalParameter) {
await _forFieldFormalParameter(builder, node, parent);
+ } else if (node is SimpleIdentifier && parent is SuperFormalParameter) {
+ await _forSuperFormalParameter(builder, node, parent);
} else if (node is Expression &&
parent is AssignmentExpression &&
parent.rightHandSide == node) {
@@ -164,6 +166,31 @@
});
}
+ /// Makes [parameter] nullable if possible.
+ Future<void> _forSuperFormalParameter(ChangeBuilder builder,
+ SimpleIdentifier name, SuperFormalParameter parameter) async {
+ if (parameter.parameters != null) {
+ // A function-typed field formal parameter.
+ if (parameter.question != null) {
+ return;
+ }
+ _variableName = parameter.identifier.name;
+ await builder.addDartFileEdit(file, (builder) {
+ // Add '?' after `)`.
+ builder.addSimpleInsertion(parameter.endToken.end, '?');
+ });
+ } else {
+ var type = parameter.type;
+ if (type == null || !_typeCanBeMadeNullable(type)) {
+ return;
+ }
+ _variableName = parameter.identifier.name;
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleInsertion(type.end, '?');
+ });
+ }
+ }
+
Future<void> _forVariableDeclaration(ChangeBuilder builder, Expression node,
VariableDeclaration parent) async {
var declarationList = parent.parent;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/move_type_arguments_to_class.dart b/pkg/analysis_server/lib/src/services/correction/dart/move_type_arguments_to_class.dart
index 417a2cf..82676c6 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/move_type_arguments_to_class.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/move_type_arguments_to_class.dart
@@ -27,7 +27,7 @@
return;
}
- var namedType = creation.constructorName.type2;
+ var namedType = creation.constructorName.type;
if (namedType.typeArguments != null) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
new file mode 100644
index 0000000..918c2a7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveLeadingUnderscore extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.REMOVE_LEADING_UNDERSCORE_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var identifier = node;
+ if (identifier is! SimpleIdentifier) {
+ return;
+ }
+
+ var name = identifier.name;
+ if (name.length < 2) {
+ return;
+ }
+
+ var newName = name.substring(1);
+
+ // Find references to the identifier.
+ List<SimpleIdentifier>? references;
+ var element = identifier.staticElement;
+ if (element is LocalVariableElement) {
+ var root = node.thisOrAncestorOfType<Block>();
+ if (root != null) {
+ references = findLocalElementReferences(root, element);
+ }
+ } else if (element is ParameterElement) {
+ if (!element.isNamed) {
+ var root = node
+ .thisOrAncestorMatching((node) =>
+ node.parent is FunctionDeclaration ||
+ node.parent is MethodDeclaration)
+ ?.parent;
+ if (root != null) {
+ references = findLocalElementReferences(root, element);
+ }
+ }
+ } else if (element is PrefixElement) {
+ var root = node.thisOrAncestorOfType<CompilationUnit>();
+ if (root != null) {
+ references = findPrefixElementReferences(root, element);
+ }
+ }
+ if (references == null) {
+ return;
+ }
+
+ // Compute the change.
+ var references_final = references;
+ await builder.addDartFileEdit(file, (builder) {
+ for (var reference in references_final) {
+ builder.addSimpleReplacement(range.node(reference), newName);
+ }
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static RemoveLeadingUnderscore newInstance() => RemoveLeadingUnderscore();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
new file mode 100644
index 0000000..08c09db
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryLate extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_LATE_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final declaration = node;
+ if (declaration is! VariableDeclaration) {
+ return;
+ }
+ final declarationList = declaration.parent;
+ if (declarationList is! VariableDeclarationList) {
+ return;
+ }
+
+ if (declarationList.variables.any((v) => v.initializer == null)) {
+ // At least one variable declared in the same list does _not_ have an
+ // initializer; removing `late` may make such a variable declaration
+ // invalid.
+ return;
+ }
+
+ final lateToken = declarationList.lateKeyword;
+ if (lateToken == null) {
+ return;
+ }
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addDeletion(range.startStart(lateToken, lateToken.next!));
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static RemoveUnnecessaryLate newInstance() => RemoveUnnecessaryLate();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart b/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart
index c42e69b..289767c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart
@@ -55,9 +55,11 @@
}
} else if (element is ParameterElement) {
if (!element.isNamed) {
- var root = node.thisOrAncestorMatching((node) =>
- node.parent is ClassOrMixinDeclaration ||
- node.parent is CompilationUnit);
+ var root = node
+ .thisOrAncestorMatching((node) =>
+ node.parent is FunctionDeclaration ||
+ node.parent is MethodDeclaration)
+ ?.parent;
if (root != null) {
references = findLocalElementReferences(root, element);
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_null_check_with_cast.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_check_with_cast.dart
new file mode 100644
index 0000000..8f2faf8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_check_with_cast.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ReplaceNullCheckWithCast extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REPLACE_NULL_CHECK_WITH_CAST;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.REPLACE_NULL_CHECK_WITH_CAST_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final node = this.node;
+ if (node is! PostfixExpression) {
+ return;
+ }
+ var operand = node.operand;
+ var operator = node.operator;
+ var operandType = operand.staticType;
+ if (operandType is! TypeParameterType) {
+ return;
+ }
+ // It is possible that there are cases of precedence and syntax which would
+ // require additional parentheses, for example converting `p!.hashCode` to
+ // `(p as T).hashCode`. However no such cases are known to trigger the lint
+ // rule.
+ // TODO(srawlins): Follow up on
+ // https://github.com/dart-lang/linter/issues/3256.
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.token(operator),
+ ' as ${operandType.getDisplayString(withNullability: false)}');
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static ReplaceNullCheckWithCast newInstance() => ReplaceNullCheckWithCast();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart
index 9d3b8dd..dfa48e4 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart
@@ -13,15 +13,24 @@
String _typeArgument = '';
@override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
List<Object>? get fixArguments => [_typeArgument];
@override
FixKind get fixKind => DartFixKind.REPLACE_RETURN_TYPE_FUTURE;
@override
+ FixKind get multiFixKind => DartFixKind.REPLACE_RETURN_TYPE_FUTURE_MULTI;
+
+ @override
Future<void> compute(ChangeBuilder builder) async {
// prepare the existing type
- var typeAnnotation = node.thisOrAncestorOfType<TypeAnnotation>();
+ var typeAnnotation = _getTypeAnnotation(node);
if (typeAnnotation == null) {
return;
}
@@ -34,4 +43,13 @@
/// Return an instance of this class. Used as a tear-off in `FixProcessor`.
static ReplaceReturnTypeFuture newInstance() => ReplaceReturnTypeFuture();
+
+ static TypeAnnotation? _getTypeAnnotation(AstNode node) {
+ var function = node.thisOrAncestorOfType<FunctionDeclaration>();
+ if (function != null) {
+ return function.returnType;
+ }
+ var method = node.thisOrAncestorOfType<MethodDeclaration>();
+ return method?.returnType;
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart
index a5f687c..b1236c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart
@@ -67,9 +67,9 @@
}
}
} else if (initializer is InstanceCreationExpression) {
- if (initializer.constructorName.type2.typeArguments == null) {
+ if (initializer.constructorName.type.typeArguments == null) {
typeArgumentsText = utils.getNodeText(typeArguments);
- typeArgumentsOffset = initializer.constructorName.type2.end;
+ typeArgumentsOffset = initializer.constructorName.type.end;
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart b/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart
new file mode 100644
index 0000000..3eb4641
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class SortConstructorFirst extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.SORT_CONSTRUCTOR_FIRST;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.SORT_CONSTRUCTOR_FIRST_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var constructor = coveredNode?.parent;
+ var clazz = constructor?.parent;
+ if (clazz is! ClassDeclaration || constructor is! ConstructorDeclaration) {
+ return;
+ }
+
+ await builder.addDartFileEdit(file, (builder) {
+ var deletionRange = range.endEnd(
+ constructor.beginToken.previous!,
+ constructor.endToken,
+ );
+
+ builder.addDeletion(deletionRange);
+ builder.addSimpleInsertion(
+ clazz.leftBracket.end,
+ utils.getRangeText(deletionRange),
+ );
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static SortConstructorFirst newInstance() => SortConstructorFirst();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/sort_unnamed_constructor_first.dart b/pkg/analysis_server/lib/src/services/correction/dart/sort_unnamed_constructor_first.dart
new file mode 100644
index 0000000..bfbcb2a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/sort_unnamed_constructor_first.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:collection/collection.dart';
+
+class SortUnnamedConstructorFirst extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.SORT_UNNAMED_CONSTRUCTOR_FIRST;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.SORT_UNNAMED_CONSTRUCTOR_FIRST_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var clazz = coveredNode?.parent?.parent;
+ if (clazz is! ClassDeclaration) return;
+
+ final firstConstructor = clazz.childEntities
+ .firstWhereOrNull((child) => child is ConstructorDeclaration)
+ as ConstructorDeclaration?;
+ if (firstConstructor == null ||
+ firstConstructor.name == null ||
+ firstConstructor.name?.name == 'new') return;
+
+ final unnamedConstructor = clazz.childEntities.firstWhereOrNull(
+ (child) => child is ConstructorDeclaration && child.name == null)
+ as ConstructorDeclaration?;
+ if (unnamedConstructor == null) return;
+
+ await builder.addDartFileEdit(file, (builder) {
+ var deletionRange = range.endEnd(
+ unnamedConstructor.beginToken.previous!,
+ unnamedConstructor.endToken,
+ );
+
+ builder.addDeletion(deletionRange);
+ builder.addSimpleInsertion(
+ firstConstructor.beginToken.previous!.end,
+ utils.getRangeText(deletionRange),
+ );
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static SortUnnamedConstructorFirst newInstance() =>
+ SortUnnamedConstructorFirst();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt b/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt
deleted file mode 100644
index badc576..0000000
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt
+++ /dev/null
@@ -1,1079 +0,0 @@
-This file contains, for each analysis code and lint name:
-* "has fix(es)", if the code has fix(es)
-* "needs evaluation", if the code has not been evaluated in terms of fixes
-* "needs fix", if the code needs a fix, with a possible issue link
-* "fixes infeasible", if it has been deemed infeasible to write a fix for this code
-
-TODO(srawlins): Add lint names not found in LintNames?
-
-Stats:
-* 808 "needs evaluation"
-* 253 "has fix(es)"
-
-AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR: needs evaluation
-AnalysisOptionsErrorCode.PARSE_ERROR: needs evaluation
-AnalysisOptionsHintCode.PREVIEW_DART_2_SETTING_DEPRECATED: needs evaluation
-AnalysisOptionsHintCode.STRONG_MODE_SETTING_DEPRECATED: needs evaluation
-AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED: needs evaluation
-AnalysisOptionsWarningCode.ANALYSIS_OPTION_DEPRECATED: needs evaluation
-AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND: needs evaluation
-AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING: needs evaluation
-AnalysisOptionsWarningCode.INVALID_OPTION: needs evaluation
-AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT: needs evaluation
-AnalysisOptionsWarningCode.SPEC_MODE_REMOVED: needs evaluation
-AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE: needs evaluation
-AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE: needs evaluation
-AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES: needs evaluation
-AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES: needs evaluation
-AnalysisOptionsWarningCode.UNSUPPORTED_VALUE: needs evaluation
-CompileTimeErrorCode.ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER: needs evaluation
-CompileTimeErrorCode.ABSTRACT_FIELD_INITIALIZER: needs evaluation
-CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE: needs evaluation
-CompileTimeErrorCode.AMBIGUOUS_EXPORT: needs evaluation
-CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS: needs evaluation
-CompileTimeErrorCode.AMBIGUOUS_IMPORT: needs evaluation
-CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH: needs evaluation
-CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER: needs evaluation
-CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.ASSIGNMENT_TO_CONST: needs evaluation
-CompileTimeErrorCode.ASSIGNMENT_TO_FINAL: has fix(es)
-CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL: has fix(es)
-CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER: needs evaluation
-CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION: needs evaluation
-CompileTimeErrorCode.ASSIGNMENT_TO_METHOD: needs evaluation
-CompileTimeErrorCode.ASSIGNMENT_TO_TYPE: needs evaluation
-CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT: has fix(es)
-CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER: needs evaluation
-CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT: has fix(es)
-CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY: has fix(es)
-CompileTimeErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME: needs evaluation
-CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME: needs evaluation
-CompileTimeErrorCode.CASE_BLOCK_NOT_TERMINATED: needs evaluation
-CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS: needs evaluation
-CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE: needs evaluation
-CompileTimeErrorCode.CAST_TO_NON_TYPE: has fix(es)
-CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_INSTANCE_MEMBER: needs evaluation
-CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_STATIC_MEMBER: needs evaluation
-CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER: needs evaluation
-CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER: has fix(es)
-CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD: needs evaluation
-CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER: needs evaluation
-CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD: needs evaluation
-CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER: needs evaluation
-CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD: needs evaluation
-CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES: needs evaluation
-CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD: needs evaluation
-CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN: needs evaluation
-CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER: needs evaluation
-CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD: needs evaluation
-CompileTimeErrorCode.CONST_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_INT: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_NUM: needs evaluation
-CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE: needs evaluation
-CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE: has fix(es)
-CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.CONST_INSTANCE_FIELD: has fix(es)
-CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS: needs evaluation
-CompileTimeErrorCode.CONST_NOT_INITIALIZED: needs evaluation
-CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS: needs evaluation
-CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET: needs evaluation
-CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP: needs evaluation
-CompileTimeErrorCode.CONST_WITH_NON_CONST: has fix(es)
-CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT: needs evaluation
-CompileTimeErrorCode.CONST_WITH_NON_TYPE: has fix(es)
-CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS: needs evaluation
-CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF: needs evaluation
-CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF: needs evaluation
-CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: needs evaluation
-CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH: needs evaluation
-CompileTimeErrorCode.COULD_NOT_INFER: needs evaluation
-CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR: has fix(es)
-CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER: needs evaluation
-CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION: needs evaluation
-CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE: needs evaluation
-CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION: needs evaluation
-CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT: needs evaluation
-CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME: needs evaluation
-CompileTimeErrorCode.DUPLICATE_DEFINITION: needs evaluation
-CompileTimeErrorCode.DUPLICATE_FIELD_FORMAL_PARAMETER: needs evaluation
-CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT: needs evaluation
-CompileTimeErrorCode.DUPLICATE_PART: needs evaluation
-CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING: needs evaluation
-CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET: needs evaluation
-CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP: needs evaluation
-CompileTimeErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS: needs evaluation
-CompileTimeErrorCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS: needs evaluation
-CompileTimeErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS: needs evaluation
-CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY: needs evaluation
-CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL: needs evaluation
-CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY: needs evaluation
-CompileTimeErrorCode.EXPRESSION_IN_MAP: needs evaluation
-CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS: needs evaluation
-CompileTimeErrorCode.EXTENDS_NON_CLASS: has fix(es)
-CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.EXTENSION_AS_EXPRESSION: needs evaluation
-CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE: needs evaluation
-CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT: needs evaluation
-CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER: has fix(es)
-CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE: needs evaluation
-CompileTimeErrorCode.EXTENSION_OVERRIDE_WITHOUT_ACCESS: needs evaluation
-CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER: needs evaluation
-CompileTimeErrorCode.EXTERNAL_FIELD_INITIALIZER: needs evaluation
-CompileTimeErrorCode.EXTERNAL_VARIABLE_INITIALIZER: needs evaluation
-CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS: has fix(es)
-CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED: has fix(es)
-CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED: has fix(es)
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1: has fix(es)
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2: has fix(es)
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS: has fix(es)
-CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE: needs evaluation
-CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE: needs evaluation
-CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE: needs evaluation
-CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND: needs evaluation
-CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT: needs evaluation
-CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC: needs evaluation
-CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES: needs evaluation
-CompileTimeErrorCode.GETTER_NOT_SUBTYPE_SETTER_TYPES: needs evaluation
-CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE: has fix(es)
-CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE: has fix(es)
-CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE: has fix(es)
-CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS: needs evaluation
-CompileTimeErrorCode.IMPLEMENTS_NON_CLASS: has fix(es)
-CompileTimeErrorCode.IMPLEMENTS_REPEATED: needs evaluation
-CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS: needs evaluation
-CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER: needs evaluation
-CompileTimeErrorCode.IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT: has fix(es)
-CompileTimeErrorCode.IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS: has fix(es)
-CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY: needs evaluation
-CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY: needs evaluation
-CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES: needs evaluation
-CompileTimeErrorCode.INCONSISTENT_INHERITANCE: needs evaluation
-CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD: needs evaluation
-CompileTimeErrorCode.INCONSISTENT_LANGUAGE_VERSION_OVERRIDE: needs evaluation
-CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD: needs evaluation
-CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD: needs evaluation
-CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD: has fix(es)
-CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER: has fix(es)
-CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION: needs evaluation
-CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY: needs evaluation
-CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC: needs evaluation
-CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS: needs evaluation
-CompileTimeErrorCode.INSTANTIATE_ENUM: needs evaluation
-CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE: has fix(es)
-CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE: needs evaluation
-CompileTimeErrorCode.INVALID_ANNOTATION: has fix(es)
-CompileTimeErrorCode.INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.INVALID_ASSIGNMENT: has fix(es)
-CompileTimeErrorCode.INVALID_CAST_FUNCTION: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_FUNCTION_EXPR: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_LITERAL: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_LITERAL_LIST: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_LITERAL_MAP: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_LITERAL_SET: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_METHOD: needs evaluation
-CompileTimeErrorCode.INVALID_CAST_NEW_EXPR: needs evaluation
-CompileTimeErrorCode.INVALID_CONSTANT: needs evaluation
-CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT: needs evaluation
-CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS: needs evaluation
-CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE: needs evaluation
-CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE: needs evaluation
-CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER: needs evaluation
-CompileTimeErrorCode.INVALID_OVERRIDE: has fix(es)
-CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS: needs evaluation
-CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION: needs evaluation
-CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST: needs evaluation
-CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP: needs evaluation
-CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET: needs evaluation
-CompileTimeErrorCode.INVALID_URI: needs evaluation
-CompileTimeErrorCode.INVALID_USE_OF_COVARIANT: needs evaluation
-CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE: needs evaluation
-CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL: needs evaluation
-CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION: needs evaluation
-CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION: has fix(es)
-CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE: needs evaluation
-CompileTimeErrorCode.LABEL_UNDEFINED: needs evaluation
-CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED: needs evaluation
-CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE: needs evaluation
-CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS: needs evaluation
-CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS: needs evaluation
-CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION: needs evaluation
-CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP: needs evaluation
-CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL: needs evaluation
-CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL: needs evaluation
-CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL: needs evaluation
-CompileTimeErrorCode.MISSING_DART_LIBRARY: needs evaluation
-CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER: has fix(es)
-CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION: has fix(es)
-CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT: has fix(es)
-CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE: needs evaluation
-CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER: needs evaluation
-CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE: has fix(es)
-CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.MIXIN_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT: needs evaluation
-CompileTimeErrorCode.MIXIN_INSTANTIATE: needs evaluation
-CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS: needs evaluation
-CompileTimeErrorCode.MIXIN_OF_NON_CLASS: has fix(es)
-CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS: needs evaluation
-CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE: needs evaluation
-CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS: needs evaluation
-CompileTimeErrorCode.MIXINS_SUPER_CLASS: needs evaluation
-CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS: needs evaluation
-CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS: needs evaluation
-CompileTimeErrorCode.NEW_WITH_NON_TYPE: has fix(es)
-CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR: has fix(es)
-CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: has fix(es)
-CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS: needs evaluation
-CompileTimeErrorCode.NO_COMBINED_SUPER_SIGNATURE: needs evaluation
-CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT: has fix(es)
-CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT: has fix(es)
-CompileTimeErrorCode.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS: needs evaluation
-CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS: has fix(es)
-CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR: has fix(es)
-CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE: has fix(es)
-CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE: has fix(es)
-CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO: has fix(es)
-CompileTimeErrorCode.NON_BOOL_CONDITION: has fix(es)
-CompileTimeErrorCode.NON_BOOL_EXPRESSION: needs evaluation
-CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION: needs evaluation
-CompileTimeErrorCode.NON_BOOL_OPERAND: needs evaluation
-CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_MAP_KEY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT: needs evaluation
-CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.NON_SYNC_FACTORY: needs evaluation
-CompileTimeErrorCode.NON_TYPE_AS_TYPE_ARGUMENT: has fix(es)
-CompileTimeErrorCode.NON_TYPE_IN_CATCH_CLAUSE: has fix(es)
-CompileTimeErrorCode.NON_VOID_RETURN_FOR_OPERATOR: needs evaluation
-CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER: needs evaluation
-CompileTimeErrorCode.NOT_A_TYPE: has fix(es)
-CompileTimeErrorCode.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE: needs evaluation
-CompileTimeErrorCode.NOT_BINARY_OPERATOR: needs evaluation
-CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS: has fix(es)
-CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD: has fix(es)
-CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_VARIABLE: needs evaluation
-CompileTimeErrorCode.NOT_INSTANTIATED_BOUND: needs evaluation
-CompileTimeErrorCode.NOT_ITERABLE_SPREAD: needs evaluation
-CompileTimeErrorCode.NOT_MAP_SPREAD: needs evaluation
-CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD: needs evaluation
-CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE: has fix(es)
-CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE: has fix(es)
-CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE: has fix(es)
-CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE: has fix(es)
-CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS: fix infeasible
-CompileTimeErrorCode.ON_REPEATED: needs evaluation
-CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR: needs evaluation
-CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY: needs evaluation
-CompileTimeErrorCode.PART_OF_NON_PART: needs evaluation
-CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY: needs evaluation
-CompileTimeErrorCode.POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT: needs evaluation
-CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER: needs evaluation
-CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT: needs evaluation
-CompileTimeErrorCode.PREFIX_SHADOWED_BY_LOCAL_DECLARATION: needs evaluation
-CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION: needs evaluation
-CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER: needs evaluation
-CompileTimeErrorCode.PRIVATE_SETTER: needs evaluation
-CompileTimeErrorCode.READ_POTENTIALLY_UNASSIGNED_FINAL: needs evaluation
-CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT: needs evaluation
-CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT: needs evaluation
-CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT: needs evaluation
-CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE: needs evaluation
-CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS: needs evaluation
-CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS: needs evaluation
-CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_ON: needs evaluation
-CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH: needs evaluation
-CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_INVALID_FUNCTION_TYPE: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_INVALID_RETURN_TYPE: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_NON_CLASS: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
-CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION: needs evaluation
-CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH: needs evaluation
-CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.RETURN_IN_GENERATOR: needs evaluation
-CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE: needs evaluation
-CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION: has fix(es)
-CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_METHOD: has fix(es)
-CompileTimeErrorCode.RETURN_WITHOUT_VALUE: needs evaluation
-CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.SHARED_DEFERRED_PREFIX: needs evaluation
-CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY: needs evaluation
-CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER: needs evaluation
-CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED: needs evaluation
-CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED: needs evaluation
-CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL: needs evaluation
-CompileTimeErrorCode.SUPER_IN_EXTENSION: needs evaluation
-CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT: needs evaluation
-CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR: needs evaluation
-CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT: needs evaluation
-CompileTimeErrorCode.SUPER_INVOCATION_NOT_LAST: needs evaluation
-CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY: has fix(es)
-CompileTimeErrorCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE: needs evaluation
-CompileTimeErrorCode.TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS: needs evaluation
-CompileTimeErrorCode.THROW_OF_INVALID_TYPE: needs evaluation
-CompileTimeErrorCode.TOP_LEVEL_CYCLE: needs evaluation
-CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF: needs evaluation
-CompileTimeErrorCode.TYPE_ANNOTATION_DEFERRED_CLASS: needs evaluation
-CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS: needs evaluation
-CompileTimeErrorCode.TYPE_PARAMETER_REFERENCED_BY_STATIC: needs evaluation
-CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND: needs evaluation
-CompileTimeErrorCode.TYPE_TEST_WITH_NON_TYPE: needs evaluation
-CompileTimeErrorCode.TYPE_TEST_WITH_UNDEFINED_NAME: has fix(es)
-CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
-CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
-CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
-CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE: has fix(es)
-CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION: has fix(es)
-CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR: has fix(es)
-CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD: has fix(es)
-CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH: has fix(es)
-CompileTimeErrorCode.UNDEFINED_ANNOTATION: has fix(es)
-CompileTimeErrorCode.UNDEFINED_CLASS: has fix(es)
-CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN: has fix(es)
-CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER: needs evaluation
-CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT: has fix(es)
-CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT: needs evaluation
-CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER: has fix(es)
-CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD: has fix(es)
-CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR: needs evaluation
-CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER: has fix(es)
-CompileTimeErrorCode.UNDEFINED_FUNCTION: has fix(es)
-CompileTimeErrorCode.UNDEFINED_GETTER: has_fix(es)
-CompileTimeErrorCode.UNDEFINED_GETTER_ON_FUNCTION_TYPE: needs evaluation
-CompileTimeErrorCode.UNDEFINED_IDENTIFIER: has fix(es)
-CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT: has fix(es)
-CompileTimeErrorCode.UNDEFINED_METHOD: has fix(es)
-CompileTimeErrorCode.UNDEFINED_METHOD_ON_FUNCTION_TYPE: needs evaluation
-CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER: has fix(es)
-CompileTimeErrorCode.UNDEFINED_OPERATOR: has fix(es)
-CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME: has fix(es)
-CompileTimeErrorCode.UNDEFINED_SETTER: has fix(es)
-CompileTimeErrorCode.UNDEFINED_SETTER_ON_FUNCTION_TYPE: needs evaluation
-CompileTimeErrorCode.UNDEFINED_SUPER_GETTER: needs evaluation
-CompileTimeErrorCode.UNDEFINED_SUPER_METHOD: needs evaluation
-CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR: needs evaluation
-CompileTimeErrorCode.UNDEFINED_SUPER_SETTER: needs evaluation
-CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER: has fix(es)
-CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE: has fix(es)
-CompileTimeErrorCode.URI_DOES_NOT_EXIST: has fix(es)
-CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED: needs evaluation
-CompileTimeErrorCode.URI_WITH_INTERPOLATION: needs evaluation
-CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION: needs evaluation
-CompileTimeErrorCode.USE_OF_VOID_RESULT: needs evaluation
-CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH: needs evaluation
-CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS: has fix(es)
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR: has fix(es)
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION: has fix(es)
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION: needs evaluation
-CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD: has fix(es)
-CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE: needs evaluation
-CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION: needs evaluation
-CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR: needs evaluation
-CompileTimeErrorCode.YIELD_IN_NON_GENERATOR: needs evaluation
-CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE: needs evaluation
-CompileTimeErrorCode.YIELD_OF_INVALID_TYPE: has fix(es)
-FfiCode.ABI_SPECIFIC_INTEGER_INVALID: needs evaluation
-FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_EXTRA: needs evaluation
-FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_MISSING: needs evaluation
-FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_UNSUPPORTED: needs evaluation
-FfiCode.ANNOTATION_ON_POINTER_FIELD: needs evaluation
-FfiCode.ARGUMENT_MUST_BE_A_CONSTANT: needs evaluation
-FfiCode.CREATION_OF_STRUCT_OR_UNION: needs evaluation
-FfiCode.EMPTY_STRUCT: needs evaluation
-FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
-FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY: needs evaluation
-FfiCode.FFI_NATIVE_MUST_BE_EXTERNAL: needs evaluation
- FfiCode
- .FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER: needs evaluation
-FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS: needs evaluation
-FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER: needs evaluation
-FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER: needs evaluation
-FfiCode.FIELD_INITIALIZER_IN_STRUCT: needs evaluation
-FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT: needs evaluation
-FfiCode.GENERIC_STRUCT_SUBCLASS: needs evaluation
-FfiCode.INVALID_EXCEPTION_VALUE: needs evaluation
-FfiCode.INVALID_FIELD_TYPE_IN_STRUCT: needs evaluation
-FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE: needs evaluation
-FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE: needs evaluation
-FfiCode.MISMATCHED_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
-FfiCode.MISSING_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
-FfiCode.MISSING_EXCEPTION_VALUE: needs evaluation
-FfiCode.MISSING_FIELD_TYPE_IN_STRUCT: needs evaluation
-FfiCode.MISSING_SIZE_ANNOTATION_CARRAY: needs evaluation
-FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE: needs evaluation
-FfiCode.MUST_BE_A_SUBTYPE: needs evaluation
-FfiCode.NON_CONSTANT_TYPE_ARGUMENT: needs evaluation
-FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER: needs evaluation
-FfiCode.NON_POSITIVE_ARRAY_DIMENSION: needs evaluation
-FfiCode.NON_SIZED_TYPE_ARGUMENT: needs evaluation
-FfiCode.PACKED_ANNOTATION: needs evaluation
-FfiCode.PACKED_ANNOTATION_ALIGNMENT: needs evaluation
-FfiCode.PACKED_NESTING_NON_PACKED: needs evaluation
-FfiCode.SIZE_ANNOTATION_DIMENSIONS: needs evaluation
-FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS: needs evaluation
-FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS: needs evaluation
-FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH: needs evaluation
-FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS: needs evaluation
-FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS: needs evaluation
-FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH: needs evaluation
-HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER: has fix(es)
-HintCode.ASSIGNMENT_OF_DO_NOT_STORE: needs evaluation
-HintCode.BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE: has fix(es)
-HintCode.CAN_BE_NULL_AFTER_NULL_AWARE: has fix(es)
-HintCode.DEAD_CODE: has fix(es)
-HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH: has fix(es)
-HintCode.DEAD_CODE_ON_CATCH_SUBTYPE: has fix(es)
-HintCode.DEPRECATED_EXTENDS_FUNCTION: needs evaluation
-HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION: needs evaluation
-HintCode.DEPRECATED_IMPLEMENTS_FUNCTION: needs evaluation
-HintCode.DEPRECATED_MEMBER_USE: has fix(es)
-HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE: needs evaluation
-HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE: needs evaluation
-HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: has fix(es)
-HintCode.DEPRECATED_MIXIN_FUNCTION: needs evaluation
-HintCode.DEPRECATED_NEW_IN_COMMENT_REFERENCE: has fix(es)
-HintCode.DIVISION_OPTIMIZATION: has fix(es)
-HintCode.DUPLICATE_HIDDEN_NAME: has fix(es)
-HintCode.DUPLICATE_IGNORE: needs evaluation
-HintCode.DUPLICATE_IMPORT: has fix(es)
-HintCode.DUPLICATE_SHOWN_NAME: has fix(es)
-HintCode.EQUAL_ELEMENTS_IN_SET: needs evaluation
-HintCode.EQUAL_KEYS_IN_MAP: needs evaluation
-HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE: needs evaluation
-HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE: needs evaluation
-HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION: needs evaluation
-HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_FUNCTION_INVOCATION: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_GENERIC_INVOCATION: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE: needs evaluation
-HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER: needs evaluation
-HintCode.INVALID_ANNOTATION_TARGET: needs evaluation
-HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT: needs evaluation
-HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY: needs evaluation
-HintCode.INVALID_FACTORY_ANNOTATION: has fix(es)
-HintCode.INVALID_FACTORY_METHOD_DECL: needs evaluation
-HintCode.INVALID_FACTORY_METHOD_IMPL: needs evaluation
-HintCode.INVALID_IMMUTABLE_ANNOTATION: has fix(es)
-HintCode.INVALID_INTERNAL_ANNOTATION: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS: needs evaluation
-HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES: needs evaluation
-HintCode.INVALID_LITERAL_ANNOTATION: has fix(es)
-HintCode.INVALID_NON_VIRTUAL_ANNOTATION: needs evaluation
-HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER: needs evaluation
-HintCode.INVALID_REQUIRED_NAMED_PARAM: has fix(es)
-HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM: has fix(es)
-HintCode.INVALID_REQUIRED_POSITIONAL_PARAM: has fix(es)
-HintCode.INVALID_SEALED_ANNOTATION: has fix(es)
-HintCode.INVALID_USE_OF_INTERNAL_MEMBER: needs evaluation
-HintCode.INVALID_USE_OF_PROTECTED_MEMBER: needs evaluation
-HintCode.INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER: needs evaluation
-HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER: needs evaluation
-HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER: needs evaluation
-HintCode.INVALID_VISIBILITY_ANNOTATION: needs evaluation
-HintCode.INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION: needs evaluation
-HintCode.MISSING_REQUIRED_PARAM: has fix(es)
-HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS: has fix(es)
-HintCode.MISSING_RETURN: needs evaluation
-HintCode.MIXIN_ON_SEALED_CLASS: needs evaluation
-HintCode.MUST_BE_IMMUTABLE: needs evaluation
-HintCode.MUST_CALL_SUPER: needs fix; https://github.com/dart-lang/sdk/issues/33985
-HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR: needs evaluation
-HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW: needs evaluation
-HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE: needs evaluation
-HintCode.NULL_AWARE_BEFORE_OPERATOR: needs evaluation
-HintCode.NULL_AWARE_IN_CONDITION: needs evaluation
-HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR: needs evaluation
-HintCode.NULL_CHECK_ALWAYS_FAILS: needs evaluation
-HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE: has fix(es)
-HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD: has fix(es)
-HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER: has fix(es)
-HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: has fix(es)
-HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER: has fix(es)
-HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT: needs evaluation
-HintCode.RECEIVER_OF_TYPE_NEVER: needs evaluation
-HintCode.RETURN_OF_DO_NOT_STORE: needs evaluation
-HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR: needs evaluation
-HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR: needs evaluation
-HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT: has fix(es)
-HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE: has fix(es)
-HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT: has fix(es)
-HintCode.SDK_VERSION_CONSTRUCTOR_TEAROFFS: needs evaluation
-HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT: has fix(es)
-HintCode.SDK_VERSION_EXTENSION_METHODS: has fix(es)
-HintCode.SDK_VERSION_GT_GT_GT_OPERATOR: has fix(es)
-HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT: has fix(es)
-HintCode.SDK_VERSION_NEVER: needs evaluation
-HintCode.SDK_VERSION_SET_LITERAL: has fix(es)
-HintCode.SDK_VERSION_UI_AS_CODE: has fix(es)
-HintCode.SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT: needs evaluation
-HintCode.STRICT_RAW_TYPE: needs evaluation
-HintCode.SUBTYPE_OF_SEALED_CLASS: needs evaluation
-HintCode.TYPE_CHECK_IS_NOT_NULL: has fix(es)
-HintCode.TYPE_CHECK_IS_NULL: has fix(es)
-HintCode.UNDEFINED_HIDDEN_NAME: has fix(es)
-HintCode.UNDEFINED_REFERENCED_PARAMETER: has fix(es)
-HintCode.UNDEFINED_SHOWN_NAME: needs evaluation
-HintCode.UNIGNORABLE_IGNORE: needs evaluation
-HintCode.UNNECESSARY_CAST: has fix(es)
-HintCode.UNNECESSARY_IGNORE: needs evaluation
-HintCode.UNNECESSARY_IMPORT: has fix(es)
-HintCode.UNNECESSARY_NO_SUCH_METHOD: needs evaluation
-HintCode.UNNECESSARY_NULL_COMPARISON_FALSE: has fix(es)
-HintCode.UNNECESSARY_NULL_COMPARISON_TRUE: has fix(es)
-HintCode.UNNECESSARY_QUESTION_MARK: needs evaluation
-HintCode.UNNECESSARY_TYPE_CHECK_FALSE: needs fix; https://github.com/dart-lang/sdk/issues/47793
-HintCode.UNNECESSARY_TYPE_CHECK_TRUE: needs fix; https://github.com/dart-lang/sdk/issues/47793
-HintCode.TEXT_DIRECTION_CODE_POINT_IN_COMMENT: needs evaluation
-HintCode.TEXT_DIRECTION_CODE_POINT_IN_LITERAL: needs evaluation
-HintCode.UNUSED_CATCH_CLAUSE: has fix(es)
-HintCode.UNUSED_CATCH_STACK: has fix(es)
-HintCode.UNUSED_ELEMENT: has fix(es)
-HintCode.UNUSED_ELEMENT_PARAMETER: needs evaluation
-HintCode.UNUSED_FIELD: has fix(es)
-HintCode.UNUSED_IMPORT: has fix(es)
-HintCode.UNUSED_LABEL: has fix(es)
-HintCode.UNUSED_LOCAL_VARIABLE: has fix(es)
-HintCode.UNUSED_RESULT: needs evaluation
-HintCode.UNUSED_RESULT_WITH_MESSAGE: needs evaluation
-HintCode.UNUSED_SHOWN_NAME: has fix(es)
-LanguageCode.IMPLICIT_DYNAMIC_FIELD: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_FUNCTION: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_INVOKE: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_LIST_LITERAL: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_MAP_LITERAL: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_METHOD: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_PARAMETER: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_RETURN: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_TYPE: needs evaluation
-LanguageCode.IMPLICIT_DYNAMIC_VARIABLE: needs evaluation
-LintNames.always_declare_return_types: has fix(es)
-LintNames.always_put_control_body_on_new_line: needs evaluation
-LintNames.always_put_required_named_parameters_first: needs evaluation
-LintNames.always_require_non_null_named_parameters: has fix(es)
-LintNames.always_specify_types: has fix(es)
-LintNames.always_use_package_imports: needs evaluation
-LintNames.annotate_overrides: has fix(es)
-LintNames.avoid_annotating_with_dynamic: has fix(es)
-LintNames.avoid_as: needs evaluation
-LintNames.avoid_bool_literals_in_conditional_expressions: needs evaluation
-LintNames.avoid_catches_without_on_clauses: needs evaluation
-LintNames.avoid_catching_errors: needs evaluation
-LintNames.avoid_classes_with_only_static_members: needs evaluation
-LintNames.avoid_double_and_int_checks: needs evaluation
-LintNames.avoid_dynamic_calls: needs evaluation
-LintNames.avoid_empty_else: has fix(es)
-LintNames.avoid_equals_and_hash_code_on_mutable_classes: needs evaluation
-LintNames.avoid_escaping_inner_quotes: has fix(es)
-LintNames.avoid_field_initializers_in_const_classes: needs evaluation
-LintNames.avoid_final_parameters: needs evaluation
-LintNames.avoid_function_literals_in_foreach_calls: has fix(es)
-LintNames.avoid_implementing_value_types: needs evaluation
-LintNames.avoid_init_to_null: has fix(es)
-LintNames.avoid_js_rounded_ints: needs evaluation
-LintNames.avoid_multiple_declarations_per_line: needs evaluation
-LintNames.avoid_null_checks_in_equality_operators: has fix(es)
-LintNames.avoid_positional_boolean_parameters: needs evaluation
-LintNames.avoid_print: has fix(es)
-LintNames.avoid_private_typedef_functions: has fix(es)
-LintNames.avoid_redundant_argument_values: has fix(es)
-LintNames.avoid_relative_lib_imports: has fix(es)
-LintNames.avoid_renaming_method_parameters: needs evaluation
-LintNames.avoid_return_types_on_setters: has fix(es)
-LintNames.avoid_returning_null: needs evaluation
-LintNames.avoid_returning_null_for_future: has fix(es)
-LintNames.avoid_returning_null_for_void: has fix(es)
-LintNames.avoid_returning_this: needs evaluation
-LintNames.avoid_setters_without_getters: needs evaluation
-LintNames.avoid_shadowing_type_parameters: needs evaluation
-LintNames.avoid_single_cascade_in_expression_statements: has fix(es)
-LintNames.avoid_slow_async_io: needs evaluation
-LintNames.avoid_type_to_string: needs evaluation
-LintNames.avoid_types_as_parameter_names: has fix(es)
-LintNames.avoid_types_on_closure_parameters: has fix(es)
-LintNames.avoid_unnecessary_containers: has fix(es)
-LintNames.avoid_unused_constructor_parameters: has fix(es)
-LintNames.avoid_void_async: needs evaluation
-LintNames.avoid_web_libraries_in_flutter: needs evaluation
-LintNames.await_only_futures: has fix(es)
-LintNames.camel_case_extensions: needs evaluation
-LintNames.camel_case_types: needs evaluation
-LintNames.cancel_subscriptions: needs evaluation
-LintNames.cascade_invocations: needs evaluation
-LintNames.cast_nullable_to_non_nullable: needs evaluation
-LintNames.close_sinks: needs evaluation
-LintNames.comment_references: needs evaluation
-LintNames.conditional_uri_does_not_exist: needs evaluation
-LintNames.constant_identifier_names: needs evaluation
-LintNames.control_flow_in_finally: needs evaluation
-LintNames.curly_braces_in_flow_control_structures: has fix(es)
-LintNames.depend_on_referenced_packages: needs evaluation
-LintNames.deprecated_consistency: needs evaluation
-LintNames.diagnostic_describe_all_properties: has fix(es)
-LintNames.directives_ordering: has fix(es)
-LintNames.do_not_use_environment: needs evaluation
-LintNames.empty_catches: has fix(es)
-LintNames.empty_constructor_bodies: has fix(es)
-LintNames.empty_statements: has fix(es)
-LintNames.eol_at_end_of_file: has fix(es)
-LintNames.exhaustive_cases: has fix(es)
-LintNames.file_names: needs evaluation
-LintNames.flutter_style_todos: needs evaluation
-LintNames.hash_and_equals: has fix(es)
-LintNames.implementation_imports: needs evaluation
-LintNames.invariant_booleans: needs evaluation
-LintNames.iterable_contains_unrelated_type: needs evaluation
-LintNames.join_return_with_assignment: needs evaluation
-LintNames.leading_newlines_in_multiline_strings: has fix(es)
-LintNames.library_names: needs evaluation
-LintNames.library_prefixes: needs evaluation
-LintNames.library_private_types_in_public_api: needs evaluation
-LintNames.lines_longer_than_80_chars: needs evaluation
-LintNames.list_remove_unrelated_type: needs evaluation
-LintNames.literal_only_boolean_expressions: needs evaluation
-LintNames.missing_whitespace_between_adjacent_strings: needs evaluation
-LintNames.no_adjacent_strings_in_list: needs evaluation
-LintNames.no_default_cases: needs evaluation
-LintNames.no_duplicate_case_values: has fix(es)
-LintNames.no_leading_underscores_for_library_prefixes: needs evaluation
-LintNames.no_leading_underscores_for_local_identifiers: needs evaluation
-LintNames.no_logic_in_create_state: needs evaluation
-LintNames.no_runtimeType_toString: needs evaluation
-LintNames.non_constant_identifier_names: has fix(es)
-LintNames.noop_primitive_operations: needs evaluation
-LintNames.null_check_on_nullable_type_parameter: needs evaluation
-LintNames.null_closures: has fix(es)
-LintNames.omit_local_variable_types: has fix(es)
-LintNames.one_member_abstracts: needs evaluation
-LintNames.only_throw_errors: needs evaluation
-LintNames.overridden_fields: needs evaluation
-LintNames.package_api_docs: needs evaluation
-LintNames.package_prefixed_library_names: needs evaluation
-LintNames.parameter_assignments: needs evaluation
-LintNames.prefer_adjacent_string_concatenation: has fix(es)
-LintNames.prefer_asserts_in_initializer_lists: needs evaluation
-LintNames.prefer_asserts_with_message: needs evaluation
-LintNames.prefer_bool_in_asserts: needs evaluation
-LintNames.prefer_collection_literals: has fix(es)
-LintNames.prefer_conditional_assignment: has fix(es)
-LintNames.prefer_const_constructors: has fix(es)
-LintNames.prefer_const_constructors_in_immutables: has fix(es)
-LintNames.prefer_const_declarations: has fix(es)
-LintNames.prefer_const_literals_to_create_immutables: has fix(es)
-LintNames.prefer_constructors_over_static_methods: needs evaluation
-LintNames.prefer_contains: has fix(es)
-LintNames.prefer_double_quotes: has fix(es)
-LintNames.prefer_equal_for_default_values: has fix(es)
-LintNames.prefer_expression_function_bodies: has fix(es)
-LintNames.prefer_final_fields: has fix(es)
-LintNames.prefer_final_in_for_each: has fix(es)
-LintNames.prefer_final_locals: has fix(es)
-LintNames.prefer_final_parameters: has fix(es)
-LintNames.prefer_for_elements_to_map_fromIterable: has fix(es)
-LintNames.prefer_foreach: needs evaluation
-LintNames.prefer_function_declarations_over_variables: needs evaluation
-LintNames.prefer_generic_function_type_aliases: has fix(es)
-LintNames.prefer_if_elements_to_conditional_expressions: has fix(es)
-LintNames.prefer_if_null_operators: has fix(es)
-LintNames.prefer_initializing_formals: has fix(es)
-LintNames.prefer_inlined_adds: has fix(es)
-LintNames.prefer_int_literals: has fix(es)
-LintNames.prefer_interpolation_to_compose_strings: has fix(es)
-LintNames.prefer_is_empty: has fix(es)
-LintNames.prefer_is_not_empty: has fix(es)
-LintNames.prefer_is_not_operator: has fix(es)
-LintNames.prefer_iterable_whereType: has fix(es)
-LintNames.prefer_mixin: needs evaluation
-LintNames.prefer_null_aware_method_calls: needs evaluation
-LintNames.prefer_null_aware_operators: has fix(es)
-LintNames.prefer_relative_imports: has fix(es)
-LintNames.prefer_single_quotes: has fix(es)
-LintNames.prefer_spread_collections: has fix(es)
-LintNames.prefer_typing_uninitialized_variables: has fix(es)
-LintNames.prefer_void_to_null: has fix(es)
-LintNames.provide_deprecation_message: needs evaluation
-LintNames.pub/package_names: needs evaluation
-LintNames.pub/secure_pubspec_urls: needs evaluation
-LintNames.pub/sort_pub_dependencies: needs evaluation
-LintNames.public_member_api_docs: needs evaluation
-LintNames.recursive_getters: needs evaluation
-LintNames.require_trailing_commas: has fix(es)
-LintNames.sized_box_for_whitespace: has fix(es)
-LintNames.sized_box_shrink_expand: needs evaluation
-LintNames.slash_for_doc_comments: has fix(es)
-LintNames.sort_child_properties_last: has fix(es)
-LintNames.sort_constructors_first: needs fix; https://github.com/dart-lang/sdk/issues/47953
-LintNames.sort_unnamed_constructors_first: needs evaluation
-LintNames.super_goes_last: needs evaluation
-LintNames.test_types_in_equals: needs evaluation
-LintNames.throw_in_finally: needs evaluation
-LintNames.tighten_type_of_initializing_formals: needs evaluation
-LintNames.type_annotate_public_apis: has fix(es)
-LintNames.type_init_formals: has fix(es)
-LintNames.unawaited_futures: has fix(es)
-LintNames.unnecessary_await_in_return: needs evaluation
-LintNames.unnecessary_brace_in_string_interps: has fix(es)
-LintNames.unnecessary_const: has fix(es)
-LintNames.unnecessary_constructor_name: has fix(es)
-LintNames.unnecessary_final: has fix(es)
-LintNames.unnecessary_getters_setters: has fix(es)
-LintNames.unnecessary_lambdas: has fix(es)
-LintNames.unnecessary_late: needs evaluation
-LintNames.unnecessary_new: has fix(es)
-LintNames.unnecessary_null_aware_assignments: needs evaluation
-LintNames.unnecessary_null_checks: needs evaluation
-LintNames.unnecessary_null_in_if_null_operators: has fix(es)
-LintNames.unnecessary_nullable_for_final_variable_declarations: has fix(es)
-LintNames.unnecessary_overrides: has fix(es)
-LintNames.unnecessary_parenthesis: has fix(es)
-LintNames.unnecessary_raw_strings: has fix(es)
-LintNames.unnecessary_statements: needs evaluation
-LintNames.unnecessary_string_escapes: has fix(es)
-LintNames.unnecessary_string_interpolations: has fix(es)
-LintNames.unnecessary_this: has fix(es)
-LintNames.unrelated_type_equality_checks: needs evaluation
-LintNames.unsafe_html: needs evaluation
-LintNames.use_build_context_synchronously: needs evaluation
-LintNames.use_decorated_box: needs evaluation
-LintNames.use_full_hex_values_for_flutter_colors: has fix(es)
-LintNames.use_function_type_syntax_for_parameters: has fix(es)
-LintNames.use_if_null_to_convert_nulls_to_bools: needs evaluation
-LintNames.use_is_even_rather_than_modulo: needs evaluation
-LintNames.use_key_in_widget_constructors: has fix(es)
-LintNames.use_late_for_private_fields_and_variables: needs evaluation
-LintNames.use_named_constants: needs evaluation
-LintNames.use_raw_strings: needs evaluation
-LintNames.use_rethrow_when_possible: has fix(es)
-LintNames.use_setters_to_change_properties: needs evaluation
-LintNames.use_string_buffers: needs evaluation
-LintNames.use_test_throws_matchers: needs evaluation
-LintNames.use_to_and_as_if_applicable: needs evaluation
-LintNames.valid_regexps: needs evaluation
-LintNames.void_checks: needs evaluation
-ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE: needs evaluation
-ManifestWarningCode.NO_TOUCHSCREEN_FEATURE: needs evaluation
-ManifestWarningCode.NON_RESIZABLE_ACTIVITY: needs evaluation
-ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE: needs evaluation
-ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY: needs evaluation
-ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE: needs evaluation
-ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE: needs evaluation
-ParserErrorCode.ABSTRACT_CLASS_MEMBER: has fix(es)
-ParserErrorCode.ABSTRACT_ENUM: needs evaluation
-ParserErrorCode.ABSTRACT_EXTERNAL_FIELD: needs evaluation
-ParserErrorCode.ABSTRACT_LATE_FIELD: needs evaluation
-ParserErrorCode.ABSTRACT_STATIC_FIELD: needs evaluation
-ParserErrorCode.ABSTRACT_STATIC_METHOD: needs evaluation
-ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION: needs evaluation
-ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE: needs evaluation
-ParserErrorCode.ABSTRACT_TYPEDEF: needs evaluation
-ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT: needs evaluation
-ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS: needs evaluation
-ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED: needs evaluation
-ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER: needs evaluation
-ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT: needs evaluation
-ParserErrorCode.BREAK_OUTSIDE_OF_LOOP: needs evaluation
-ParserErrorCode.CATCH_SYNTAX: needs evaluation
-ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS: needs evaluation
-ParserErrorCode.CLASS_IN_CLASS: needs evaluation
-ParserErrorCode.COLON_IN_PLACE_OF_IN: needs evaluation
-ParserErrorCode.CONFLICTING_MODIFIERS: needs evaluation
-ParserErrorCode.CONST_AND_FINAL: needs evaluation
-ParserErrorCode.CONST_CLASS: needs evaluation
-ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY: needs evaluation
-ParserErrorCode.CONST_ENUM: needs evaluation
-ParserErrorCode.CONST_FACTORY: needs evaluation
-ParserErrorCode.CONST_METHOD: needs evaluation
-ParserErrorCode.CONST_TYPEDEF: needs evaluation
-ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE: needs evaluation
-ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS: needs evaluation
-ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP: needs evaluation
-ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE: needs evaluation
-ParserErrorCode.COVARIANT_AND_STATIC: needs evaluation
-ParserErrorCode.COVARIANT_CONSTRUCTOR: needs evaluation
-ParserErrorCode.COVARIANT_MEMBER: needs evaluation
-ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION: needs evaluation
-ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE: needs evaluation
-ParserErrorCode.DEFERRED_AFTER_PREFIX: needs evaluation
-ParserErrorCode.DIRECTIVE_AFTER_DECLARATION: needs evaluation
-ParserErrorCode.DUPLICATE_DEFERRED: needs evaluation
-ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT: needs evaluation
-ParserErrorCode.DUPLICATE_PREFIX: needs evaluation
-ParserErrorCode.DUPLICATED_MODIFIER: needs evaluation
-ParserErrorCode.EMPTY_ENUM_BODY: needs evaluation
-ParserErrorCode.ENUM_IN_CLASS: needs evaluation
-ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND: needs evaluation
-ParserErrorCode.EXPECTED_BODY: needs evaluation
-ParserErrorCode.EXPECTED_CASE_OR_DEFAULT: needs evaluation
-ParserErrorCode.EXPECTED_CLASS_MEMBER: needs evaluation
-ParserErrorCode.EXPECTED_ELSE_OR_COMMA: needs evaluation
-ParserErrorCode.EXPECTED_EXECUTABLE: needs evaluation
-ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD: needs evaluation
-ParserErrorCode.EXPECTED_INSTEAD: needs evaluation
-ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL: needs evaluation
-ParserErrorCode.EXPECTED_STRING_LITERAL: needs evaluation
-ParserErrorCode.EXPECTED_TOKEN: has fix(es)
-ParserErrorCode.EXPECTED_TYPE_NAME: needs evaluation
-ParserErrorCode.EXPERIMENT_NOT_ENABLED: needs evaluation
-ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE: needs evaluation
-ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER: needs evaluation
-ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR: needs evaluation
-ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD: needs evaluation
-ParserErrorCode.EXTERNAL_CLASS: needs evaluation
-ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER: needs evaluation
-ParserErrorCode.EXTERNAL_ENUM: needs evaluation
-ParserErrorCode.EXTERNAL_FACTORY_REDIRECTION: needs evaluation
-ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_FIELD: needs evaluation
-ParserErrorCode.EXTERNAL_GETTER_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_LATE_FIELD: needs evaluation
-ParserErrorCode.EXTERNAL_METHOD_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_SETTER_WITH_BODY: needs evaluation
-ParserErrorCode.EXTERNAL_TYPEDEF: needs evaluation
-ParserErrorCode.EXTRANEOUS_MODIFIER: needs evaluation
-ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION: needs evaluation
-ParserErrorCode.FACTORY_WITH_INITIALIZERS: needs evaluation
-ParserErrorCode.FACTORY_WITHOUT_BODY: needs evaluation
-ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS: needs evaluation
-ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR: needs evaluation
-ParserErrorCode.FINAL_AND_COVARIANT: needs evaluation
-ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER: needs evaluation
-ParserErrorCode.FINAL_AND_VAR: needs evaluation
-ParserErrorCode.FINAL_CLASS: needs evaluation
-ParserErrorCode.FINAL_CONSTRUCTOR: needs evaluation
-ParserErrorCode.FINAL_ENUM: needs evaluation
-ParserErrorCode.FINAL_METHOD: needs evaluation
-ParserErrorCode.FINAL_TYPEDEF: needs evaluation
-ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR: needs evaluation
-ParserErrorCode.GETTER_CONSTRUCTOR: needs evaluation
-ParserErrorCode.GETTER_IN_FUNCTION: needs evaluation
-ParserErrorCode.GETTER_WITH_PARAMETERS: has fix(es)
-ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE: needs evaluation
-ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS: needs evaluation
-ParserErrorCode.IMPLEMENTS_BEFORE_ON: needs evaluation
-ParserErrorCode.IMPLEMENTS_BEFORE_WITH: needs evaluation
-ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE: needs evaluation
-ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH: needs evaluation
-ParserErrorCode.INVALID_AWAIT_IN_FOR: needs evaluation
-ParserErrorCode.INVALID_CODE_POINT: needs evaluation
-ParserErrorCode.INVALID_COMMENT_REFERENCE: needs evaluation
-ParserErrorCode.INVALID_CONSTRUCTOR_NAME: needs evaluation
-ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE: needs evaluation
-ParserErrorCode.INVALID_HEX_ESCAPE: needs evaluation
-ParserErrorCode.INVALID_INITIALIZER: needs evaluation
-ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION: needs evaluation
-ParserErrorCode.INVALID_OPERATOR: needs evaluation
-ParserErrorCode.INVALID_OPERATOR_FOR_SUPER: needs evaluation
-ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER: needs evaluation
-ParserErrorCode.INVALID_STAR_AFTER_ASYNC: needs evaluation
-ParserErrorCode.INVALID_SUPER_IN_INITIALIZER: needs evaluation
-ParserErrorCode.INVALID_SYNC: needs evaluation
-ParserErrorCode.INVALID_THIS_IN_INITIALIZER: needs evaluation
-ParserErrorCode.INVALID_UNICODE_ESCAPE: needs evaluation
-ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION: needs evaluation
-ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST: needs evaluation
-ParserErrorCode.LITERAL_WITH_CLASS_AND_NEW: needs evaluation
-ParserErrorCode.LITERAL_WITH_CLASS: needs evaluation
-ParserErrorCode.LITERAL_WITH_NEW: needs evaluation
-ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER: needs evaluation
-ParserErrorCode.MEMBER_WITH_CLASS_NAME: needs evaluation
-ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR: needs evaluation
-ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER: needs evaluation
-ParserErrorCode.MISSING_CATCH_OR_FINALLY: needs evaluation
-ParserErrorCode.MISSING_CLOSING_PARENTHESIS: needs evaluation
-ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE: has fix(es)
-ParserErrorCode.MISSING_ENUM_BODY: needs evaluation
-ParserErrorCode.MISSING_EXPRESSION_IN_INITIALIZER: needs evaluation
-ParserErrorCode.MISSING_EXPRESSION_IN_THROW: needs evaluation
-ParserErrorCode.MISSING_FUNCTION_BODY: has fix(es)
-ParserErrorCode.MISSING_FUNCTION_KEYWORD: needs evaluation
-ParserErrorCode.MISSING_FUNCTION_PARAMETERS: needs evaluation
-ParserErrorCode.MISSING_GET: needs evaluation
-ParserErrorCode.MISSING_IDENTIFIER: needs evaluation
-ParserErrorCode.MISSING_INITIALIZER: needs evaluation
-ParserErrorCode.MISSING_KEYWORD_OPERATOR: needs evaluation
-ParserErrorCode.MISSING_METHOD_PARAMETERS: needs evaluation
-ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER: needs evaluation
-ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE: needs evaluation
-ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE: needs evaluation
-ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT: needs evaluation
-ParserErrorCode.MISSING_STAR_AFTER_SYNC: needs evaluation
-ParserErrorCode.MISSING_STATEMENT: needs evaluation
-ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
-ParserErrorCode.MISSING_TYPEDEF_PARAMETERS: needs evaluation
-ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH: needs evaluation
-ParserErrorCode.MIXED_PARAMETER_GROUPS: needs evaluation
-ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR: needs evaluation
-ParserErrorCode.MODIFIER_OUT_OF_ORDER: needs evaluation
-ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES: needs evaluation
-ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES: needs evaluation
-ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES: needs evaluation
-ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS: needs evaluation
-ParserErrorCode.MULTIPLE_ON_CLAUSES: needs evaluation
-ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES: needs evaluation
-ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS: needs evaluation
-ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH: needs evaluation
-ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS: needs evaluation
-ParserErrorCode.MULTIPLE_WITH_CLAUSES: needs evaluation
-ParserErrorCode.NAMED_FUNCTION_EXPRESSION: needs evaluation
-ParserErrorCode.NAMED_FUNCTION_TYPE: needs evaluation
-ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP: needs evaluation
-ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE: needs evaluation
-ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION: needs evaluation
-ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE: needs evaluation
-ParserErrorCode.NON_CONSTRUCTOR_FACTORY: needs evaluation
-ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME: needs evaluation
-ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART: needs evaluation
-ParserErrorCode.NON_STRING_LITERAL_AS_URI: needs evaluation
-ParserErrorCode.NON_USER_DEFINABLE_OPERATOR: needs evaluation
-ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS: needs evaluation
-ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER: needs evaluation
-ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT: needs evaluation
-ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP: needs evaluation
-ParserErrorCode.PREFIX_AFTER_COMBINATOR: needs evaluation
-ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY: needs evaluation
-ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR: needs evaluation
-ParserErrorCode.SETTER_CONSTRUCTOR: needs evaluation
-ParserErrorCode.SETTER_IN_FUNCTION: needs evaluation
-ParserErrorCode.STACK_OVERFLOW: needs evaluation
-ParserErrorCode.STATIC_CONSTRUCTOR: needs evaluation
-ParserErrorCode.STATIC_GETTER_WITHOUT_BODY: needs evaluation
-ParserErrorCode.STATIC_OPERATOR: needs evaluation
-ParserErrorCode.STATIC_SETTER_WITHOUT_BODY: needs evaluation
-ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION: needs evaluation
-ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE: needs evaluation
-ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES: needs evaluation
-ParserErrorCode.TOP_LEVEL_OPERATOR: needs evaluation
-ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE: needs evaluation
-ParserErrorCode.TYPE_BEFORE_FACTORY: needs evaluation
-ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR: needs evaluation
-ParserErrorCode.TYPE_PARAMETER_ON_OPERATOR: needs evaluation
-ParserErrorCode.TYPEDEF_IN_CLASS: needs evaluation
-ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
-ParserErrorCode.UNEXPECTED_TOKEN: needs evaluation
-ParserErrorCode.VAR_AND_TYPE: needs evaluation
-ParserErrorCode.VAR_AS_TYPE_NAME: has fix(es)
-ParserErrorCode.VAR_CLASS: needs evaluation
-ParserErrorCode.VAR_ENUM: needs evaluation
-ParserErrorCode.VAR_RETURN_TYPE: needs evaluation
-ParserErrorCode.VAR_TYPEDEF: needs evaluation
-ParserErrorCode.VOID_WITH_TYPE_ARGUMENTS: needs evaluation
-ParserErrorCode.WITH_BEFORE_EXTENDS: needs evaluation
-ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER: needs evaluation
-ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
-PubspecWarningCode.ASSET_DOES_NOT_EXIST: needs evaluation
-PubspecWarningCode.ASSET_DIRECTORY_DOES_NOT_EXIST: needs evaluation
-PubspecWarningCode.ASSET_FIELD_NOT_LIST: needs evaluation
-PubspecWarningCode.ASSET_NOT_STRING: needs evaluation
-PubspecWarningCode.DEPENDENCIES_FIELD_NOT_MAP: needs evaluation
-PubspecWarningCode.DEPRECATED_FIELD: needs evaluation
-PubspecWarningCode.FLUTTER_FIELD_NOT_MAP: needs evaluation
-PubspecWarningCode.INVALID_DEPENDENCY: needs evaluation
-PubspecWarningCode.MISSING_NAME: needs evaluation
-PubspecWarningCode.NAME_NOT_STRING: needs evaluation
-PubspecWarningCode.PATH_DOES_NOT_EXIST: needs evaluation
-PubspecWarningCode.PATH_NOT_POSIX: needs evaluation
-PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST: needs evaluation
-PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY: needs evaluation
-ScannerErrorCode.EXPECTED_TOKEN: needs evaluation
-ScannerErrorCode.ILLEGAL_CHARACTER: needs evaluation
-ScannerErrorCode.MISSING_DIGIT: needs evaluation
-ScannerErrorCode.MISSING_HEX_DIGIT: needs evaluation
-ScannerErrorCode.MISSING_IDENTIFIER: needs evaluation
-ScannerErrorCode.MISSING_QUOTE: needs evaluation
-ScannerErrorCode.UNABLE_GET_CONTENT: needs evaluation
-ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING: needs evaluation
-ScannerErrorCode.UNSUPPORTED_OPERATOR: needs evaluation
-ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT: needs evaluation
-ScannerErrorCode.UNTERMINATED_STRING_LITERAL: needs evaluation
-StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION: has fix(es)
-StaticWarningCode.INVALID_NULL_AWARE_OPERATOR: has fix(es)
-StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT: has fix(es)
-StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED: needs evaluation
-StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL: needs evaluation
-StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH: has fix(es)
-StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION: has fix(es)
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
new file mode 100644
index 0000000..fa7be23
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -0,0 +1,2364 @@
+# This file contains a map. The key of each top-level entry is the unique name
+# of either an error code or a lint name. The value of each top-level entry is
+# a map describing the status of fixes related to that diagnostic.
+#
+# In every second-level map, the first key is `status` and the corresponding
+# value is one of the following:
+# - needsEvaluation, if the diagnostic has not been evaluated in terms of fixes.
+# - hasFix, if the diagnostic has one or more fixes.
+# - noFix, if no fix seems appropriate for the diagnostic. There should be a
+# second key named `reason` whose value is text explaining why there is no
+# appropriate fix.
+# - needsFix, if the diagnostic needs a fix, with a possible issue link. If an
+# issue has been opened, there should be a second key named `issue` whose
+# value is the URL of the issue.
+#
+# Stats:
+# - 809 "needsEvaluation"
+# - 19 "needsFix"
+# - 253 "hasFix"
+# - 3 "noFix"
+
+AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR:
+ status: noFix
+AnalysisOptionsErrorCode.PARSE_ERROR:
+ status: noFix
+AnalysisOptionsHintCode.PREVIEW_DART_2_SETTING_DEPRECATED:
+ status: needsEvaluation
+AnalysisOptionsHintCode.STRONG_MODE_SETTING_DEPRECATED:
+ status: needsEvaluation
+AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.ANALYSIS_OPTION_DEPRECATED:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.INVALID_OPTION:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.SPEC_MODE_REMOVED:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES:
+ status: needsEvaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_VALUE:
+ status: needsEvaluation
+CompileTimeErrorCode.ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.ABSTRACT_FIELD_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE:
+ status: needsEvaluation
+CompileTimeErrorCode.AMBIGUOUS_EXPORT:
+ status: needsEvaluation
+CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS:
+ status: needsEvaluation
+CompileTimeErrorCode.AMBIGUOUS_IMPORT:
+ status: needsEvaluation
+CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH:
+ status: needsEvaluation
+CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER:
+ status: needsEvaluation
+CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE:
+ status: hasFix
+CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_CONST:
+ status: needsEvaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL:
+ status: hasFix
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL:
+ status: hasFix
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION:
+ status: needsEvaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_METHOD:
+ status: needsEvaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT:
+ status: hasFix
+CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT:
+ status: hasFix
+CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY:
+ status: hasFix
+CompileTimeErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.CASE_BLOCK_NOT_TERMINATED:
+ status: needsEvaluation
+CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS:
+ status: needsEvaluation
+CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.CAST_TO_NON_TYPE:
+ status: hasFix
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_INSTANCE_MEMBER:
+ status: needsEvaluation
+ since: 2.15
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_STATIC_MEMBER:
+ status: needsEvaluation
+ since: 2.15
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER:
+ status: needsEvaluation
+ since: in 2.15
+CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer a fix that would remove all of the types in the
+ class header that are or implement `Enum`, but I think it would be more
+ likely that the user needed to restructure the super interfaces so that
+ `Enum` wasn't included but the rest of the interfaces could be.
+CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER:
+ status: hasFix
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER:
+ status: noFix
+ since: 2.15
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER:
+ status: noFix
+ since: 2.15
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES:
+ status: needsEvaluation
+CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM:
+ status: noFix
+ since: 2.17
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM:
+ status: noFix
+ since: 2.17
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN:
+ status: noFix
+ notes: |-
+ The fix is to rename one of the two, but we can't know what name to use.
+CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_INT:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_NUM:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE:
+ status: hasFix
+CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_INSTANCE_FIELD:
+ status: hasFix
+CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_NOT_INITIALIZED:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_WITH_NON_CONST:
+ status: hasFix
+CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_WITH_NON_TYPE:
+ status: hasFix
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF:
+ status: needsEvaluation
+ since: 2.15
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF:
+ status: needsEvaluation
+ since: 2.15
+CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT:
+ status: needsEvaluation
+CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH:
+ status: needsEvaluation
+CompileTimeErrorCode.COULD_NOT_INFER:
+ status: needsEvaluation
+CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR:
+ status: hasFix
+CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION:
+ status: needsEvaluation
+CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT:
+ status: needsEvaluation
+CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME:
+ status: needsEvaluation
+CompileTimeErrorCode.DUPLICATE_DEFINITION:
+ status: needsEvaluation
+CompileTimeErrorCode.DUPLICATE_FIELD_FORMAL_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.DUPLICATE_PART:
+ status: needsEvaluation
+CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING:
+ status: needsEvaluation
+CompileTimeErrorCode.ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR:
+ status: noFix
+ since: 2.17
+CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED:
+ status: noFix
+ since: 2.17
+CompileTimeErrorCode.ENUM_MIXIN_WITH_INSTANCE_VARIABLE:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer a fix that would remove the mixin, but I think it
+ would be more likely that the user needed to restructure the mixin so that
+ part of it could be included here.
+CompileTimeErrorCode.ENUM_WITH_ABSTRACT_MEMBER:
+ status: needsFix
+ since: 2.17
+ issue: https://github.com/dart-lang/sdk/issues/48478
+CompileTimeErrorCode.ENUM_WITH_NAME_VALUES:
+ status: noFix
+ since: 2.17
+ notes: |-
+ Requires a rename.
+CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET:
+ status: needsEvaluation
+CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.EXPRESSION_IN_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENDS_NON_CLASS:
+ status: hasFix
+CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_AS_EXPRESSION:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER:
+ status: hasFix
+CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_WITHOUT_ACCESS:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTERNAL_FIELD_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTERNAL_VARIABLE_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS:
+ status: hasFix
+CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED:
+ status: hasFix
+CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED:
+ status: hasFix
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1:
+ status: hasFix
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2:
+ status: hasFix
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS:
+ status: hasFix
+CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND:
+ status: needsEvaluation
+CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES:
+ status: needsEvaluation
+CompileTimeErrorCode.GETTER_NOT_SUBTYPE_SETTER_TYPES:
+ status: needsEvaluation
+CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE:
+ status: hasFix
+CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE:
+ status: hasFix
+CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer to remove the member, but the user probably needs
+ to think about what they were trying to do and it seems more likely that the
+ right fix is to rename the member.
+CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer to remove the member, but the user probably needs
+ to think about what they were trying to do and it seems more likely that the
+ right fix is to rename the member.
+CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION:
+ status: noFix
+ since: 2.17
+ notes: |-
+ While we could have a fix to remove the declaration, it seems more likely
+ that the user would want to rename it.
+CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE:
+ status: noFix
+ since: 2.17
+CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer to remove the override, or to update it to the
+ lowest legal value, but it isn't clear that either of these is the right
+ fix without knowing why the language override was added.
+CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE:
+ status: hasFix
+CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLEMENTS_NON_CLASS:
+ status: hasFix
+CompileTimeErrorCode.IMPLEMENTS_REPEATED:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS:
+ status: hasFix
+CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES:
+ status: needsEvaluation
+CompileTimeErrorCode.INCONSISTENT_INHERITANCE:
+ status: needsEvaluation
+CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD:
+ status: needsEvaluation
+CompileTimeErrorCode.INCONSISTENT_LANGUAGE_VERSION_OVERRIDE:
+ status: needsEvaluation
+CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD:
+ status: needsEvaluation
+CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD:
+ status: needsEvaluation
+CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD:
+ status: hasFix
+CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER:
+ status: hasFix
+CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION:
+ status: needsEvaluation
+CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY:
+ status: needsEvaluation
+CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC:
+ status: needsEvaluation
+CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.INSTANTIATE_ENUM:
+ status: needsEvaluation
+CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE:
+ status: hasFix
+CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_ANNOTATION:
+ status: hasFix
+CompileTimeErrorCode.INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_ASSIGNMENT:
+ status: hasFix
+CompileTimeErrorCode.INVALID_CAST_FUNCTION:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_FUNCTION_EXPR:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_LIST:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_SET:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_METHOD:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CAST_NEW_EXPR:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_CONSTANT:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_OVERRIDE:
+ status: hasFix
+CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR:
+ status: noFix
+ since: 2.17
+CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION:
+ status: needsFix
+ since: 2.17
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_URI: needsEvaluation
+CompileTimeErrorCode.INVALID_USE_OF_COVARIANT:
+ status: needsEvaluation
+CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE:
+ status: needsEvaluation
+CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL:
+ status: needsEvaluation
+CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION:
+ status: needsEvaluation
+CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION:
+ status: hasFix
+CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE:
+ status: needsEvaluation
+CompileTimeErrorCode.LABEL_UNDEFINED:
+ status: needsEvaluation
+CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED:
+ status: needsEvaluation
+CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS:
+ status: needsEvaluation
+CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS:
+ status: needsEvaluation
+CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION:
+ status: needsEvaluation
+CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP:
+ status: needsEvaluation
+CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL:
+ status: needsEvaluation
+CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL:
+ status: needsEvaluation
+CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL:
+ status: needsEvaluation
+CompileTimeErrorCode.MISSING_DART_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER:
+ status: hasFix
+CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION:
+ status: hasFix
+CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT:
+ status: hasFix
+CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE:
+ status: hasFix
+CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_INSTANTIATE:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_OF_NON_CLASS:
+ status: hasFix
+CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MIXINS_SUPER_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS:
+ status: needsEvaluation
+CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS:
+ status: needsEvaluation
+CompileTimeErrorCode.NEW_WITH_NON_TYPE:
+ status: hasFix
+CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR:
+ status: hasFix
+CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT:
+ status: hasFix
+CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS:
+ status: needsEvaluation
+CompileTimeErrorCode.NO_COMBINED_SUPER_SIGNATURE:
+ status: needsEvaluation
+CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT:
+ status: hasFix
+CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT:
+ status: hasFix
+CompileTimeErrorCode.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS:
+ status: hasFix
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR:
+ status: hasFix
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE:
+ status: hasFix
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE:
+ status: hasFix
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO:
+ status: hasFix
+CompileTimeErrorCode.NON_BOOL_CONDITION:
+ status: hasFix
+CompileTimeErrorCode.NON_BOOL_EXPRESSION:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_BOOL_OPERAND:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR:
+ status: needsFix
+ since: 2.17
+ issue: https://github.com/dart-lang/sdk/issues/48479
+CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_KEY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_FINAL_FIELD_IN_ENUM:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_SYNC_FACTORY:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_TYPE_AS_TYPE_ARGUMENT:
+ status: hasFix
+CompileTimeErrorCode.NON_TYPE_IN_CATCH_CLAUSE:
+ status: hasFix
+CompileTimeErrorCode.NON_VOID_RETURN_FOR_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_A_TYPE:
+ status: hasFix
+CompileTimeErrorCode.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_BINARY_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS:
+ status: hasFix
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD:
+ status: hasFix
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_VARIABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_INSTANTIATED_BOUND:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_ITERABLE_SPREAD:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_MAP_SPREAD:
+ status: needsEvaluation
+CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD:
+ status: needsEvaluation
+CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE:
+ status: hasFix
+CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE:
+ status: hasFix
+CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE:
+ status: hasFix
+CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE:
+ status: hasFix
+CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS:
+ status: noFix
+CompileTimeErrorCode.ON_REPEATED:
+ status: needsEvaluation
+CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.PART_OF_NON_PART:
+ status: needsEvaluation
+CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT:
+ status: needsFix
+ since: 2.17
+CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER:
+ status: needsEvaluation
+CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT:
+ status: needsEvaluation
+CompileTimeErrorCode.PREFIX_SHADOWED_BY_LOCAL_DECLARATION:
+ status: needsEvaluation
+CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION:
+ status: needsEvaluation
+CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.PRIVATE_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.READ_POTENTIALLY_UNASSIGNED_FINAL:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_ON:
+ status: needsEvaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_INVALID_FUNCTION_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_INVALID_RETURN_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_NON_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
+ status: needsEvaluation
+CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION:
+ status: needsEvaluation
+CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH:
+ status: needsEvaluation
+CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.RETURN_IN_GENERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE:
+ status: needsEvaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION:
+ status: hasFix
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_METHOD:
+ status: hasFix
+CompileTimeErrorCode.RETURN_WITHOUT_VALUE:
+ status: needsEvaluation
+CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.SHARED_DEFERRED_PREFIX:
+ status: needsEvaluation
+CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY:
+ status: needsEvaluation
+CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER:
+ status: needsEvaluation
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED:
+ status: needsFix
+ since: 2.17
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED:
+ status: needsFix
+ since: 2.17
+ issue: https://github.com/dart-lang/sdk/issues/48480
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL:
+ status: needsFix
+ issue: https://github.com/dart-lang/sdk/issues/48359
+CompileTimeErrorCode.SUPER_IN_ENUM_CONSTRUCTOR:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer a fix to remove the super invocation, but the
+ user really needs to think about what constructor they were trying to invoke
+ and why in order to really fix the issue.
+CompileTimeErrorCode.SUPER_IN_EXTENSION:
+ status: needsEvaluation
+CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT:
+ status: needsEvaluation
+CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR:
+ status: needsEvaluation
+CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT:
+ status: needsEvaluation
+CompileTimeErrorCode.SUPER_INVOCATION_NOT_LAST:
+ status: needsEvaluation
+CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY:
+ status: hasFix
+CompileTimeErrorCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE:
+ status: needsEvaluation
+CompileTimeErrorCode.TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS:
+ status: needsEvaluation
+ since: 2.15
+CompileTimeErrorCode.THROW_OF_INVALID_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.TOP_LEVEL_CYCLE:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_ANNOTATION_DEFERRED_CLASS:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_PARAMETER_REFERENCED_BY_STATIC:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_TEST_WITH_NON_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.TYPE_TEST_WITH_UNDEFINED_NAME:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD:
+ status: hasFix
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_ANNOTATION:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_CLASS:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED:
+ status: needsFix
+ since: 2.17
+ issue: https://github.com/dart-lang/sdk/issues/48481
+CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED:
+ status: needsFix
+ since: 2.17
+ issue: https://github.com/dart-lang/sdk/issues/48481
+CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_FUNCTION:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_GETTER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_GETTER_ON_FUNCTION_TYPE:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.UNDEFINED_IDENTIFIER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_METHOD:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_METHOD_ON_FUNCTION_TYPE:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_OPERATOR:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_SETTER:
+ status: hasFix
+CompileTimeErrorCode.UNDEFINED_SETTER_ON_FUNCTION_TYPE:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.UNDEFINED_SUPER_GETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_METHOD:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER:
+ status: hasFix
+CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE:
+ status: hasFix
+CompileTimeErrorCode.URI_DOES_NOT_EXIST:
+ status: hasFix
+CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED:
+ status: needsEvaluation
+CompileTimeErrorCode.URI_WITH_INTERPOLATION:
+ status: needsEvaluation
+CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION:
+ status: needsEvaluation
+ since: ~2.15
+CompileTimeErrorCode.USE_OF_VOID_RESULT:
+ status: needsEvaluation
+CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially offer to remove the member, but the user probably needs
+ to think about what they were trying to do and it seems more likely that the
+ right fix is to rename the member.
+CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS:
+ status: hasFix
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION:
+ status: needsFix
+ since: 2.15
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR:
+ status: hasFix
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We can't know which type arguments to add or remove. (We do have a fix to
+ remove all type arguments that would work here, it just isn't a very good
+ fix to suggest.)
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION:
+ status: hasFix
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION:
+ status: needsFix
+ since: ~2.15
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD:
+ status: hasFix
+CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE:
+ status: needsEvaluation
+CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION:
+ status: needsEvaluation
+CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.YIELD_IN_NON_GENERATOR:
+ status: needsEvaluation
+CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE:
+ status: needsEvaluation
+CompileTimeErrorCode.YIELD_OF_INVALID_TYPE:
+ status: hasFix
+FfiCode.ABI_SPECIFIC_INTEGER_INVALID:
+ status: needsEvaluation
+ since: ~2.16
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_EXTRA:
+ status: needsEvaluation
+ since: ~2.16
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_MISSING:
+ status: needsEvaluation
+ since: ~2.16
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_UNSUPPORTED:
+ status: needsEvaluation
+ since: ~2.16
+FfiCode.ANNOTATION_ON_POINTER_FIELD:
+ status: needsEvaluation
+FfiCode.ARGUMENT_MUST_BE_A_CONSTANT:
+ status: needsEvaluation
+FfiCode.CREATION_OF_STRUCT_OR_UNION:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.EMPTY_STRUCT:
+ status: needsEvaluation
+FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD:
+ status: needsEvaluation
+FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY:
+ status: needsEvaluation
+FfiCode.FFI_NATIVE_MUST_BE_EXTERNAL:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER:
+ status: needsEvaluation
+FfiCode.FIELD_INITIALIZER_IN_STRUCT:
+ status: needsEvaluation
+FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT:
+ status: needsEvaluation
+ since: ~2.15
+FfiCode.GENERIC_STRUCT_SUBCLASS:
+ status: needsEvaluation
+FfiCode.INVALID_EXCEPTION_VALUE:
+ status: needsEvaluation
+FfiCode.INVALID_FIELD_TYPE_IN_STRUCT:
+ status: needsEvaluation
+FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE:
+ status: needsEvaluation
+FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE:
+ status: needsEvaluation
+FfiCode.MISMATCHED_ANNOTATION_ON_STRUCT_FIELD:
+ status: needsEvaluation
+FfiCode.MISSING_ANNOTATION_ON_STRUCT_FIELD:
+ status: needsEvaluation
+FfiCode.MISSING_EXCEPTION_VALUE:
+ status: needsEvaluation
+FfiCode.MISSING_FIELD_TYPE_IN_STRUCT:
+ status: needsEvaluation
+FfiCode.MISSING_SIZE_ANNOTATION_CARRAY:
+ status: needsEvaluation
+FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE:
+ status: needsEvaluation
+FfiCode.MUST_BE_A_SUBTYPE:
+ status: needsEvaluation
+FfiCode.NON_CONSTANT_TYPE_ARGUMENT:
+ status: needsEvaluation
+FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER:
+ status: needsEvaluation
+FfiCode.NON_POSITIVE_ARRAY_DIMENSION:
+ status: needsEvaluation
+FfiCode.NON_SIZED_TYPE_ARGUMENT:
+ status: needsEvaluation
+FfiCode.PACKED_ANNOTATION:
+ status: needsEvaluation
+FfiCode.PACKED_ANNOTATION_ALIGNMENT:
+ status: needsEvaluation
+FfiCode.PACKED_NESTING_NON_PACKED:
+ status: needsEvaluation
+FfiCode.SIZE_ANNOTATION_DIMENSIONS:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS:
+ status: needsEvaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH:
+ status: needsEvaluation
+HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER:
+ status: needsEvaluation
+HintCode.ASSIGNMENT_OF_DO_NOT_STORE:
+ status: needsEvaluation
+HintCode.BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE:
+ status: hasFix
+HintCode.CAN_BE_NULL_AFTER_NULL_AWARE:
+ status: hasFix
+HintCode.DEAD_CODE:
+ status: hasFix
+HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH:
+ status: hasFix
+HintCode.DEAD_CODE_ON_CATCH_SUBTYPE:
+ status: hasFix
+HintCode.DEPRECATED_EXTENDS_FUNCTION:
+ status: needsEvaluation
+HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION:
+ status: needsEvaluation
+HintCode.DEPRECATED_IMPLEMENTS_FUNCTION:
+ status: needsEvaluation
+HintCode.DEPRECATED_MEMBER_USE:
+ status: hasFix
+HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE:
+ status: needsEvaluation
+HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE:
+ status: needsEvaluation
+HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE:
+ status: hasFix
+HintCode.DEPRECATED_MIXIN_FUNCTION:
+ status: needsEvaluation
+HintCode.DEPRECATED_NEW_IN_COMMENT_REFERENCE:
+ status: hasFix
+HintCode.DIVISION_OPTIMIZATION:
+ status: hasFix
+HintCode.DUPLICATE_HIDDEN_NAME:
+ status: hasFix
+HintCode.DUPLICATE_IGNORE:
+ status: needsEvaluation
+HintCode.DUPLICATE_IMPORT:
+ status: hasFix
+HintCode.DUPLICATE_SHOWN_NAME:
+ status: hasFix
+HintCode.EQUAL_ELEMENTS_IN_SET:
+ status: needsEvaluation
+HintCode.EQUAL_KEYS_IN_MAP:
+ status: needsEvaluation
+HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE:
+ status: needsEvaluation
+HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE:
+ status: needsEvaluation
+HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION:
+ status: needsEvaluation
+HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_FUNCTION_INVOCATION:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_GENERIC_INVOCATION:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE:
+ status: needsEvaluation
+HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER:
+ status: needsEvaluation
+HintCode.INVALID_ANNOTATION_TARGET:
+ status: needsEvaluation
+HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT:
+ status: needsEvaluation
+HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY:
+ status: needsEvaluation
+HintCode.INVALID_FACTORY_ANNOTATION:
+ status: hasFix
+HintCode.INVALID_FACTORY_METHOD_DECL:
+ status: needsEvaluation
+HintCode.INVALID_FACTORY_METHOD_IMPL:
+ status: needsEvaluation
+HintCode.INVALID_IMMUTABLE_ANNOTATION:
+ status: hasFix
+HintCode.INVALID_INTERNAL_ANNOTATION:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS:
+ status: needsEvaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES:
+ status: needsEvaluation
+HintCode.INVALID_LITERAL_ANNOTATION:
+ status: hasFix
+HintCode.INVALID_NON_VIRTUAL_ANNOTATION:
+ status: needsEvaluation
+HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER:
+ status: needsEvaluation
+HintCode.INVALID_REQUIRED_NAMED_PARAM:
+ status: hasFix
+HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM:
+ status: hasFix
+HintCode.INVALID_REQUIRED_POSITIONAL_PARAM:
+ status: hasFix
+HintCode.INVALID_SEALED_ANNOTATION:
+ status: hasFix
+HintCode.INVALID_USE_OF_INTERNAL_MEMBER:
+ status: needsEvaluation
+HintCode.INVALID_USE_OF_PROTECTED_MEMBER:
+ status: needsEvaluation
+HintCode.INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER:
+ status: needsEvaluation
+ since: ~2.15
+HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER:
+ status: needsEvaluation
+HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER:
+ status: needsEvaluation
+HintCode.INVALID_VISIBILITY_ANNOTATION:
+ status: needsEvaluation
+HintCode.INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION:
+ status: needsFix
+ since: ~2.15
+HintCode.MISSING_REQUIRED_PARAM:
+ status: hasFix
+HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS:
+ status: hasFix
+HintCode.MISSING_RETURN:
+ status: hasFix
+HintCode.MIXIN_ON_SEALED_CLASS:
+ status: needsEvaluation
+HintCode.MUST_BE_IMMUTABLE:
+ status: needsEvaluation
+HintCode.MUST_CALL_SUPER:
+ status: needsFix
+ issue: https://github.com/dart-lang/sdk/issues/33985
+HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR:
+ status: needsEvaluation
+HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW:
+ status: needsEvaluation
+HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE:
+ status: needsEvaluation
+ since: ~2.15
+HintCode.NULL_AWARE_BEFORE_OPERATOR:
+ status: needsEvaluation
+HintCode.NULL_AWARE_IN_CONDITION:
+ status: needsEvaluation
+HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR:
+ status: needsEvaluation
+HintCode.NULL_CHECK_ALWAYS_FAILS:
+ status: needsEvaluation
+HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE:
+ status: hasFix
+HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD:
+ status: hasFix
+HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER:
+ status: hasFix
+HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD:
+ status: hasFix
+HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER:
+ status: hasFix
+HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT:
+ status: needsEvaluation
+HintCode.RECEIVER_OF_TYPE_NEVER:
+ status: needsEvaluation
+HintCode.RETURN_OF_DO_NOT_STORE:
+ status: needsEvaluation
+HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR:
+ status: needsEvaluation
+HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR:
+ status: needsEvaluation
+HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT:
+ status: hasFix
+HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE:
+ status: hasFix
+HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT:
+ status: hasFix
+HintCode.SDK_VERSION_CONSTRUCTOR_TEAROFFS:
+ status: needsFix
+ since: 2.15
+HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT:
+ status: hasFix
+HintCode.SDK_VERSION_EXTENSION_METHODS:
+ status: hasFix
+HintCode.SDK_VERSION_GT_GT_GT_OPERATOR:
+ status: hasFix
+HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT:
+ status: hasFix
+HintCode.SDK_VERSION_NEVER:
+ status: needsEvaluation
+HintCode.SDK_VERSION_SET_LITERAL:
+ status: hasFix
+HintCode.SDK_VERSION_UI_AS_CODE:
+ status: hasFix
+HintCode.SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT:
+ status: needsEvaluation
+HintCode.STRICT_RAW_TYPE:
+ status: needsEvaluation
+HintCode.SUBTYPE_OF_SEALED_CLASS:
+ status: needsEvaluation
+HintCode.TYPE_CHECK_IS_NOT_NULL:
+ status: hasFix
+HintCode.TYPE_CHECK_IS_NULL:
+ status: hasFix
+HintCode.UNDEFINED_HIDDEN_NAME:
+ status: hasFix
+HintCode.UNDEFINED_REFERENCED_PARAMETER:
+ status: needsEvaluation
+HintCode.UNDEFINED_SHOWN_NAME:
+ status: hasFix
+HintCode.UNIGNORABLE_IGNORE:
+ status: needsEvaluation
+HintCode.UNNECESSARY_CAST:
+ status: hasFix
+HintCode.UNNECESSARY_IGNORE:
+ status: needsEvaluation
+HintCode.UNNECESSARY_IMPORT:
+ status: hasFix
+HintCode.UNNECESSARY_NO_SUCH_METHOD:
+ status: needsEvaluation
+HintCode.UNNECESSARY_NULL_COMPARISON_FALSE:
+ status: hasFix
+HintCode.UNNECESSARY_NULL_COMPARISON_TRUE:
+ status: hasFix
+HintCode.UNNECESSARY_QUESTION_MARK:
+ status: needsEvaluation
+HintCode.UNNECESSARY_TYPE_CHECK_FALSE:
+ status: needsFix
+ issue: https://github.com/dart-lang/sdk/issues/47793
+HintCode.UNNECESSARY_TYPE_CHECK_TRUE:
+ status: needsFix
+ issue: https://github.com/dart-lang/sdk/issues/47793
+HintCode.TEXT_DIRECTION_CODE_POINT_IN_COMMENT:
+ status: needsFix
+ since: ~2.16
+HintCode.TEXT_DIRECTION_CODE_POINT_IN_LITERAL:
+ status: needsFix
+ since: ~2.16
+HintCode.UNUSED_CATCH_CLAUSE:
+ status: hasFix
+HintCode.UNUSED_CATCH_STACK:
+ status: hasFix
+HintCode.UNUSED_ELEMENT:
+ status: hasFix
+HintCode.UNUSED_ELEMENT_PARAMETER:
+ status: needsEvaluation
+HintCode.UNUSED_FIELD:
+ status: hasFix
+HintCode.UNUSED_IMPORT:
+ status: hasFix
+HintCode.UNUSED_LABEL:
+ status: hasFix
+HintCode.UNUSED_LOCAL_VARIABLE:
+ status: hasFix
+HintCode.UNUSED_RESULT:
+ status: needsEvaluation
+HintCode.UNUSED_RESULT_WITH_MESSAGE:
+ status: needsEvaluation
+HintCode.UNUSED_SHOWN_NAME:
+ status: hasFix
+LanguageCode.IMPLICIT_DYNAMIC_FIELD:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_FUNCTION:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_INVOKE:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_LIST_LITERAL:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_MAP_LITERAL:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_METHOD:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_PARAMETER:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_RETURN:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_TYPE:
+ status: needsEvaluation
+LanguageCode.IMPLICIT_DYNAMIC_VARIABLE:
+ status: needsEvaluation
+LintCode.always_declare_return_types:
+ status: hasFix
+LintCode.always_put_control_body_on_new_line:
+ status: needsEvaluation
+LintCode.always_put_required_named_parameters_first:
+ status: needsEvaluation
+LintCode.always_require_non_null_named_parameters:
+ status: hasFix
+LintCode.always_specify_types:
+ status: hasFix
+LintCode.always_use_package_imports:
+ status: hasFix
+LintCode.annotate_overrides:
+ status: hasFix
+LintCode.avoid_annotating_with_dynamic:
+ status: hasFix
+LintCode.avoid_as:
+ status: needsEvaluation
+LintCode.avoid_bool_literals_in_conditional_expressions:
+ status: needsEvaluation
+LintCode.avoid_catches_without_on_clauses:
+ status: needsEvaluation
+LintCode.avoid_catching_errors:
+ status: needsEvaluation
+LintCode.avoid_classes_with_only_static_members:
+ status: needsEvaluation
+LintCode.avoid_double_and_int_checks:
+ status: needsEvaluation
+LintCode.avoid_dynamic_calls:
+ status: needsEvaluation
+LintCode.avoid_empty_else:
+ status: hasFix
+LintCode.avoid_equals_and_hash_code_on_mutable_classes:
+ status: needsEvaluation
+LintCode.avoid_escaping_inner_quotes:
+ status: hasFix
+LintCode.avoid_field_initializers_in_const_classes:
+ status: needsEvaluation
+LintCode.avoid_final_parameters:
+ status: needsEvaluation
+LintCode.avoid_function_literals_in_foreach_calls:
+ status: hasFix
+LintCode.avoid_implementing_value_types:
+ status: needsEvaluation
+LintCode.avoid_init_to_null:
+ status: hasFix
+LintCode.avoid_js_rounded_ints:
+ status: needsEvaluation
+LintCode.avoid_multiple_declarations_per_line:
+ status: needsEvaluation
+LintCode.avoid_null_checks_in_equality_operators:
+ status: hasFix
+LintCode.avoid_positional_boolean_parameters:
+ status: needsEvaluation
+LintCode.avoid_print:
+ status: hasFix
+LintCode.avoid_private_typedef_functions:
+ status: hasFix
+LintCode.avoid_redundant_argument_values:
+ status: hasFix
+LintCode.avoid_relative_lib_imports:
+ status: hasFix
+LintCode.avoid_renaming_method_parameters:
+ status: needsEvaluation
+LintCode.avoid_return_types_on_setters:
+ status: hasFix
+LintCode.avoid_returning_null:
+ status: needsEvaluation
+LintCode.avoid_returning_null_for_future:
+ status: hasFix
+LintCode.avoid_returning_null_for_void:
+ status: hasFix
+LintCode.avoid_returning_this:
+ status: needsEvaluation
+LintCode.avoid_setters_without_getters:
+ status: needsEvaluation
+LintCode.avoid_shadowing_type_parameters:
+ status: needsEvaluation
+LintCode.avoid_single_cascade_in_expression_statements:
+ status: hasFix
+LintCode.avoid_slow_async_io:
+ status: needsEvaluation
+LintCode.avoid_type_to_string:
+ status: needsEvaluation
+LintCode.avoid_types_as_parameter_names:
+ status: hasFix
+LintCode.avoid_types_on_closure_parameters:
+ status: hasFix
+LintCode.avoid_unnecessary_containers:
+ status: hasFix
+LintCode.avoid_unused_constructor_parameters:
+ status: hasFix
+LintCode.avoid_void_async:
+ status: hasFix
+LintCode.avoid_web_libraries_in_flutter:
+ status: needsEvaluation
+LintCode.await_only_futures:
+ status: hasFix
+LintCode.camel_case_extensions:
+ status: needsEvaluation
+LintCode.camel_case_types:
+ status: needsEvaluation
+LintCode.cancel_subscriptions:
+ status: needsEvaluation
+LintCode.cascade_invocations:
+ status: needsEvaluation
+LintCode.cast_nullable_to_non_nullable:
+ status: needsEvaluation
+LintCode.close_sinks:
+ status: needsEvaluation
+LintCode.comment_references:
+ status: needsEvaluation
+LintCode.conditional_uri_does_not_exist:
+ status: needsEvaluation
+LintCode.constant_identifier_names:
+ status: needsEvaluation
+LintCode.control_flow_in_finally:
+ status: needsEvaluation
+LintCode.curly_braces_in_flow_control_structures:
+ status: hasFix
+LintCode.depend_on_referenced_packages:
+ status: needsFix
+LintCode.deprecated_consistency:
+ status: needsEvaluation
+LintCode.diagnostic_describe_all_properties:
+ status: hasFix
+LintCode.directives_ordering:
+ status: hasFix
+LintCode.do_not_use_environment:
+ status: needsEvaluation
+LintCode.empty_catches:
+ status: hasFix
+LintCode.empty_constructor_bodies:
+ status: hasFix
+LintCode.empty_statements:
+ status: hasFix
+LintCode.eol_at_end_of_file:
+ status: hasFix
+LintCode.exhaustive_cases:
+ status: hasFix
+LintCode.file_names:
+ status: needsEvaluation
+LintCode.flutter_style_todos:
+ status: needsEvaluation
+LintCode.hash_and_equals:
+ status: hasFix
+LintCode.implementation_imports:
+ status: needsEvaluation
+LintCode.invariant_booleans:
+ status: needsEvaluation
+LintCode.iterable_contains_unrelated_type:
+ status: needsEvaluation
+LintCode.join_return_with_assignment:
+ status: needsEvaluation
+LintCode.leading_newlines_in_multiline_strings:
+ status: hasFix
+LintCode.library_names:
+ status: needsEvaluation
+LintCode.library_prefixes:
+ status: needsEvaluation
+LintCode.library_private_types_in_public_api:
+ status: needsEvaluation
+LintCode.lines_longer_than_80_chars:
+ status: needsEvaluation
+LintCode.list_remove_unrelated_type:
+ status: needsEvaluation
+LintCode.literal_only_boolean_expressions:
+ status: needsEvaluation
+LintCode.missing_whitespace_between_adjacent_strings:
+ status: needsEvaluation
+LintCode.no_adjacent_strings_in_list:
+ status: needsEvaluation
+LintCode.no_default_cases:
+ status: needsEvaluation
+LintCode.no_duplicate_case_values:
+ status: hasFix
+LintCode.no_leading_underscores_for_library_prefixes:
+ status: hasFix
+LintCode.no_leading_underscores_for_local_identifiers:
+ status: hasFix
+LintCode.no_logic_in_create_state:
+ status: needsEvaluation
+LintCode.no_runtimeType_toString:
+ status: needsEvaluation
+LintCode.non_constant_identifier_names:
+ status: hasFix
+LintCode.noop_primitive_operations:
+ status: needsEvaluation
+LintCode.null_check_on_nullable_type_parameter:
+ status: hasFix
+ notes: |-
+ A second fix is possible, in which we make the type parameter not
+ potentially nullable, something like changing `T foo<T>()` to
+ `T foo<T extends Object>()` and `T foo<T extends num?>()` to
+ `T foo<T extends num>()`. This is particularly valuable in the first
+ case, where the choice to implicitly bound the type to `dynamic` may not
+ have been intentional.
+LintCode.null_closures:
+ status: hasFix
+LintCode.omit_local_variable_types:
+ status: hasFix
+LintCode.one_member_abstracts:
+ status: needsEvaluation
+LintCode.only_throw_errors:
+ status: needsEvaluation
+LintCode.overridden_fields:
+ status: needsEvaluation
+LintCode.package_api_docs:
+ status: needsEvaluation
+LintCode.package_names:
+ status: needsEvaluation
+LintCode.package_prefixed_library_names:
+ status: needsEvaluation
+LintCode.parameter_assignments:
+ status: needsEvaluation
+LintCode.prefer_adjacent_string_concatenation:
+ status: hasFix
+LintCode.prefer_asserts_in_initializer_lists:
+ status: needsEvaluation
+LintCode.prefer_asserts_with_message:
+ status: needsEvaluation
+LintCode.prefer_bool_in_asserts:
+ status: needsEvaluation
+LintCode.prefer_collection_literals:
+ status: hasFix
+LintCode.prefer_conditional_assignment:
+ status: hasFix
+LintCode.prefer_const_constructors:
+ status: hasFix
+LintCode.prefer_const_constructors_in_immutables:
+ status: hasFix
+LintCode.prefer_const_declarations:
+ status: hasFix
+LintCode.prefer_const_literals_to_create_immutables:
+ status: hasFix
+LintCode.prefer_constructors_over_static_methods:
+ status: needsEvaluation
+LintCode.prefer_contains:
+ status: hasFix
+LintCode.prefer_double_quotes:
+ status: hasFix
+LintCode.prefer_equal_for_default_values:
+ status: hasFix
+LintCode.prefer_expression_function_bodies:
+ status: hasFix
+LintCode.prefer_final_fields:
+ status: hasFix
+LintCode.prefer_final_in_for_each:
+ status: hasFix
+LintCode.prefer_final_locals:
+ status: hasFix
+LintCode.prefer_final_parameters:
+ status: hasFix
+LintCode.prefer_for_elements_to_map_fromIterable:
+ status: hasFix
+LintCode.prefer_foreach:
+ status: needsEvaluation
+LintCode.prefer_function_declarations_over_variables:
+ status: needsEvaluation
+LintCode.prefer_generic_function_type_aliases:
+ status: hasFix
+LintCode.prefer_if_elements_to_conditional_expressions:
+ status: hasFix
+LintCode.prefer_if_null_operators:
+ status: hasFix
+LintCode.prefer_initializing_formals:
+ status: hasFix
+LintCode.prefer_inlined_adds:
+ status: hasFix
+LintCode.prefer_int_literals:
+ status: hasFix
+LintCode.prefer_interpolation_to_compose_strings:
+ status: hasFix
+LintCode.prefer_is_empty:
+ status: hasFix
+LintCode.prefer_is_not_empty:
+ status: hasFix
+LintCode.prefer_is_not_operator:
+ status: hasFix
+LintCode.prefer_iterable_whereType:
+ status: hasFix
+LintCode.prefer_mixin:
+ status: needsEvaluation
+LintCode.prefer_null_aware_method_calls:
+ status: needsEvaluation
+LintCode.prefer_null_aware_operators:
+ status: hasFix
+LintCode.prefer_relative_imports:
+ status: hasFix
+LintCode.prefer_single_quotes:
+ status: hasFix
+LintCode.prefer_spread_collections:
+ status: hasFix
+LintCode.prefer_typing_uninitialized_variables:
+ status: hasFix
+LintCode.prefer_void_to_null:
+ status: hasFix
+LintCode.provide_deprecation_message:
+ status: needsEvaluation
+LintCode.public_member_api_docs:
+ status: needsEvaluation
+LintCode.recursive_getters:
+ status: needsEvaluation
+LintCode.require_trailing_commas:
+ status: hasFix
+LintCode.secure_pubspec_urls:
+ status: needsEvaluation
+LintCode.sized_box_for_whitespace:
+ status: hasFix
+LintCode.sized_box_shrink_expand:
+ status: needsEvaluation
+LintCode.slash_for_doc_comments:
+ status: hasFix
+LintCode.sort_child_properties_last:
+ status: hasFix
+LintCode.sort_constructors_first:
+ status: hasFix
+LintCode.sort_pub_dependencies:
+ status: needsEvaluation
+LintCode.sort_unnamed_constructors_first:
+ status: hasFix
+LintCode.super_goes_last:
+ status: needsEvaluation
+LintCode.test_types_in_equals:
+ status: needsEvaluation
+LintCode.throw_in_finally:
+ status: needsEvaluation
+LintCode.tighten_type_of_initializing_formals:
+ status: needsEvaluation
+LintCode.type_annotate_public_apis:
+ status: hasFix
+LintCode.type_init_formals:
+ status: hasFix
+LintCode.unawaited_futures:
+ status: hasFix
+LintCode.unnecessary_await_in_return:
+ status: needsEvaluation
+LintCode.unnecessary_brace_in_string_interps:
+ status: hasFix
+LintCode.unnecessary_const:
+ status: hasFix
+LintCode.unnecessary_constructor_name:
+ status: hasFix
+LintCode.unnecessary_final:
+ status: hasFix
+LintCode.unnecessary_getters_setters:
+ status: hasFix
+LintCode.unnecessary_lambdas:
+ status: hasFix
+LintCode.unnecessary_late:
+ status: hasFix
+LintCode.unnecessary_new:
+ status: hasFix
+LintCode.unnecessary_null_aware_assignments:
+ status: needsFix
+LintCode.unnecessary_null_checks:
+ status: needsEvaluation
+LintCode.unnecessary_null_in_if_null_operators:
+ status: hasFix
+LintCode.unnecessary_nullable_for_final_variable_declarations:
+ status: hasFix
+LintCode.unnecessary_overrides:
+ status: hasFix
+LintCode.unnecessary_parenthesis:
+ status: hasFix
+LintCode.unnecessary_raw_strings:
+ status: hasFix
+LintCode.unnecessary_statements:
+ status: needsEvaluation
+LintCode.unnecessary_string_escapes:
+ status: hasFix
+LintCode.unnecessary_string_interpolations:
+ status: hasFix
+LintCode.unnecessary_this:
+ status: hasFix
+LintCode.unrelated_type_equality_checks:
+ status: needsEvaluation
+LintCode.unsafe_html_attribute:
+ status: needsEvaluation
+LintCode.unsafe_html_method:
+ status: needsEvaluation
+LintCode.unsafe_html_constructor:
+ status: needsEvaluation
+LintCode.use_build_context_synchronously:
+ status: needsEvaluation
+LintCode.use_decorated_box:
+ status: needsEvaluation
+LintCode.use_full_hex_values_for_flutter_colors:
+ status: hasFix
+LintCode.use_function_type_syntax_for_parameters:
+ status: hasFix
+LintCode.use_if_null_to_convert_nulls_to_bools:
+ status: needsEvaluation
+LintCode.use_is_even_rather_than_modulo:
+ status: needsEvaluation
+LintCode.use_key_in_widget_constructors:
+ status: hasFix
+LintCode.use_late_for_private_fields_and_variables:
+ status: needsEvaluation
+LintCode.use_named_constants:
+ status: needsEvaluation
+LintCode.use_raw_strings:
+ status: hasFix
+LintCode.use_rethrow_when_possible:
+ status: hasFix
+LintCode.use_setters_to_change_properties:
+ status: needsEvaluation
+LintCode.use_string_buffers:
+ status: needsEvaluation
+LintCode.use_test_throws_matchers:
+ status: needsEvaluation
+LintCode.use_to_and_as_if_applicable:
+ status: needsEvaluation
+LintCode.valid_regexps:
+ status: needsEvaluation
+LintCode.void_checks:
+ status: needsEvaluation
+ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE:
+ status: needsEvaluation
+ManifestWarningCode.NO_TOUCHSCREEN_FEATURE:
+ status: needsEvaluation
+ManifestWarningCode.NON_RESIZABLE_ACTIVITY:
+ status: needsEvaluation
+ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE:
+ status: needsEvaluation
+ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY:
+ status: needsEvaluation
+ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE:
+ status: needsEvaluation
+ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_CLASS_MEMBER:
+ status: hasFix
+ParserErrorCode.ABSTRACT_ENUM:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_EXTERNAL_FIELD:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_LATE_FIELD:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_STATIC_FIELD:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_STATIC_METHOD:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE:
+ status: needsEvaluation
+ParserErrorCode.ABSTRACT_TYPEDEF:
+ status: needsEvaluation
+ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT:
+ status: needsEvaluation
+ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS:
+ status: needsEvaluation
+ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED:
+ status: needsEvaluation
+ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER:
+ status: needsEvaluation
+ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT:
+ status: needsEvaluation
+ParserErrorCode.BREAK_OUTSIDE_OF_LOOP:
+ status: needsEvaluation
+ParserErrorCode.CATCH_SYNTAX:
+ status: needsEvaluation
+ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS:
+ status: needsEvaluation
+ParserErrorCode.CLASS_IN_CLASS:
+ status: needsEvaluation
+ParserErrorCode.COLON_IN_PLACE_OF_IN:
+ status: needsEvaluation
+ParserErrorCode.CONFLICTING_MODIFIERS:
+ status: needsEvaluation
+ParserErrorCode.CONST_AND_FINAL:
+ status: needsEvaluation
+ParserErrorCode.CONST_CLASS:
+ status: needsEvaluation
+ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.CONST_ENUM:
+ status: needsEvaluation
+ParserErrorCode.CONST_FACTORY:
+ status: needsEvaluation
+ParserErrorCode.CONST_METHOD:
+ status: needsEvaluation
+ParserErrorCode.CONST_TYPEDEF:
+ status: needsEvaluation
+ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE:
+ status: needsEvaluation
+ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS:
+ status: needsEvaluation
+ since: ~2.15
+ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP:
+ status: needsEvaluation
+ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE:
+ status: needsEvaluation
+ParserErrorCode.COVARIANT_AND_STATIC:
+ status: needsEvaluation
+ParserErrorCode.COVARIANT_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.COVARIANT_MEMBER:
+ status: needsEvaluation
+ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION:
+ status: needsEvaluation
+ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE:
+ status: needsEvaluation
+ParserErrorCode.DEFERRED_AFTER_PREFIX:
+ status: needsEvaluation
+ParserErrorCode.DIRECTIVE_AFTER_DECLARATION:
+ status: needsEvaluation
+ParserErrorCode.DUPLICATE_DEFERRED:
+ status: needsEvaluation
+ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT:
+ status: needsEvaluation
+ParserErrorCode.DUPLICATE_PREFIX:
+ status: needsEvaluation
+ParserErrorCode.DUPLICATED_MODIFIER:
+ status: needsEvaluation
+ParserErrorCode.EMPTY_ENUM_BODY:
+ status: noFix
+ notes: |-
+ We can't guess at the names or number of the enum constants that should be
+ added.
+ParserErrorCode.ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS:
+ status: noFix
+ since: 2.17
+ notes: |-
+ We could potentially add `()`, but we generally don't have fixes for parse
+ errors because we assume the user is still typing and will soon fix the
+ problem.
+ParserErrorCode.ENUM_IN_CLASS:
+ status: needsEvaluation
+ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_CASE_OR_DEFAULT:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_CLASS_MEMBER:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_ELSE_OR_COMMA:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_EXECUTABLE:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_INSTEAD:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_STRING_LITERAL:
+ status: needsEvaluation
+ParserErrorCode.EXPECTED_TOKEN:
+ status: hasFix
+ParserErrorCode.EXPECTED_TYPE_NAME:
+ status: needsEvaluation
+ParserErrorCode.EXPERIMENT_NOT_ENABLED:
+ status: needsEvaluation
+ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE:
+ status: needsEvaluation
+ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER:
+ status: needsEvaluation
+ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_CLASS:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_ENUM:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_FACTORY_REDIRECTION:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_FIELD:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_GETTER_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_LATE_FIELD:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_METHOD_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_SETTER_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.EXTERNAL_TYPEDEF:
+ status: needsEvaluation
+ParserErrorCode.EXTRANEOUS_MODIFIER:
+ status: needsEvaluation
+ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION:
+ status: needsEvaluation
+ParserErrorCode.FACTORY_WITH_INITIALIZERS:
+ status: needsEvaluation
+ParserErrorCode.FACTORY_WITHOUT_BODY:
+ status: needsEvaluation
+ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS:
+ status: needsEvaluation
+ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.FINAL_AND_COVARIANT:
+ status: needsEvaluation
+ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.FINAL_AND_VAR:
+ status: needsEvaluation
+ParserErrorCode.FINAL_CLASS:
+ status: needsEvaluation
+ParserErrorCode.FINAL_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.FINAL_ENUM:
+ status: needsEvaluation
+ParserErrorCode.FINAL_METHOD:
+ status: needsEvaluation
+ParserErrorCode.FINAL_TYPEDEF:
+ status: needsEvaluation
+ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR:
+ status: needsEvaluation
+ParserErrorCode.GETTER_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.GETTER_IN_FUNCTION:
+ status: needsEvaluation
+ParserErrorCode.GETTER_WITH_PARAMETERS:
+ status: hasFix
+ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE:
+ status: needsEvaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS:
+ status: needsEvaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_ON:
+ status: needsEvaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_WITH:
+ status: needsEvaluation
+ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE:
+ status: needsEvaluation
+ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH:
+ status: needsEvaluation
+ParserErrorCode.INVALID_AWAIT_IN_FOR:
+ status: needsEvaluation
+ParserErrorCode.INVALID_CODE_POINT:
+ status: needsEvaluation
+ParserErrorCode.INVALID_COMMENT_REFERENCE:
+ status: needsEvaluation
+ParserErrorCode.INVALID_CONSTRUCTOR_NAME:
+ status: needsEvaluation
+ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE:
+ status: needsEvaluation
+ParserErrorCode.INVALID_HEX_ESCAPE:
+ status: needsEvaluation
+ParserErrorCode.INVALID_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION:
+ status: needsEvaluation
+ParserErrorCode.INVALID_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.INVALID_OPERATOR_FOR_SUPER:
+ status: needsEvaluation
+ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER:
+ status: needsEvaluation
+ParserErrorCode.INVALID_STAR_AFTER_ASYNC:
+ status: needsEvaluation
+ParserErrorCode.INVALID_SUPER_IN_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.INVALID_SYNC:
+ status: needsEvaluation
+ParserErrorCode.INVALID_THIS_IN_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.INVALID_UNICODE_ESCAPE:
+ status: needsEvaluation
+ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION:
+ status: needsEvaluation
+ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST:
+ status: needsEvaluation
+ParserErrorCode.LITERAL_WITH_CLASS_AND_NEW:
+ status: needsEvaluation
+ParserErrorCode.LITERAL_WITH_CLASS:
+ status: needsEvaluation
+ParserErrorCode.LITERAL_WITH_NEW:
+ status: needsEvaluation
+ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER:
+ status: needsEvaluation
+ParserErrorCode.MEMBER_WITH_CLASS_NAME:
+ status: needsEvaluation
+ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR:
+ status: needsEvaluation
+ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.MISSING_CATCH_OR_FINALLY:
+ status: needsEvaluation
+ParserErrorCode.MISSING_CLOSING_PARENTHESIS:
+ status: needsEvaluation
+ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE:
+ status: hasFix
+ParserErrorCode.MISSING_ENUM_BODY:
+ status: needsEvaluation
+ParserErrorCode.MISSING_EXPRESSION_IN_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.MISSING_EXPRESSION_IN_THROW:
+ status: needsEvaluation
+ParserErrorCode.MISSING_FUNCTION_BODY:
+ status: hasFix
+ParserErrorCode.MISSING_FUNCTION_KEYWORD:
+ status: needsEvaluation
+ParserErrorCode.MISSING_FUNCTION_PARAMETERS:
+ status: needsEvaluation
+ParserErrorCode.MISSING_GET:
+ status: needsEvaluation
+ParserErrorCode.MISSING_IDENTIFIER:
+ status: needsEvaluation
+ParserErrorCode.MISSING_INITIALIZER:
+ status: needsEvaluation
+ParserErrorCode.MISSING_KEYWORD_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.MISSING_METHOD_PARAMETERS:
+ status: needsEvaluation
+ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER:
+ status: needsEvaluation
+ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE:
+ status: needsEvaluation
+ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE:
+ status: needsEvaluation
+ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT:
+ status: needsEvaluation
+ParserErrorCode.MISSING_STAR_AFTER_SYNC:
+ status: needsEvaluation
+ParserErrorCode.MISSING_STATEMENT:
+ status: needsEvaluation
+ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP:
+ status: needsEvaluation
+ParserErrorCode.MISSING_TYPEDEF_PARAMETERS:
+ status: needsEvaluation
+ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH:
+ status: needsEvaluation
+ParserErrorCode.MIXED_PARAMETER_GROUPS:
+ status: needsEvaluation
+ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.MODIFIER_OUT_OF_ORDER:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_ON_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS:
+ status: needsEvaluation
+ParserErrorCode.MULTIPLE_WITH_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.NAMED_FUNCTION_EXPRESSION:
+ status: needsEvaluation
+ParserErrorCode.NAMED_FUNCTION_TYPE:
+ status: needsEvaluation
+ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP:
+ status: needsEvaluation
+ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE:
+ status: needsEvaluation
+ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION:
+ status: needsEvaluation
+ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE:
+ status: needsEvaluation
+ParserErrorCode.NON_CONSTRUCTOR_FACTORY:
+ status: needsEvaluation
+ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME:
+ status: needsEvaluation
+ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART:
+ status: needsEvaluation
+ParserErrorCode.NON_STRING_LITERAL_AS_URI:
+ status: needsEvaluation
+ParserErrorCode.NON_USER_DEFINABLE_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS:
+ status: needsEvaluation
+ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER:
+ status: needsEvaluation
+ParserErrorCode.OUT_OF_ORDER_CLAUSES:
+ status: needsEvaluation
+ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT:
+ status: needsEvaluation
+ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP:
+ status: needsEvaluation
+ParserErrorCode.PREFIX_AFTER_COMBINATOR:
+ status: needsEvaluation
+ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY:
+ status: needsEvaluation
+ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.SETTER_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.SETTER_IN_FUNCTION:
+ status: needsEvaluation
+ParserErrorCode.STACK_OVERFLOW:
+ status: needsEvaluation
+ParserErrorCode.STATIC_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.STATIC_GETTER_WITHOUT_BODY:
+ status: needsEvaluation
+ParserErrorCode.STATIC_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.STATIC_SETTER_WITHOUT_BODY:
+ status: needsEvaluation
+ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION:
+ status: needsEvaluation
+ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE:
+ status: needsEvaluation
+ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES:
+ status: needsEvaluation
+ParserErrorCode.TOP_LEVEL_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE:
+ status: needsEvaluation
+ParserErrorCode.TYPE_BEFORE_FACTORY:
+ status: needsEvaluation
+ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR:
+ status: needsEvaluation
+ParserErrorCode.TYPE_PARAMETER_ON_OPERATOR:
+ status: needsEvaluation
+ParserErrorCode.TYPEDEF_IN_CLASS:
+ status: needsEvaluation
+ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP:
+ status: needsEvaluation
+ParserErrorCode.UNEXPECTED_TOKEN:
+ status: needsEvaluation
+ParserErrorCode.UNEXPECTED_TOKENS:
+ status: needsEvaluation
+ParserErrorCode.VAR_AND_TYPE:
+ status: needsEvaluation
+ParserErrorCode.VAR_AS_TYPE_NAME:
+ status: hasFix
+ParserErrorCode.VAR_CLASS:
+ status: needsEvaluation
+ParserErrorCode.VAR_ENUM:
+ status: needsEvaluation
+ParserErrorCode.VAR_RETURN_TYPE:
+ status: needsEvaluation
+ParserErrorCode.VAR_TYPEDEF:
+ status: needsEvaluation
+ParserErrorCode.VOID_WITH_TYPE_ARGUMENTS:
+ status: needsEvaluation
+ParserErrorCode.WITH_BEFORE_EXTENDS:
+ status: needsEvaluation
+ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER:
+ status: needsEvaluation
+ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP:
+ status: needsEvaluation
+PubspecWarningCode.ASSET_DOES_NOT_EXIST:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.ASSET_DIRECTORY_DOES_NOT_EXIST:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.ASSET_FIELD_NOT_LIST:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.ASSET_NOT_STRING:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.DEPENDENCIES_FIELD_NOT_MAP:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.DEPRECATED_FIELD:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.FLUTTER_FIELD_NOT_MAP:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.INVALID_DEPENDENCY:
+ status: needsEvaluation
+PubspecWarningCode.MISSING_NAME:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.NAME_NOT_STRING:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.PATH_DOES_NOT_EXIST:
+ status: needsEvaluation
+PubspecWarningCode.PATH_NOT_POSIX:
+ status: needsEvaluation
+ since: ~2.15
+PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST:
+ status: needsEvaluation
+PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY:
+ status: needsEvaluation
+ since: ~2.15
+ScannerErrorCode.EXPECTED_TOKEN:
+ status: needsEvaluation
+ScannerErrorCode.ILLEGAL_CHARACTER:
+ status: needsEvaluation
+ScannerErrorCode.MISSING_DIGIT:
+ status: needsEvaluation
+ScannerErrorCode.MISSING_HEX_DIGIT:
+ status: needsEvaluation
+ScannerErrorCode.MISSING_IDENTIFIER:
+ status: needsEvaluation
+ScannerErrorCode.MISSING_QUOTE:
+ status: needsEvaluation
+ScannerErrorCode.UNABLE_GET_CONTENT:
+ status: needsEvaluation
+ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING:
+ status: needsEvaluation
+ScannerErrorCode.UNSUPPORTED_OPERATOR:
+ status: needsEvaluation
+ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT:
+ status: needsEvaluation
+ScannerErrorCode.UNTERMINATED_STRING_LITERAL:
+ status: needsEvaluation
+StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION:
+ status: hasFix
+StaticWarningCode.INVALID_NULL_AWARE_OPERATOR:
+ status: hasFix
+StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT:
+ status: hasFix
+StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED:
+ status: needsEvaluation
+StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL:
+ status: needsEvaluation
+StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH:
+ status: hasFix
+StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION:
+ status: hasFix
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index b4fb0b2..d3411f7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -508,6 +508,16 @@
DartFixKindPriority.IN_FILE,
"Convert to 'package:' imports everywhere in file",
);
+ static const CONVERT_TO_RAW_STRING = FixKind(
+ 'dart.fix.convert.toRawString',
+ DartFixKindPriority.DEFAULT,
+ 'Convert to raw string',
+ );
+ static const CONVERT_TO_RAW_STRING_MULTI = FixKind(
+ 'dart.fix.convert.toRawString.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Convert to raw strings everywhere in file',
+ );
static const CONVERT_TO_RELATIVE_IMPORT = FixKind(
'dart.fix.convert.toRelativeImport',
DartFixKindPriority.DEFAULT,
@@ -941,6 +951,16 @@
DartFixKindPriority.IN_FILE,
'Remove unnecessary interpolation braces everywhere in file',
);
+ static const REMOVE_LEADING_UNDERSCORE = FixKind(
+ 'dart.fix.remove.leadingUnderscore',
+ DartFixKindPriority.DEFAULT,
+ 'Remove leading underscore',
+ );
+ static const REMOVE_LEADING_UNDERSCORE_MULTI = FixKind(
+ 'dart.fix.remove.leadingUnderscore.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Remove leading underscores in file',
+ );
static const REMOVE_METHOD_DECLARATION = FixKind(
'dart.fix.remove.methodDeclaration',
DartFixKindPriority.DEFAULT,
@@ -1053,6 +1073,16 @@
DartFixKindPriority.IN_FILE,
'Remove unnecessary const keywords everywhere in file',
);
+ static const REMOVE_UNNECESSARY_LATE = FixKind(
+ 'dart.fix.remove.unnecessaryLate',
+ DartFixKindPriority.DEFAULT,
+ 'Remove unnecessary late keyword',
+ );
+ static const REMOVE_UNNECESSARY_LATE_MULTI = FixKind(
+ 'dart.fix.remove.unnecessaryLate.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Remove unnecessary late keywords everywhere in file',
+ );
static const REMOVE_UNNECESSARY_NEW = FixKind(
'dart.fix.remove.unnecessaryNew',
DartFixKindPriority.DEFAULT,
@@ -1238,6 +1268,16 @@
DartFixKindPriority.IN_FILE,
"Replace 'new' with 'const' where possible in file",
);
+ static const REPLACE_NULL_CHECK_WITH_CAST = FixKind(
+ 'dart.fix.replace.nullCheckWithCast',
+ DartFixKindPriority.DEFAULT,
+ 'Replace null check with a cast',
+ );
+ static const REPLACE_NULL_CHECK_WITH_CAST_MULTI = FixKind(
+ 'dart.fix.replace.nullCheckWithCast.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Replace null checks with casts in file',
+ );
static const REPLACE_NULL_WITH_CLOSURE = FixKind(
'dart.fix.replace.nullWithClosure',
DartFixKindPriority.DEFAULT,
@@ -1278,6 +1318,11 @@
DartFixKindPriority.DEFAULT,
"Return 'Future<{0}>'",
);
+ static const REPLACE_RETURN_TYPE_FUTURE_MULTI = FixKind(
+ 'dart.fix.replace.returnTypeFuture.multi',
+ DartFixKindPriority.IN_FILE,
+ "Return a 'Future' where required in file.",
+ );
static const REPLACE_RETURN_TYPE_ITERABLE = FixKind(
'dart.fix.replace.returnTypeIterable',
DartFixKindPriority.DEFAULT,
@@ -1425,6 +1470,26 @@
DartFixKindPriority.IN_FILE,
'Move child properties to ends of arguments everywhere in file',
);
+ static const SORT_CONSTRUCTOR_FIRST = FixKind(
+ 'dart.fix.sort.sortConstructorFirst',
+ DartFixKindPriority.DEFAULT,
+ 'Move before other members',
+ );
+ static const SORT_CONSTRUCTOR_FIRST_MULTI = FixKind(
+ 'dart.fix.sort.sortConstructorFirst.multi',
+ DartFixKindPriority.DEFAULT,
+ 'Move all constructors before other members',
+ );
+ static const SORT_UNNAMED_CONSTRUCTOR_FIRST = FixKind(
+ 'dart.fix.sort.sortUnnamedConstructorFirst',
+ DartFixKindPriority.DEFAULT,
+ 'Move before named constructors',
+ );
+ static const SORT_UNNAMED_CONSTRUCTOR_FIRST_MULTI = FixKind(
+ 'dart.fix.sort.sortUnnamedConstructorFirst.multi',
+ DartFixKindPriority.DEFAULT,
+ 'Move all unnamed constructors before named constructors',
+ );
static const UPDATE_SDK_CONSTRAINTS = FixKind(
'dart.fix.updateSdkConstraints',
DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
index 4f0972c..bd0dde1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
@@ -114,7 +114,7 @@
if (node is ExtensionOverride) {
return node.typeArguments;
} else if (node is InstanceCreationExpression) {
- return node.constructorName.type2.typeArguments;
+ return node.constructorName.type.typeArguments;
} else if (node is InvocationExpression) {
return node.typeArguments;
} else if (node is NamedType) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index e512626..0157194 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -96,7 +96,7 @@
}
} else if (node is InstanceCreationExpression) {
var name = node.constructorName;
- var className = _nameFromIdentifier(name.type2.name);
+ var className = _nameFromIdentifier(name.type.name);
var constructorName = name.name?.name ?? '';
if (components[0] == constructorName && components[1] == className) {
return true;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index acceb63..beda821 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -223,7 +223,7 @@
// get a more exact matcher.
// TODO(brianwilkerson) Use 'new' for the name of the unnamed constructor.
var constructorName = node.name?.name ?? ''; // ?? 'new';
- var className = node.type2.name.simpleName;
+ var className = node.type.name.simpleName;
_addMatcher(
components: [constructorName, className],
kinds: const [ElementKind.constructorKind],
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
index c71ea13..7b052fa 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
@@ -6,6 +6,7 @@
import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
+import 'package:analysis_server/src/utilities/index_range.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -109,14 +110,14 @@
}
}
- var insertionRanges = argumentsToInsert.contiguousSubRanges.toList();
- var deletionRanges = argumentsToDelete.contiguousSubRanges.toList();
+ var insertionRanges = IndexRange.contiguousSubRanges(argumentsToInsert);
+ var deletionRanges = IndexRange.contiguousSubRanges(argumentsToDelete);
if (insertionRanges.isNotEmpty) {
/// Write to the [builder] the new arguments in the [insertionRange]. If
/// [needsInitialComma] is `true` then we need to write a comma before the
/// first of the new arguments.
void writeInsertionRange(DartEditBuilder builder,
- _IndexRange insertionRange, bool needsInitialComma) {
+ IndexRange insertionRange, bool needsInitialComma) {
var needsComma = needsInitialComma;
for (var argumentIndex = insertionRange.lower;
argumentIndex <= insertionRange.upper;
@@ -199,7 +200,7 @@
}
if (upper >= lower) {
builder.addInsertion(offset, (builder) {
- writeInsertionRange(builder, _IndexRange(lower, upper),
+ writeInsertionRange(builder, IndexRange(lower, upper),
nextRemaining > 0 || insertionCount > 0);
});
}
@@ -255,7 +256,7 @@
/// Return the range from the list of [ranges] that contains the given
/// [index], or `null` if there is no such range.
- _IndexRange? _rangeContaining(List<_IndexRange> ranges, int index) {
+ IndexRange? _rangeContaining(List<IndexRange> ranges, int index) {
for (var range in ranges) {
if (index >= range.lower && index <= range.upper) {
return range;
@@ -295,44 +296,3 @@
/// invocation site.
_Data(this.argumentList);
}
-
-/// A range of indexes within a list.
-class _IndexRange {
- /// The index of the first element in the range.
- final int lower;
-
- /// The index of the last element in the range. This will be the same as the
- /// [lower] if there is a single element in the range.
- final int upper;
-
- /// Initialize a newly created range.
- _IndexRange(this.lower, this.upper);
-
- /// Return the number of indices in this range.
- int get count => upper - lower + 1;
-
- @override
- String toString() => '[$lower..$upper]';
-}
-
-extension on List<int> {
- Iterable<_IndexRange> get contiguousSubRanges sync* {
- if (isEmpty) {
- return;
- }
- var lower = this[0];
- var previous = lower;
- var index = 1;
- while (index < length) {
- var current = this[index];
- if (current == previous + 1) {
- previous = current;
- } else {
- yield _IndexRange(lower, previous);
- lower = previous = current;
- }
- index++;
- }
- yield _IndexRange(lower, previous);
- }
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
index 92e23b9..6d36d486 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
@@ -99,7 +99,7 @@
}
}
} else if (node is ConstructorName) {
- var typeName = node.type2.name;
+ var typeName = node.type.name;
SimpleIdentifier classNameNode;
if (typeName is SimpleIdentifier) {
classNameNode = typeName;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index bae5fc7..11db925 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -61,6 +61,7 @@
import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware_spread.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_on_type.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_raw_string.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
@@ -117,6 +118,7 @@
import 'package:analysis_server/src/services/correction/dart/remove_if_null_operator.dart';
import 'package:analysis_server/src/services/correction/dart/remove_initializer.dart';
import 'package:analysis_server/src/services/correction/dart/remove_interpolation_braces.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_leading_underscore.dart';
import 'package:analysis_server/src/services/correction/dart/remove_method_declaration.dart';
import 'package:analysis_server/src/services/correction/dart/remove_name_from_combinator.dart';
import 'package:analysis_server/src/services/correction/dart/remove_non_null_assertion.dart';
@@ -129,6 +131,7 @@
import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_raw_string.dart';
@@ -150,6 +153,7 @@
import 'package:analysis_server/src/services/correction/dart/replace_final_with_const.dart';
import 'package:analysis_server/src/services/correction/dart/replace_final_with_var.dart';
import 'package:analysis_server/src/services/correction/dart/replace_new_with_const.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_null_check_with_cast.dart';
import 'package:analysis_server/src/services/correction/dart/replace_null_with_closure.dart';
import 'package:analysis_server/src/services/correction/dart/replace_return_type.dart';
import 'package:analysis_server/src/services/correction/dart/replace_return_type_future.dart';
@@ -169,6 +173,8 @@
import 'package:analysis_server/src/services/correction/dart/replace_with_tear_off.dart';
import 'package:analysis_server/src/services/correction/dart/replace_with_var.dart';
import 'package:analysis_server/src/services/correction/dart/sort_child_property_last.dart';
+import 'package:analysis_server/src/services/correction/dart/sort_constructor_first.dart';
+import 'package:analysis_server/src/services/correction/dart/sort_unnamed_constructor_first.dart';
import 'package:analysis_server/src/services/correction/dart/update_sdk_constraints.dart';
import 'package:analysis_server/src/services/correction/dart/use_const.dart';
import 'package:analysis_server/src/services/correction/dart/use_curly_braces.dart';
@@ -344,6 +350,9 @@
LintNames.always_specify_types: [
AddTypeAnnotation.newInstanceBulkFixable,
],
+ LintNames.always_use_package_imports: [
+ ConvertToPackageImport.newInstance,
+ ],
LintNames.annotate_overrides: [
AddOverride.newInstance,
],
@@ -406,6 +415,9 @@
LintNames.avoid_unnecessary_containers: [
FlutterRemoveWidget.newInstance,
],
+ LintNames.avoid_void_async: [
+ ReplaceReturnTypeFuture.newInstance,
+ ],
LintNames.await_only_futures: [
RemoveAwait.newInstance,
],
@@ -443,9 +455,18 @@
LintNames.no_duplicate_case_values: [
RemoveDuplicateCase.newInstance,
],
+ LintNames.no_leading_underscores_for_library_prefixes: [
+ RemoveLeadingUnderscore.newInstance,
+ ],
+ LintNames.no_leading_underscores_for_local_identifiers: [
+ RemoveLeadingUnderscore.newInstance,
+ ],
LintNames.non_constant_identifier_names: [
RenameToCamelCase.newInstance,
],
+ LintNames.null_check_on_nullable_type_parameter: [
+ ReplaceNullCheckWithCast.newInstance,
+ ],
LintNames.null_closures: [
ReplaceNullWithClosure.newInstance,
],
@@ -567,6 +588,12 @@
LintNames.sort_child_properties_last: [
SortChildPropertyLast.newInstance,
],
+ LintNames.sort_constructors_first: [
+ SortConstructorFirst.newInstance,
+ ],
+ LintNames.sort_unnamed_constructors_first: [
+ SortUnnamedConstructorFirst.newInstance,
+ ],
LintNames.type_annotate_public_apis: [
AddTypeAnnotation.newInstanceBulkFixable,
],
@@ -594,6 +621,9 @@
LintNames.unnecessary_lambdas: [
ReplaceWithTearOff.newInstance,
],
+ LintNames.unnecessary_late: [
+ RemoveUnnecessaryLate.newInstance,
+ ],
LintNames.unnecessary_new: [
RemoveUnnecessaryNew.newInstance,
],
@@ -630,6 +660,9 @@
LintNames.use_key_in_widget_constructors: [
AddKeyToConstructors.newInstance,
],
+ LintNames.use_raw_strings: [
+ ConvertToRawString.newInstance,
+ ],
LintNames.use_rethrow_when_possible: [
UseRethrow.newInstance,
],
@@ -662,12 +695,7 @@
DataDriven.newInstance,
ImportLibrary.forType,
],
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT: [
- AddSuperConstructorInvocation.newInstance,
- ],
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS: [
+ CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS: [
AddSuperConstructorInvocation.newInstance,
],
CompileTimeErrorCode.INVALID_ANNOTATION: [
diff --git a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
index da822b8..93de681 100644
--- a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
+++ b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
@@ -181,7 +181,7 @@
name = expression.methodName.name;
} else if (expression is InstanceCreationExpression) {
var constructorName = expression.constructorName;
- var namedType = constructorName.type2;
+ var namedType = constructorName.type;
var typeNameIdentifier = namedType.name;
// new ClassName()
if (typeNameIdentifier is SimpleIdentifier) {
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
index e4438f2..f3abafa 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
@@ -69,7 +69,7 @@
/// Organize all [Directive]s.
void _organizeDirectives() {
- var lineInfo = unit.lineInfo ?? LineInfo.fromContent(code);
+ var lineInfo = unit.lineInfo;
var hasLibraryDirective = false;
var directives = <_DirectiveInfo>[];
// Track the end offset of any library-level comment/annotations that should
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index d257984..7fdb383 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -95,6 +95,8 @@
for (var unitMember in unit.declarations) {
if (unitMember is ClassOrMixinDeclaration) {
_sortClassMembers(unitMember.members);
+ } else if (unitMember is EnumDeclaration) {
+ _sortClassMembers(unitMember.members);
} else if (unitMember is ExtensionDeclaration) {
_sortClassMembers(unitMember.members);
}
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 9066429..bdb7b99 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -29,6 +29,7 @@
show SourceChange, SourceEdit;
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;
/// Adds edits to the given [change] that ensure that all the [libraries] are
@@ -160,6 +161,14 @@
return collector.references;
}
+/// Return references to the [element] inside the [root] node.
+List<SimpleIdentifier> findPrefixElementReferences(
+ AstNode root, PrefixElement element) {
+ var collector = _ElementReferenceCollector(element);
+ root.accept(collector);
+ return collector.references;
+}
+
/// TODO(scheglov) replace with nodes once there will be
/// [CompilationUnit.getComments].
///
@@ -240,6 +249,9 @@
if (node is CompilationUnit) {
return member;
}
+ if (node is EnumDeclaration) {
+ return member;
+ }
member = node;
}
return null;
@@ -322,7 +334,7 @@
/// Computes the best URI to import [what] into [from].
String getLibrarySourceUri(
path.Context pathContext, LibraryElement from, Uri what) {
- if (what.scheme == 'file') {
+ if (what.isScheme('file')) {
var fromFolder = pathContext.dirname(from.source.fullName);
var relativeFile = pathContext.relative(what.path, from: fromFolder);
return pathContext.split(relativeFile).join('/');
@@ -788,7 +800,7 @@
// end
var endOffset = sourceRange.end;
var afterEndLineOffset = endOffset;
- var lineInfo = unit.lineInfo!;
+ var lineInfo = unit.lineInfo;
var lineStart = lineInfo
.getOffsetOfLine(lineInfo.getLocation(startLineOffset).lineNumber - 1);
if (lineStart == startLineOffset) {
@@ -982,6 +994,39 @@
return ClassMemberLocation(prefix, offset, suffix);
}
+ ClassMemberLocation? prepareEnumNewConstructorLocation(
+ EnumDeclaration enumDeclaration,
+ ) {
+ var indent = getIndent(1);
+
+ var targetMember = enumDeclaration.members
+ .where((e) => e is FieldDeclaration || e is ConstructorDeclaration)
+ .lastOrNull;
+ if (targetMember != null) {
+ return ClassMemberLocation(
+ endOfLine + endOfLine + indent,
+ targetMember.end,
+ '',
+ );
+ }
+
+ var semicolon = enumDeclaration.semicolon;
+ if (semicolon != null) {
+ return ClassMemberLocation(
+ endOfLine + endOfLine + indent,
+ semicolon.end,
+ '',
+ );
+ }
+
+ var lastConstant = enumDeclaration.constants.last;
+ return ClassMemberLocation(
+ ';' + endOfLine + endOfLine + indent,
+ lastConstant.end,
+ '',
+ );
+ }
+
ClassMemberLocation? prepareNewClassMemberLocation(
CompilationUnitMember declaration,
bool Function(ClassMember existingMember) shouldSkip) {
diff --git a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
index ee34219..d6832cf 100644
--- a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
@@ -295,15 +295,15 @@
// ClassDeclarations) and super.visitClassTypeAlias is not sufficient.
//
_handleRefEdge(
- node.superclass2.name.staticElement,
+ node.superclass.name.staticElement,
const <String>[schema.REF_EDGE],
- syntacticEntity: node.superclass2,
+ syntacticEntity: node.superclass,
);
// TODO(jwren) refactor the following lines into a method that can be used
// by visitClassDeclaration()
// extends
var recordSupertypeVName = _vNameFromElement(
- node.superclass2.name.staticElement, schema.RECORD_KIND);
+ node.superclass.name.staticElement, schema.RECORD_KIND);
addEdge(_enclosingClassVName!, schema.EXTENDS_EDGE, recordSupertypeVName);
// implements
@@ -659,7 +659,7 @@
// assert (element.enclosingElement != null);
}
// visit children
- _safelyVisitList(constructorName.type2.typeArguments?.arguments);
+ _safelyVisitList(constructorName.type.typeArguments?.arguments);
_safelyVisit(node.argumentList);
}
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 90e9fbe..472ddf8 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -9,6 +9,7 @@
static const String always_require_non_null_named_parameters =
'always_require_non_null_named_parameters';
static const String always_specify_types = 'always_specify_types';
+ static const String always_use_package_imports = 'always_use_package_imports';
static const String annotate_overrides = 'annotate_overrides';
static const String avoid_annotating_with_dynamic =
'avoid_annotating_with_dynamic';
@@ -42,6 +43,7 @@
'avoid_unused_constructor_parameters';
static const String avoid_unnecessary_containers =
'avoid_unnecessary_containers';
+ static const String avoid_void_async = 'avoid_void_async';
static const String await_only_futures = 'await_only_futures';
static const String curly_braces_in_flow_control_structures =
'curly_braces_in_flow_control_structures';
@@ -57,8 +59,14 @@
static const String leading_newlines_in_multiline_strings =
'leading_newlines_in_multiline_strings';
static const String no_duplicate_case_values = 'no_duplicate_case_values';
+ static const String no_leading_underscores_for_library_prefixes =
+ 'no_leading_underscores_for_library_prefixes';
+ static const String no_leading_underscores_for_local_identifiers =
+ 'no_leading_underscores_for_local_identifiers';
static const String non_constant_identifier_names =
'non_constant_identifier_names';
+ static const String null_check_on_nullable_type_parameter =
+ 'null_check_on_nullable_type_parameter';
static const String null_closures = 'null_closures';
static const String omit_local_variable_types = 'omit_local_variable_types';
static const String prefer_adjacent_string_concatenation =
@@ -112,6 +120,8 @@
static const String slash_for_doc_comments = 'slash_for_doc_comments';
static const String sort_child_properties_last = 'sort_child_properties_last';
static const String sort_constructors_first = 'sort_constructors_first';
+ static const String sort_unnamed_constructors_first =
+ 'sort_unnamed_constructors_first';
static const String type_annotate_public_apis = 'type_annotate_public_apis';
static const String type_init_formals = 'type_init_formals';
static const String unawaited_futures = 'unawaited_futures';
@@ -124,6 +134,7 @@
static const String unnecessary_getters_setters =
'unnecessary_getters_setters';
static const String unnecessary_lambdas = 'unnecessary_lambdas';
+ static const String unnecessary_late = 'unnecessary_late';
static const String unnecessary_new = 'unnecessary_new';
static const String unnecessary_null_in_if_null_operators =
'unnecessary_null_in_if_null_operators';
@@ -142,5 +153,6 @@
'use_function_type_syntax_for_parameters';
static const String use_key_in_widget_constructors =
'use_key_in_widget_constructors';
+ static const String use_raw_strings = 'use_raw_strings';
static const String use_rethrow_when_possible = 'use_rethrow_when_possible';
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 565b9a8..5aaf8ad 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -52,7 +52,9 @@
}
// method
var field = element.variable;
- if (field is FieldElement && field.enclosingElement is ClassElement) {
+ if (field is FieldElement &&
+ (field.enclosingElement is ClassElement ||
+ field.enclosingElement is ExtensionElement)) {
var elements = await getHierarchyMembers(searchEngine, field);
await Future.forEach(elements, (ClassMemberElement member) async {
if (member is FieldElement) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 163572e..b33e29a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -435,8 +435,13 @@
return validateCreateFunction(searchEngine, libraryElement, name);
}
// method of class
+ ClassElement? classElement;
if (parent is ClassDeclaration) {
- var classElement = parent.declaredElement!;
+ classElement = parent.declaredElement!;
+ } else if (parent is EnumDeclaration) {
+ classElement = parent.declaredElement!;
+ }
+ if (classElement != null) {
return validateCreateMethod(searchEngine,
AnalysisSessionHelper(resolveResult.session), classElement, name);
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 1f66fe6..8a99365 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -161,9 +161,10 @@
{
var enclosingClassElement = getEnclosingClassElement(node);
if (enclosingClassElement != null) {
- var elements = <ClassElement>{};
- elements.add(enclosingClassElement);
- elements.addAll(getSuperClasses(enclosingClassElement));
+ var elements = [
+ ...enclosingClassElement.allSupertypes.map((e) => e.element),
+ enclosingClassElement,
+ ];
for (var classElement in elements) {
var classMembers = getChildren(classElement);
for (var classMemberElement in classMembers) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index f3cae42..caa3706 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -22,16 +23,16 @@
final ResourceProvider resourceProvider;
final pathos.Context pathContext;
final RefactoringWorkspace refactoringWorkspace;
- final ResolvedUnitResult resolvedUnit;
late AnalysisDriver driver;
+ late AnalysisSession _session;
late String oldFile;
late String newFile;
final packagePrefixedStringPattern = RegExp(r'''^r?['"]+package:''');
- MoveFileRefactoringImpl(this.resourceProvider, this.refactoringWorkspace,
- this.resolvedUnit, this.oldFile)
+ MoveFileRefactoringImpl(
+ this.resourceProvider, this.refactoringWorkspace, this.oldFile)
: pathContext = resourceProvider.pathContext;
@override
@@ -54,7 +55,8 @@
}
driver = drivers.first;
- if (!driver.resourceProvider.getFile(oldFile).exists) {
+ _session = driver.currentSession;
+ if (!resourceProvider.getResource(oldFile).exists) {
return RefactoringStatus.fatal('$oldFile does not exist.');
}
@@ -68,24 +70,53 @@
@override
Future<SourceChange> createChange() async {
- var changeBuilder = ChangeBuilder(session: resolvedUnit.session);
+ var changeBuilder = ChangeBuilder(session: _session);
+
+ final resource = resourceProvider.getResource(oldFile);
+
+ try {
+ await _appendChangesForResource(changeBuilder, resource, newFile);
+ } on InconsistentAnalysisException {
+ // If an InconsistentAnalysisException occurs, it's likely the user
+ // modified the source and is no longer interested in the results.
+ return SourceChange('Refactor cancelled by file modifications');
+ }
+
+ // If cancellation was requested the results may be incomplete so return
+ // a new empty change instead of a partial one with a descriptive name
+ // so it's clear from any logs that cancellation was processed.
+ if (isCancellationRequested) {
+ return SourceChange('Refactor cancelled');
+ }
+
+ return changeBuilder.sourceChange;
+ }
+
+ Future<void> _appendChangeForFile(
+ ChangeBuilder changeBuilder, File file, String newPath) async {
+ var oldPath = file.path;
+ var oldDir = pathContext.dirname(oldPath);
+ var newDir = pathContext.dirname(newPath);
+
+ final resolvedUnit = await _session.getResolvedUnit(file.path);
+ if (resolvedUnit is! ResolvedUnitResult) {
+ return;
+ }
+
var element = resolvedUnit.unit.declaredElement;
if (element == null) {
- return changeBuilder.sourceChange;
+ return;
}
var libraryElement = element.library;
- final oldDir = pathContext.dirname(oldFile);
- final newDir = pathContext.dirname(newFile);
-
// If this element is a library, update outgoing references inside the file.
if (element == libraryElement.definingCompilationUnit) {
// Handle part-of directives in this library
var libraryResult = await driver.currentSession
.getResolvedLibraryByElement(libraryElement);
if (libraryResult is! ResolvedLibraryResult) {
- return changeBuilder.sourceChange;
+ return;
}
var definingUnitResult = libraryResult.units.first;
for (var result in libraryResult.units) {
@@ -99,9 +130,7 @@
await changeBuilder.addDartFileEdit(
result.unit.declaredElement!.source.fullName, (builder) {
partOfs.forEach((uri) {
- var newLocation =
- pathContext.join(newDir, pathos.basename(newFile));
- var newUri = _getRelativeUri(newLocation, oldDir);
+ var newUri = _getRelativeUri(newPath, oldDir);
builder.addSimpleReplacement(
SourceRange(uri.offset, uri.length), "'$newUri'");
});
@@ -145,27 +174,41 @@
var references = getSourceReferences(matches);
for (var reference in references) {
await changeBuilder.addDartFileEdit(reference.file, (builder) {
- var newUri = _computeNewUri(reference);
+ var newUri = _computeNewUri(reference, newPath);
builder.addSimpleReplacement(reference.range, "'$newUri'");
});
}
-
- return changeBuilder.sourceChange;
}
- /// Computes the URI to use to reference [newFile] from [reference].
- String _computeNewUri(SourceReference reference) {
+ Future<void> _appendChangesForResource(
+ ChangeBuilder changeBuilder, Resource resource, String newPath) async {
+ if (isCancellationRequested) {
+ return;
+ }
+
+ if (resource is File) {
+ await _appendChangeForFile(changeBuilder, resource, newPath);
+ } else if (resource is Folder) {
+ for (final child in resource.getChildren()) {
+ await _appendChangesForResource(changeBuilder, child,
+ pathContext.join(newPath, pathContext.basename(child.path)));
+ }
+ }
+ }
+
+ /// Computes the URI to use to reference [newPath] from [reference].
+ String _computeNewUri(SourceReference reference, String newPath) {
var refDir = pathContext.dirname(reference.file);
// Try to keep package: URI
if (_isPackageReference(reference)) {
- var restoredUri = driver.sourceFactory.pathToUri(newFile);
+ var restoredUri = driver.sourceFactory.pathToUri(newPath);
// If the new URI is not a package: URI, fall back to computing a relative
// URI below.
if (restoredUri?.isScheme('package') ?? false) {
return restoredUri.toString();
}
}
- return _getRelativeUri(newFile, refDir);
+ return _getRelativeUri(newPath, refDir);
}
String _getRelativeUri(String path, String from) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 05e0eb3..efe3880 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -20,6 +20,7 @@
import 'package:analysis_server/src/services/refactoring/rename_local.dart';
import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/progress.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
@@ -248,16 +249,12 @@
bool isAvailable();
}
-/// [Refactoring] to move/rename a file.
+/// [Refactoring] to move/rename a file or folder.
abstract class MoveFileRefactoring implements Refactoring {
/// Returns a new [MoveFileRefactoring] instance.
- factory MoveFileRefactoring(
- ResourceProvider resourceProvider,
- RefactoringWorkspace workspace,
- ResolvedUnitResult resolveResult,
- String oldFilePath) {
- return MoveFileRefactoringImpl(
- resourceProvider, workspace, resolveResult, oldFilePath);
+ factory MoveFileRefactoring(ResourceProvider resourceProvider,
+ RefactoringWorkspace workspace, String oldFilePath) {
+ return MoveFileRefactoringImpl(resourceProvider, workspace, oldFilePath);
}
/// The new file path to which the given file is being moved.
@@ -266,6 +263,8 @@
/// Abstract interface for all refactorings.
abstract class Refactoring {
+ set cancellationToken(CancellationToken token);
+
/// The ids of source edits that are not known to be valid.
///
/// An edit is not known to be valid if there was insufficient type
@@ -418,7 +417,7 @@
// Rename the class when on `new` in an instance creation.
if (node is InstanceCreationExpression) {
var creation = node;
- var typeIdentifier = creation.constructorName.type2.name;
+ var typeIdentifier = creation.constructorName.type.name;
element = typeIdentifier.staticElement;
offset = typeIdentifier.offset;
length = typeIdentifier.length;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
index b31755a..d969475 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
@@ -8,6 +8,7 @@
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/progress.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -37,6 +38,11 @@
@override
final List<String> potentialEditIds = <String>[];
+ CancellationToken? cancellationToken;
+
+ bool get isCancellationRequested =>
+ cancellationToken?.isCancellationRequested ?? false;
+
@override
Future<RefactoringStatus> checkAllConditions() async {
var result = RefactoringStatus();
@@ -72,6 +78,9 @@
bool get isConstructorTearOff =>
_match.kind == MatchKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF;
+ bool get isInvocationByEnumConstantWithoutArguments =>
+ _match.kind == MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS;
+
bool get isResolved => _match.isResolved;
SourceRange get range => _match.sourceRange;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 91654f8..8065f1f 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -13,6 +13,7 @@
import 'package:analysis_server/src/services/refactoring/visible_ranges_computer.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -149,20 +150,23 @@
// check if there is a member with "newName" in the same ClassElement
for (var newNameMember in getChildren(elementClass, name)) {
result.addError(
- format(
- "Class '{0}' already declares {1} with name '{2}'.",
- elementClass.displayName,
- getElementKindName(newNameMember),
- name),
- newLocation_fromElement(newNameMember));
+ format(
+ "{0} '{1}' already declares {2} with name '{3}'.",
+ capitalize(elementClass.kind.displayName),
+ elementClass.displayName,
+ getElementKindName(newNameMember),
+ name,
+ ),
+ newLocation_fromElement(newNameMember),
+ );
}
}
Future<void> _checkHierarchy({
required bool isRename,
- required Set<ClassElement> superClasses,
required Set<ClassElement> subClasses,
}) async {
+ var superClasses = elementClass.allSupertypes.map((e) => e.element).toSet();
// check shadowing in the hierarchy
var declarations = await searchEngine.searchMemberDeclarations(name);
for (var declaration in declarations) {
@@ -212,19 +216,18 @@
Future<RefactoringStatus> validate() async {
_checkClassAlreadyDeclares();
// do chained computations
- var superClasses = getSuperClasses(elementClass);
var subClasses = await searchEngine.searchAllSubtypes(elementClass);
// check shadowing of class names
if (elementClass.name == name) {
result.addError(
- format("Created {0} has the same name as the declaring class '{1}'.",
- elementKind.displayName, name),
- newLocation_fromElement(elementClass));
+ 'Created ${elementKind.displayName} has the same name as the '
+ "declaring ${elementClass.kind.displayName} '$name'.",
+ newLocation_fromElement(elementClass),
+ );
}
// check shadowing in the hierarchy
await _checkHierarchy(
isRename: false,
- superClasses: superClasses,
subClasses: subClasses,
);
// done
@@ -272,7 +275,6 @@
Future<RefactoringStatus> validate() async {
_checkClassAlreadyDeclares();
// do chained computations
- var superClasses = getSuperClasses(elementClass);
await _prepareReferences();
var subClasses = await searchEngine.searchAllSubtypes(elementClass);
// check shadowing of class names
@@ -280,11 +282,8 @@
var enclosingElement = element.enclosingElement;
if (enclosingElement is ClassElement && enclosingElement.name == name) {
result.addError(
- format(
- "Renamed {0} has the same name as the declaring class '{1}'.",
- elementKind.displayName,
- name,
- ),
+ 'Renamed ${elementKind.displayName} has the same name as the '
+ "declaring ${enclosingElement.kind.displayName} '$name'.",
newLocation_fromElement(element),
);
}
@@ -306,7 +305,6 @@
// check shadowing in the hierarchy
await _checkHierarchy(
isRename: true,
- superClasses: superClasses,
subClasses: subClasses,
);
// visibility
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
index dc58d49..5e7e7bc 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
@@ -10,8 +10,6 @@
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/refactoring/rename.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -55,12 +53,6 @@
// prepare references
var matches = await searchEngine.searchReferences(element);
var references = getSourceReferences(matches);
- // append declaration
- if (element.isSynthetic) {
- await _replaceSynthetic();
- } else {
- references.add(_createDeclarationReference());
- }
// update references
for (var reference in references) {
String replacement;
@@ -69,8 +61,24 @@
} else {
replacement = reference.isConstructorTearOff ? '.new' : '';
}
+ if (reference.isInvocationByEnumConstantWithoutArguments) {
+ replacement += '()';
+ }
reference.addEdit(change, replacement);
}
+ // Update the declaration.
+ if (element.isSynthetic) {
+ await _replaceSynthetic();
+ } else {
+ doSourceChange_addSourceEdit(
+ change,
+ element.source,
+ newSourceEdit_range(
+ _declarationNameRange(),
+ newName.isNotEmpty ? '.$newName' : '',
+ ),
+ );
+ }
}
void _analyzePossibleConflicts(RefactoringStatus result) {
@@ -88,25 +96,14 @@
}
}
- SourceReference _createDeclarationReference() {
- SourceRange sourceRange;
+ SourceRange _declarationNameRange() {
var offset = element.periodOffset;
var nameEnd = element.nameEnd!;
if (offset != null) {
- sourceRange = range.startOffsetEndOffset(offset, nameEnd);
+ return range.startOffsetEndOffset(offset, nameEnd);
} else {
- sourceRange = SourceRange(nameEnd, 0);
+ return SourceRange(nameEnd, 0);
}
- return SourceReference(SearchMatchImpl(
- element.source.fullName,
- element.library.source,
- element.source,
- element.library,
- element,
- true,
- true,
- MatchKind.DECLARATION,
- sourceRange));
}
Future<void> _replaceSynthetic() async {
@@ -118,32 +115,46 @@
return;
}
- var classNode = result.node;
- if (classNode is! ClassDeclaration) {
- return;
- }
-
var resolvedUnit = result.resolvedUnit;
if (resolvedUnit == null) {
return;
}
- var utils = CorrectionUtils(resolvedUnit);
- var location =
- utils.prepareNewConstructorLocation(resolvedUnit.session, classNode);
- if (location == null) {
- return;
- }
+ var node = result.node;
+ if (node is ClassDeclaration) {
+ var utils = CorrectionUtils(resolvedUnit);
+ var location = utils.prepareNewConstructorLocation(session, node);
+ if (location == null) {
+ return;
+ }
- var header = '${classElement.name}.$newName();';
- doSourceChange_addElementEdit(
- change,
- classElement,
- SourceEdit(
- location.offset,
- 0,
- location.prefix + header + location.suffix,
- ),
- );
+ var header = '${classElement.name}.$newName();';
+ doSourceChange_addElementEdit(
+ change,
+ classElement,
+ SourceEdit(
+ location.offset,
+ 0,
+ location.prefix + header + location.suffix,
+ ),
+ );
+ } else if (node is EnumDeclaration) {
+ var utils = CorrectionUtils(resolvedUnit);
+ var location = utils.prepareEnumNewConstructorLocation(node);
+ if (location == null) {
+ return;
+ }
+
+ var header = 'const ${classElement.name}.$newName();';
+ doSourceChange_addElementEdit(
+ change,
+ classElement,
+ SourceEdit(
+ location.offset,
+ 0,
+ location.prefix + header + location.suffix,
+ ),
+ );
+ }
}
}
diff --git a/pkg/analysis_server/lib/src/services/search/hierarchy.dart b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
index 05d4116..eda9ad4 100644
--- a/pkg/analysis_server/lib/src/services/search/hierarchy.dart
+++ b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
@@ -95,8 +95,10 @@
// method, field, etc
if (enclosingElement is ClassElement) {
var name = member.displayName;
- var searchClasses = getSuperClasses(enclosingElement);
- searchClasses.add(enclosingElement);
+ var searchClasses = [
+ ...enclosingElement.allSupertypes.map((e) => e.element),
+ enclosingElement,
+ ];
for (var superClass in searchClasses) {
// ignore if super- class does not declare member
if (getClassMembers(superClass, name).isEmpty) {
@@ -152,49 +154,17 @@
///
/// Excludes: constructors and synthetic elements.
List<Element> getMembers(ClassElement clazz) {
+ var classElements = [
+ ...clazz.allSupertypes.map((e) => e.element),
+ clazz,
+ ];
var members = <Element>[];
- members.addAll(getClassMembers(clazz));
- var superClasses = getSuperClasses(clazz);
- for (var superClass in superClasses) {
+ for (var superClass in classElements) {
members.addAll(getClassMembers(superClass));
}
return members;
}
-/// Returns a [Set] with all direct and indirect superclasses of [seed].
-Set<ClassElement> getSuperClasses(ClassElement seed) {
- Set<ClassElement> result = HashSet<ClassElement>();
- // prepare queue
- var queue = <ClassElement>[];
- queue.add(seed);
- // process queue
- while (queue.isNotEmpty) {
- var current = queue.removeLast();
- // add if not checked already
- if (!result.add(current)) {
- continue;
- }
- // append supertype
- {
- var superType = current.supertype;
- if (superType != null) {
- queue.add(superType.element);
- }
- }
- // append superclass constraints
- for (var interface in current.superclassConstraints) {
- queue.add(interface.element);
- }
- // append interfaces
- for (var interface in current.interfaces) {
- queue.add(interface.element);
- }
- }
- // we don't need "seed" itself
- result.remove(seed);
- return result;
-}
-
/// If the given [element] is a synthetic [PropertyAccessorElement] returns
/// its variable, otherwise returns [element].
Element getSyntheticAccessorVariable(Element element) {
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine.dart b/pkg/analysis_server/lib/src/services/search/search_engine.dart
index 362216e..09df9a4 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine.dart
@@ -23,6 +23,11 @@
/// A reference to an element in which it is being invoked.
static const MatchKind INVOCATION = MatchKind('INVOCATION');
+ /// An invocation of an enum constructor from an enum constant without
+ /// arguments.
+ static const MatchKind INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS =
+ MatchKind('INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS');
+
/// A reference to an element in which it is referenced.
static const MatchKind REFERENCE = MatchKind('REFERENCE');
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 059c23e98..2eda0d4 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -242,6 +242,10 @@
if (kind == SearchResultKind.INVOCATION) {
return MatchKind.INVOCATION;
}
+ if (kind ==
+ SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS) {
+ return MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS;
+ }
if (kind == SearchResultKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF) {
return MatchKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF;
}
diff --git a/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart b/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart
new file mode 100644
index 0000000..1a6a9ec
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart
@@ -0,0 +1,472 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:meta/meta.dart';
+
+abstract class FlutterSnippetProducer extends SnippetProducer {
+ final flutter = Flutter.instance;
+ final AnalysisSessionHelper sessionHelper;
+
+ late ClassElement? classWidget;
+
+ FlutterSnippetProducer(DartSnippetRequest request)
+ : sessionHelper = AnalysisSessionHelper(request.analysisSession),
+ super(request);
+
+ @override
+ @mustCallSuper
+ Future<bool> isValid() async {
+ if ((classWidget = await _getClass('Widget')) == null) {
+ return false;
+ }
+
+ return super.isValid();
+ }
+
+ Future<ClassElement?> _getClass(String name) =>
+ sessionHelper.getClass(flutter.widgetsUri, name);
+
+ DartType _getType(
+ ClassElement classElement, [
+ NullabilitySuffix nullabilitySuffix = NullabilitySuffix.none,
+ ]) =>
+ classElement.instantiate(
+ typeArguments: const [],
+ nullabilitySuffix: nullabilitySuffix,
+ );
+}
+
+/// Produces a [Snippet] that creates a Flutter StatefulWidget and related State
+/// class.
+class FlutterStatefulWidgetSnippetProducer extends FlutterSnippetProducer {
+ static const prefix = 'stful';
+ static const label = 'Flutter Stateful Widget';
+
+ late ClassElement? classStatefulWidget;
+ late ClassElement? classState;
+ late ClassElement? classBuildContext;
+ late ClassElement? classKey;
+
+ FlutterStatefulWidgetSnippetProducer(DartSnippetRequest request)
+ : super(request);
+
+ @override
+ Future<Snippet> compute() async {
+ final builder = ChangeBuilder(session: request.analysisSession);
+
+ // Checked by isValid().
+ final classStatefulWidget = this.classStatefulWidget!;
+ final classState = this.classState!;
+ final classWidget = this.classWidget!;
+ final classBuildContext = this.classBuildContext!;
+ final classKey = this.classKey!;
+
+ // Only include `?` for nulable types like Key? if in a null-safe library.
+ final nullableSuffix = request.unit.libraryElement.isNonNullableByDefault
+ ? NullabilitySuffix.question
+ : NullabilitySuffix.none;
+
+ final className = 'MyWidget';
+ await builder.addDartFileEdit(request.filePath, (builder) {
+ builder.addReplacement(request.replacementRange, (builder) {
+ // Write the StatefulWidget class
+ builder.writeClassDeclaration(
+ className,
+ nameGroupName: 'name',
+ superclass: _getType(classStatefulWidget),
+ membersWriter: () {
+ // Add the constructor.
+ builder.write(' ');
+ builder.writeConstructorDeclaration(
+ className,
+ classNameGroupName: 'name',
+ isConst: true,
+ parameterWriter: () {
+ builder.write('{');
+ builder.writeParameter(
+ 'key',
+ type: _getType(classKey, nullableSuffix),
+ );
+ builder.write('}');
+ },
+ initializerWriter: () => builder.write('super(key: key)'),
+ );
+ builder.writeln();
+ builder.writeln();
+
+ // Add the createState method.
+ builder.writeln(' @override');
+ builder.write(' State<');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.write('> createState() => _');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.writeln('State();');
+ },
+ );
+ builder.writeln();
+ builder.writeln();
+
+ // Write the State class.
+ builder.write('class _');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.write('State extends ');
+ builder.writeReference(classState);
+ builder.write('<');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.writeln('> {');
+ {
+ // Add the build method.
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'build',
+ returnType: _getType(classWidget),
+ parameterWriter: () {
+ builder.writeParameter(
+ 'context',
+ type: _getType(classBuildContext),
+ );
+ },
+ bodyWriter: () {
+ builder.writeln('{');
+ builder.write(' ');
+ builder.selectHere();
+ builder.writeln();
+ builder.writeln(' }');
+ },
+ );
+ }
+ builder.write('}');
+ });
+ });
+
+ return Snippet(
+ prefix,
+ label,
+ 'Insert a StatefulWidget',
+ builder.sourceChange,
+ );
+ }
+
+ @override
+ Future<bool> isValid() async {
+ if (!await super.isValid()) {
+ return false;
+ }
+
+ if ((classStatefulWidget = await _getClass('StatefulWidget')) == null ||
+ (classState = await _getClass('State')) == null ||
+ (classBuildContext = await _getClass('BuildContext')) == null ||
+ (classKey = await _getClass('Key')) == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static FlutterStatefulWidgetSnippetProducer newInstance(
+ DartSnippetRequest request) =>
+ FlutterStatefulWidgetSnippetProducer(request);
+}
+
+/// Produces a [Snippet] that creates a Flutter StatefulWidget with a
+/// AnimationController and related State class.
+class FlutterStatefulWidgetWithAnimationControllerSnippetProducer
+ extends FlutterSnippetProducer {
+ static const prefix = 'stanim';
+ static const label = 'Flutter Widget with AnimationController';
+
+ late ClassElement? classStatefulWidget;
+ late ClassElement? classState;
+ late ClassElement? classBuildContext;
+ late ClassElement? classKey;
+ late ClassElement? classAnimationController;
+ late ClassElement? classSingleTickerProviderStateMixin;
+
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer(
+ DartSnippetRequest request)
+ : super(request);
+
+ @override
+ Future<Snippet> compute() async {
+ final builder = ChangeBuilder(session: request.analysisSession);
+
+ // Checked by isValid().
+ final classStatefulWidget = this.classStatefulWidget!;
+ final classState = this.classState!;
+ final classWidget = this.classWidget!;
+ final classBuildContext = this.classBuildContext!;
+ final classKey = this.classKey!;
+ final classAnimationController = this.classAnimationController!;
+ final classSingleTickerProviderStateMixin =
+ this.classSingleTickerProviderStateMixin!;
+
+ // Only include `?` for nulable types like Key? if in a null-safe library.
+ final nullableSuffix = request.unit.libraryElement.isNonNullableByDefault
+ ? NullabilitySuffix.question
+ : NullabilitySuffix.none;
+
+ final className = 'MyWidget';
+ await builder.addDartFileEdit(request.filePath, (builder) {
+ builder.addReplacement(request.replacementRange, (builder) {
+ // Write the StatefulWidget class
+ builder.writeClassDeclaration(
+ className,
+ nameGroupName: 'name',
+ superclass: _getType(classStatefulWidget),
+ membersWriter: () {
+ // Add the constructor.
+ builder.write(' ');
+ builder.writeConstructorDeclaration(
+ className,
+ classNameGroupName: 'name',
+ isConst: true,
+ parameterWriter: () {
+ builder.write('{');
+ builder.writeParameter(
+ 'key',
+ type: _getType(classKey, nullableSuffix),
+ );
+ builder.write('}');
+ },
+ initializerWriter: () => builder.write('super(key: key)'),
+ );
+ builder.writeln();
+ builder.writeln();
+
+ // Add the createState method.
+ builder.writeln(' @override');
+ builder.write(' State<');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.write('> createState() => _');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.writeln('State();');
+ },
+ );
+ builder.writeln();
+ builder.writeln();
+
+ // Write the State class.
+ builder.write('class _');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.write('State extends ');
+ builder.writeReference(classState);
+ builder.write('<');
+ builder.addSimpleLinkedEdit('name', className);
+ builder.writeln('>');
+ builder.write(' with ');
+ builder.writeReference(classSingleTickerProviderStateMixin);
+ builder.writeln(' {');
+ builder.write(' late ');
+ builder.writeReference(classAnimationController);
+ builder.writeln(' _controller;');
+ builder.writeln();
+ {
+ // Add the initState method.
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'initState',
+ returnType: VoidTypeImpl.instance,
+ bodyWriter: () {
+ builder.writeln('{');
+ builder.writeln(' super.initState();');
+ builder.write(' _controller = ');
+ builder.writeReference(classAnimationController);
+ builder.writeln('(vsync: this);');
+ builder.writeln(' }');
+ },
+ );
+ }
+ builder.writeln();
+ {
+ // Add the dispose method.
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'dispose',
+ returnType: VoidTypeImpl.instance,
+ bodyWriter: () {
+ builder.writeln('{');
+ builder.writeln(' super.dispose();');
+ builder.writeln(' _controller.dispose();');
+ builder.writeln(' }');
+ },
+ );
+ }
+ builder.writeln();
+ {
+ // Add the build method.
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'build',
+ returnType: _getType(classWidget),
+ parameterWriter: () {
+ builder.writeParameter(
+ 'context',
+ type: _getType(classBuildContext),
+ );
+ },
+ bodyWriter: () {
+ builder.writeln('{');
+ builder.write(' ');
+ builder.selectHere();
+ builder.writeln();
+ builder.writeln(' }');
+ },
+ );
+ }
+ builder.write('}');
+ });
+ });
+
+ return Snippet(
+ prefix,
+ label,
+ 'Insert a StatefulWidget with an AnimationController',
+ builder.sourceChange,
+ );
+ }
+
+ @override
+ Future<bool> isValid() async {
+ if (!await super.isValid()) {
+ return false;
+ }
+
+ if ((classStatefulWidget = await _getClass('StatefulWidget')) == null ||
+ (classState = await _getClass('State')) == null ||
+ (classBuildContext = await _getClass('BuildContext')) == null ||
+ (classKey = await _getClass('Key')) == null ||
+ (classAnimationController = await _getClass('AnimationController')) ==
+ null ||
+ (classSingleTickerProviderStateMixin =
+ await _getClass('SingleTickerProviderStateMixin')) ==
+ null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static FlutterStatefulWidgetWithAnimationControllerSnippetProducer
+ newInstance(DartSnippetRequest request) =>
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer(request);
+}
+
+/// Produces a [Snippet] that creates a Flutter StatelessWidget.
+class FlutterStatelessWidgetSnippetProducer extends FlutterSnippetProducer {
+ static const prefix = 'stless';
+ static const label = 'Flutter Stateless Widget';
+
+ late ClassElement? classStatelessWidget;
+ late ClassElement? classBuildContext;
+ late ClassElement? classKey;
+
+ FlutterStatelessWidgetSnippetProducer(DartSnippetRequest request)
+ : super(request);
+
+ @override
+ Future<Snippet> compute() async {
+ final builder = ChangeBuilder(session: request.analysisSession);
+
+ // Checked by isValid().
+ final classStatelessWidget = this.classStatelessWidget!;
+ final classWidget = this.classWidget!;
+ final classBuildContext = this.classBuildContext!;
+ final classKey = this.classKey!;
+
+ // Only include `?` for nulable types like Key? if in a null-safe library.
+ final nullableSuffix = request.unit.libraryElement.isNonNullableByDefault
+ ? NullabilitySuffix.question
+ : NullabilitySuffix.none;
+
+ final className = 'MyWidget';
+ await builder.addDartFileEdit(request.filePath, (builder) {
+ builder.addReplacement(request.replacementRange, (builder) {
+ builder.writeClassDeclaration(
+ className,
+ nameGroupName: 'name',
+ superclass: _getType(classStatelessWidget),
+ membersWriter: () {
+ // Add the constructor.
+ builder.write(' ');
+ builder.writeConstructorDeclaration(
+ className,
+ classNameGroupName: 'name',
+ isConst: true,
+ parameterWriter: () {
+ builder.write('{');
+ builder.writeParameter(
+ 'key',
+ type: _getType(classKey, nullableSuffix),
+ );
+ builder.write('}');
+ },
+ initializerWriter: () => builder.write('super(key: key)'),
+ );
+ builder.writeln();
+ builder.writeln();
+
+ // Add the build method.
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'build',
+ returnType: _getType(classWidget),
+ parameterWriter: () {
+ builder.writeParameter(
+ 'context',
+ type: _getType(classBuildContext),
+ );
+ },
+ bodyWriter: () {
+ builder.writeln('{');
+ builder.write(' ');
+ builder.selectHere();
+ builder.writeln();
+ builder.writeln(' }');
+ },
+ );
+ },
+ );
+ });
+ });
+
+ return Snippet(
+ prefix,
+ label,
+ 'Insert a StatelessWidget',
+ builder.sourceChange,
+ );
+ }
+
+ @override
+ Future<bool> isValid() async {
+ if (!await super.isValid()) {
+ return false;
+ }
+
+ if ((classStatelessWidget = await _getClass('StatelessWidget')) == null ||
+ (classBuildContext = await _getClass('BuildContext')) == null ||
+ (classKey = await _getClass('Key')) == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static FlutterStatelessWidgetSnippetProducer newInstance(
+ DartSnippetRequest request) =>
+ FlutterStatelessWidgetSnippetProducer(request);
+}
diff --git a/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart b/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart
new file mode 100644
index 0000000..34dc40b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart
@@ -0,0 +1,193 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/provisional/completion/completion_core.dart';
+import 'package:analysis_server/src/services/snippets/dart/flutter_snippet_producers.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
+
+typedef SnippetProducerGenerator = SnippetProducer Function(DartSnippetRequest);
+
+/// [DartSnippetManager] determines if a snippet request is Dart specific
+/// and forwards those requests to all Snippet Producers that return `true` from
+/// their `isValid()` method.
+class DartSnippetManager {
+ final producerGenerators =
+ const <SnippetContext, List<SnippetProducerGenerator>>{
+ SnippetContext.atTopLevel: [
+ FlutterStatefulWidgetSnippetProducer.newInstance,
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer.newInstance,
+ FlutterStatelessWidgetSnippetProducer.newInstance,
+ ]
+ };
+
+ Future<List<Snippet>> computeSnippets(
+ DartSnippetRequest request,
+ ) async {
+ var pathContext = request.resourceProvider.pathContext;
+ if (!file_paths.isDart(pathContext, request.filePath)) {
+ return const [];
+ }
+
+ try {
+ final snippets = <Snippet>[];
+ final generators = producerGenerators[request.context];
+ if (generators == null) {
+ return snippets;
+ }
+ for (final generator in generators) {
+ final producer = generator(request);
+ if (await producer.isValid()) {
+ snippets.add(await producer.compute());
+ }
+ }
+ return snippets;
+ } on InconsistentAnalysisException {
+ // The state of the code being analyzed has changed, so results are likely
+ // to be inconsistent. Just abort the operation.
+ throw AbortCompletion();
+ }
+ }
+}
+
+/// The information about a request for a list of snippets within a Dart file.
+class DartSnippetRequest {
+ /// The resolved unit for the file that snippets are being requested for.
+ final ResolvedUnitResult unit;
+
+ /// The path of the file snippets are being requested for.
+ final String filePath;
+
+ /// The offset within the source at which snippets are being
+ /// requested for.
+ final int offset;
+
+ /// The context in which the snippet request is being made.
+ late final SnippetContext context;
+
+ /// The source range that represents the region of text that should be
+ /// replaced if the snippet is selected.
+ late final SourceRange replacementRange;
+
+ DartSnippetRequest({
+ required this.unit,
+ required this.offset,
+ }) : filePath = unit.path {
+ final target = CompletionTarget.forOffset(unit.unit, offset);
+ context = _getContext(target);
+ replacementRange = target.computeReplacementRange(offset);
+ }
+
+ /// The analysis session that produced the elements of the request.
+ AnalysisSession get analysisSession => unit.session;
+
+ /// The resource provider associated with this request.
+ ResourceProvider get resourceProvider => analysisSession.resourceProvider;
+
+ static SnippetContext _getContext(CompletionTarget target) {
+ final entity = target.entity;
+ if (entity is Token) {
+ final tokenType = (entity.beforeSynthetic ?? entity).type;
+
+ if (tokenType == TokenType.MULTI_LINE_COMMENT ||
+ tokenType == TokenType.SINGLE_LINE_COMMENT) {
+ return SnippetContext.inComment;
+ }
+
+ if (tokenType == TokenType.STRING ||
+ tokenType == TokenType.STRING_INTERPOLATION_EXPRESSION ||
+ tokenType == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
+ return SnippetContext.inString;
+ }
+ }
+
+ AstNode? node = target.containingNode;
+ while (node != null) {
+ if (node is Comment) {
+ return SnippetContext.inComment;
+ }
+
+ if (node is StringLiteral) {
+ return SnippetContext.inString;
+ }
+
+ if (node is Block) {
+ return SnippetContext.inBlock;
+ }
+
+ if (node is Statement || node is Expression || node is Annotation) {
+ return SnippetContext.inExpressionOrStatement;
+ }
+
+ if (node is BlockFunctionBody) {
+ return SnippetContext.inBlock;
+ }
+
+ if (node is ClassOrMixinDeclaration || node is ExtensionDeclaration) {
+ return SnippetContext.inClass;
+ }
+
+ node = node.parent;
+ }
+
+ return SnippetContext.atTopLevel;
+ }
+}
+
+class Snippet {
+ /// The text the user will type to use this snippet.
+ final String prefix;
+
+ /// The label/title of this snippet.
+ final String label;
+
+ /// A description of/documentation for the snippet.
+ final String? documentation;
+
+ /// The source changes to be made to insert this snippet.
+ final SourceChange change;
+
+ Snippet(
+ this.prefix,
+ this.label,
+ this.documentation,
+ this.change,
+ );
+}
+
+/// The context in which a snippet request was made.
+///
+/// This is used to filter the available snippets (for example preventing
+/// snippets that create classes showing up when inside an existing class or
+/// function body).
+enum SnippetContext {
+ atTopLevel,
+ inClass,
+ inBlock,
+ inExpressionOrStatement,
+ inComment,
+ inString,
+}
+
+abstract class SnippetProducer {
+ final DartSnippetRequest request;
+
+ SnippetProducer(this.request);
+
+ Future<Snippet> compute();
+
+ Future<bool> isValid() async {
+ // File edit builders will not produce edits for files outside of the
+ // analysis roots so we should not try to produce any snippets.
+ final analysisContext = request.analysisSession.analysisContext;
+ return analysisContext.contextRoot.isAnalyzed(request.filePath);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart b/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
index 95c5384..eedc3c7 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/utilities/index_range.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source_range.dart';
@@ -67,6 +68,30 @@
}
}
+ /// Return a list of the ranges that cover all of the elements in the [list]
+ /// whose index is in the list of [indexes].
+ List<SourceRange> nodesInList<T extends AstNode>(
+ NodeList<T> list, List<int> indexes) {
+ var ranges = <SourceRange>[];
+ var indexRanges = IndexRange.contiguousSubRanges(indexes);
+ if (indexRanges.length == 1) {
+ var indexRange = indexRanges[0];
+ if (indexRange.lower == 0 && indexRange.upper == list.length - 1) {
+ ranges.add(startEnd(list[indexRange.lower], list[indexRange.upper]));
+ return ranges;
+ }
+ }
+ for (var indexRange in indexRanges) {
+ if (indexRange.lower == 0) {
+ ranges.add(
+ startStart(list[indexRange.lower], list[indexRange.upper + 1]));
+ } else {
+ ranges.add(endEnd(list[indexRange.lower - 1], list[indexRange.upper]));
+ }
+ }
+ return ranges;
+ }
+
/// Return a source range that covers the given [node] with any leading and
/// trailing comments.
///
diff --git a/pkg/analysis_server/lib/src/utilities/index_range.dart b/pkg/analysis_server/lib/src/utilities/index_range.dart
new file mode 100644
index 0000000..648ec02
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/index_range.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A range of indexes within a list.
+class IndexRange {
+ /// The index of the first element in the range.
+ final int lower;
+
+ /// The index of the last element in the range. This will be the same as the
+ /// [lower] if there is a single element in the range.
+ final int upper;
+
+ /// Initialize a newly created range.
+ IndexRange(this.lower, this.upper);
+
+ /// Return the number of indices in this range.
+ int get count => upper - lower + 1;
+
+ @override
+ String toString() => '[$lower..$upper]';
+
+ static List<IndexRange> contiguousSubRanges(List<int> indexes) {
+ var ranges = <IndexRange>[];
+ if (indexes.isEmpty) {
+ return ranges;
+ }
+ var lower = indexes[0];
+ var previous = lower;
+ for (var index = 1; index < indexes.length; index++) {
+ var current = indexes[index];
+ if (current == previous + 1) {
+ previous = current;
+ } else {
+ ranges.add(IndexRange(lower, previous));
+ lower = previous = current;
+ }
+ }
+ ranges.add(IndexRange(lower, previous));
+ return ranges;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
index bef5102..6ad7371 100644
--- a/pkg/analysis_server/lib/src/utilities/mocks.dart
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -23,7 +23,7 @@
StreamController<Response> responseController =
StreamController<Response>.broadcast();
StreamController<Notification> notificationController =
- StreamController<Notification>(sync: true);
+ StreamController<Notification>.broadcast(sync: true);
Completer<Response>? errorCompleter;
List<Response> responsesReceived = [];
@@ -35,6 +35,11 @@
MockServerChannel();
+ /// Return the broadcast stream of notifications.
+ Stream<Notification> get notifications {
+ return notificationController.stream;
+ }
+
@override
Stream<Request> get requests => requestController.stream;
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 39518e8..5f62d61 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -13,7 +13,6 @@
analyzer_plugin:
path: ../analyzer_plugin
args: any
- cli_util: any
collection: any
convert: any
crypto: any
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index c86b091..59847fe 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -48,7 +48,7 @@
/// Return a list of the experiments that are to be enabled for tests in this
/// class, an empty list if there are no experiments that should be enabled.
List<String> get experiments => [
- EnableString.constructor_tearoffs,
+ EnableString.enhanced_enums,
EnableString.named_arguments_anywhere,
EnableString.super_parameters,
];
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 6d19ce9..440b1b4 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -67,38 +67,7 @@
await createProject();
}
- Future<void> test_class_declaration() async {
- addTestFile('''
-class A<E> {}
-class I1<K, V> {}
-class I2<E> {}
-class M1 {}
-class M2<E> {}
-class B<T> extends A<T> with M1, M2<int> implements I1<int, String>, I2 {}
-''');
- var hover = await prepareHover('B<T>');
- expect(hover.containingClassDescription, null);
- expect(
- hover.elementDescription,
- 'class B<T> extends A<T> with M1, M2<int> '
- 'implements I1<int, String>, I2<dynamic>');
- expect(hover.staticType, isNull);
- expect(hover.propagatedType, isNull);
- }
-
- Future<void> test_class_declaration_abstract() async {
- addTestFile('''
-class A {}
-abstract class B extends A {}
-''');
- var hover = await prepareHover('B extends');
- expect(hover.containingClassDescription, null);
- expect(hover.elementDescription, 'abstract class B extends A');
- expect(hover.staticType, isNull);
- expect(hover.propagatedType, isNull);
- }
-
- Future<void> test_constructor_named() async {
+ Future<void> test_class_constructor_named() async {
addTestFile('''
library my.library;
class A {
@@ -129,7 +98,7 @@
}
}
- Future<void> test_constructor_noKeyword_const() async {
+ Future<void> test_class_constructor_noKeyword_const() async {
addTestFile('''
library my.library;
class A {
@@ -156,7 +125,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructor_noKeyword_new() async {
+ Future<void> test_class_constructor_noKeyword_new() async {
addTestFile('''
library my.library;
class A {}
@@ -181,7 +150,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructor_synthetic() async {
+ Future<void> test_class_constructor_synthetic() async {
addTestFile('''
library my.library;
class A {
@@ -207,7 +176,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructor_synthetic_withTypeArgument() async {
+ Future<void> test_class_constructor_synthetic_withTypeArgument() async {
addTestFile('''
library my.library;
class A<T> {}
@@ -249,7 +218,7 @@
}
}
- Future<void> test_constructorReference_named() async {
+ Future<void> test_class_constructorReference_named() async {
addTestFile('''
class A<T> {
/// doc aaa
@@ -276,7 +245,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructorReference_unnamed_declared() async {
+ Future<void> test_class_constructorReference_unnamed_declared() async {
addTestFile('''
class A<T> {
/// doc aaa
@@ -303,7 +272,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructorReference_unnamed_declared_new() async {
+ Future<void> test_class_constructorReference_unnamed_declared_new() async {
addTestFile('''
class A<T> {
/// doc aaa
@@ -330,7 +299,7 @@
expect(hover.parameter, isNull);
}
- Future<void> test_constructorReference_unnamed_synthetic() async {
+ Future<void> test_class_constructorReference_unnamed_synthetic() async {
addTestFile('''
class A<T> {}
@@ -353,6 +322,269 @@
expect(hover.parameter, isNull);
}
+ Future<void> test_class_declaration() async {
+ addTestFile('''
+class A<E> {}
+class I1<K, V> {}
+class I2<E> {}
+class M1 {}
+class M2<E> {}
+class B<T> extends A<T> with M1, M2<int> implements I1<int, String>, I2 {}
+''');
+ var hover = await prepareHover('B<T>');
+ expect(hover.containingClassDescription, null);
+ expect(
+ hover.elementDescription,
+ 'class B<T> extends A<T> with M1, M2<int> '
+ 'implements I1<int, String>, I2<dynamic>');
+ expect(hover.staticType, isNull);
+ expect(hover.propagatedType, isNull);
+ }
+
+ Future<void> test_class_declaration_abstract() async {
+ addTestFile('''
+class A {}
+abstract class B extends A {}
+''');
+ var hover = await prepareHover('B extends');
+ expect(hover.containingClassDescription, null);
+ expect(hover.elementDescription, 'abstract class B extends A');
+ expect(hover.staticType, isNull);
+ expect(hover.propagatedType, isNull);
+ }
+
+ Future<void> test_class_getter_synthetic() async {
+ addTestFile('''
+library my.library;
+class A {
+ /// doc aaa
+ /// doc bbb
+ String fff;
+}
+void f(A a) {
+ print(a.fff);
+}
+''');
+ var hover = await prepareHover('fff);');
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'A');
+ expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
+ expect(hover.elementDescription, 'String fff');
+ expect(hover.elementKind, 'field');
+ // types
+ expect(hover.staticType, 'String');
+ expect(hover.propagatedType, isNull);
+ }
+
+ Future<void> test_class_method_declaration() async {
+ addTestFile('''
+library my.library;
+class A {
+ /// doc aaa
+ /// doc bbb
+ List<String> mmm(int a, String b) {
+ }
+}
+''');
+ var hover = await prepareHover('mmm(int a');
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'A');
+ expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
+ expect(hover.elementKind, 'method');
+ // types
+ expect(hover.staticType, isNull);
+ expect(hover.propagatedType, isNull);
+ // no parameter
+ expect(hover.parameter, isNull);
+ }
+
+ Future<void> test_class_method_reference() async {
+ addTestFile('''
+library my.library;
+class A {
+ List<String> mmm(int a, String b) {
+ }
+}
+void f(A a) {
+ a.mmm(42, 'foo');
+}
+''');
+ var hover = await prepareHover('mm(42, ');
+ // range
+ expect(hover.offset, findOffset('mmm(42, '));
+ expect(hover.length, 'mmm'.length);
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
+ expect(hover.elementKind, 'method');
+ expect(hover.isDeprecated, isFalse);
+ // types
+ expect(hover.staticType, 'List<String> Function(int, String)');
+ expect(hover.propagatedType, isNull);
+ // no parameter
+ expect(hover.parameter, isNull);
+ }
+
+ Future<void> test_class_method_reference_deprecated() async {
+ addTestFile('''
+class A {
+ @deprecated
+ static void test() {}
+}
+void f() {
+ A.test();
+}
+''');
+ var hover = await prepareHover('test();');
+ // element
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.elementDescription, 'void test()');
+ expect(hover.elementKind, 'method');
+ expect(hover.isDeprecated, isTrue);
+ }
+
+ Future<void> test_class_method_reference_genericMethod() async {
+ addTestFile('''
+library my.library;
+
+abstract class Stream<T> {
+ Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer);
+}
+abstract class StreamTransformer<T, S> {}
+
+f(Stream<int> s) {
+ s.transform(null);
+}
+''');
+ var hover = await prepareHover('nsform(n');
+ // range
+ expect(hover.offset, findOffset('transform(n'));
+ expect(hover.length, 'transform'.length);
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.elementDescription,
+ 'Stream<S> transform<S>(StreamTransformer<int, S> streamTransformer)');
+ expect(hover.elementKind, 'method');
+ expect(hover.isDeprecated, isFalse);
+ // types
+ expect(hover.staticType,
+ 'Stream<dynamic> Function(StreamTransformer<int, dynamic>)');
+ expect(hover.propagatedType, isNull);
+ // no parameter
+ expect(hover.parameter, isNull);
+ }
+
+ Future<void> test_class_setter_hasDocumentation() async {
+ addTestFile('''
+class A {
+ /// getting
+ int get foo => 42;
+ /// setting
+ set foo(int x) {}
+}
+void f(A a) {
+ a.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'A');
+ expect(hover.dartdoc, '''setting''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
+ Future<void> test_class_setter_noDocumentation() async {
+ addTestFile('''
+class A {
+ /// getting
+ int get foo => 42;
+ set foo(int x) {}
+}
+void f(A a) {
+ a.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'A');
+ expect(hover.dartdoc, '''getting''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
+ Future<void> test_class_setter_super_hasDocumentation() async {
+ addTestFile('''
+class A {
+ /// pgetting
+ int get foo => 42;
+ /// psetting
+ set foo(int x) {}
+}
+class B extends A {
+ /// getting
+ int get foo => 42;
+ set foo(int x) {}
+}
+void f(B b) {
+ b.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'B');
+ expect(hover.dartdoc, '''psetting\n\nCopied from `A`.''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
+ Future<void> test_class_setter_super_noDocumentation() async {
+ addTestFile('''
+class A {
+ /// pgetting
+ int get foo => 42;
+ set foo(int x) {}
+}
+class B extends A {
+ int get foo => 42;
+ set foo(int x) {}
+}
+void f(B b) {
+ b.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'B');
+ expect(hover.dartdoc, '''pgetting\n\nCopied from `A`.''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
+ @failingTest
+ Future<void> test_class_setter_super_noSetter() async {
+ addTestFile('''
+class A {
+ /// pgetting
+ int get foo => 42;
+}
+class B extends A {
+ set foo(int x) {}
+}
+void f(B b) {
+ b.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'B');
+ expect(hover.dartdoc, '''pgetting''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
Future<void> test_dartdoc_block() async {
addTestFile('''
/**
@@ -453,6 +685,131 @@
expect(hover.propagatedType, isNull);
}
+ Future<void> test_enum_getter() async {
+ addTestFile('''
+library my.library;
+enum E {
+ v;
+ /// doc aaa
+ /// doc bbb
+ int get foo => 0;
+}
+void f(E e) {
+ print(e.foo);
+}
+''');
+ var hover = await prepareHover('foo);');
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'E');
+ expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
+ expect(hover.elementDescription, 'int get foo');
+ expect(hover.elementKind, 'getter');
+ }
+
+ Future<void> test_enum_getter_synthetic() async {
+ addTestFile('''
+library my.library;
+enum E {
+ v;
+ /// doc aaa
+ /// doc bbb
+ final String fff;
+}
+void f(E e) {
+ print(e.fff);
+}
+''');
+ var hover = await prepareHover('fff);');
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'E');
+ expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
+ expect(hover.elementDescription, 'String fff');
+ expect(hover.elementKind, 'field');
+ // types
+ expect(hover.staticType, 'String');
+ expect(hover.propagatedType, isNull);
+ }
+
+ Future<void> test_enum_method_declaration() async {
+ addTestFile('''
+library my.library;
+enum E {
+ v;
+ /// doc aaa
+ /// doc bbb
+ List<String> mmm(int a, String b) {
+ }
+}
+''');
+ var hover = await prepareHover('mmm(int a');
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'E');
+ expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
+ expect(hover.elementKind, 'method');
+ // types
+ expect(hover.staticType, isNull);
+ expect(hover.propagatedType, isNull);
+ // no parameter
+ expect(hover.parameter, isNull);
+ }
+
+ Future<void> test_enum_method_reference() async {
+ addTestFile('''
+library my.library;
+enum E {
+ v;
+ List<String> mmm(int a, String b) {
+ }
+}
+void f(E e) {
+ e.mmm(42, 'foo');
+}
+''');
+ var hover = await prepareHover('mm(42, ');
+ // range
+ expect(hover.offset, findOffset('mmm(42, '));
+ expect(hover.length, 'mmm'.length);
+ // element
+ expect(hover.containingLibraryName, 'bin/test.dart');
+ expect(hover.containingLibraryPath, testFile);
+ expect(hover.containingClassDescription, 'E');
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
+ expect(hover.elementKind, 'method');
+ expect(hover.isDeprecated, isFalse);
+ // types
+ expect(hover.staticType, 'List<String> Function(int, String)');
+ expect(hover.propagatedType, isNull);
+ // no parameter
+ expect(hover.parameter, isNull);
+ }
+
+ Future<void> test_enum_setter_hasDocumentation() async {
+ addTestFile('''
+enum E {
+ v;
+ /// getting
+ int get foo => 42;
+ /// setting
+ set foo(int x) {}
+}
+void f(E e) {
+ e.foo = 123;
+}
+''');
+ var hover = await prepareHover('foo = ');
+ expect(hover.containingClassDescription, 'E');
+ expect(hover.dartdoc, '''setting''');
+ expect(hover.elementDescription, 'void set foo(int x)');
+ expect(hover.elementKind, 'setter');
+ }
+
Future<void> test_extensionDeclaration() async {
addTestFile('''
class A {}
@@ -586,31 +943,6 @@
expect(hover.parameter, isNull);
}
- Future<void> test_getter_synthetic() async {
- addTestFile('''
-library my.library;
-class A {
- /// doc aaa
- /// doc bbb
- String fff;
-}
-void f(A a) {
- print(a.fff);
-}
-''');
- var hover = await prepareHover('fff);');
- // element
- expect(hover.containingLibraryName, 'bin/test.dart');
- expect(hover.containingLibraryPath, testFile);
- expect(hover.containingClassDescription, 'A');
- expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
- expect(hover.elementDescription, 'String fff');
- expect(hover.elementKind, 'field');
- // types
- expect(hover.staticType, 'String');
- expect(hover.propagatedType, isNull);
- }
-
Future<void> test_integerLiteral() async {
addTestFile('''
void f() {
@@ -726,109 +1058,6 @@
expect(hover.propagatedType, null);
}
- Future<void> test_method_declaration() async {
- addTestFile('''
-library my.library;
-class A {
- /// doc aaa
- /// doc bbb
- List<String> mmm(int a, String b) {
- }
-}
-''');
- var hover = await prepareHover('mmm(int a');
- // element
- expect(hover.containingLibraryName, 'bin/test.dart');
- expect(hover.containingLibraryPath, testFile);
- expect(hover.containingClassDescription, 'A');
- expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
- expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
- expect(hover.elementKind, 'method');
- // types
- expect(hover.staticType, isNull);
- expect(hover.propagatedType, isNull);
- // no parameter
- expect(hover.parameter, isNull);
- }
-
- Future<void> test_method_reference() async {
- addTestFile('''
-library my.library;
-class A {
- List<String> mmm(int a, String b) {
- }
-}
-void f(A a) {
- a.mmm(42, 'foo');
-}
-''');
- var hover = await prepareHover('mm(42, ');
- // range
- expect(hover.offset, findOffset('mmm(42, '));
- expect(hover.length, 'mmm'.length);
- // element
- expect(hover.containingLibraryName, 'bin/test.dart');
- expect(hover.containingLibraryPath, testFile);
- expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
- expect(hover.elementKind, 'method');
- expect(hover.isDeprecated, isFalse);
- // types
- expect(hover.staticType, 'List<String> Function(int, String)');
- expect(hover.propagatedType, isNull);
- // no parameter
- expect(hover.parameter, isNull);
- }
-
- Future<void> test_method_reference_deprecated() async {
- addTestFile('''
-class A {
- @deprecated
- static void test() {}
-}
-void f() {
- A.test();
-}
-''');
- var hover = await prepareHover('test();');
- // element
- expect(hover.containingLibraryPath, testFile);
- expect(hover.elementDescription, 'void test()');
- expect(hover.elementKind, 'method');
- expect(hover.isDeprecated, isTrue);
- }
-
- Future<void> test_method_reference_genericMethod() async {
- addTestFile('''
-library my.library;
-
-abstract class Stream<T> {
- Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer);
-}
-abstract class StreamTransformer<T, S> {}
-
-f(Stream<int> s) {
- s.transform(null);
-}
-''');
- var hover = await prepareHover('nsform(n');
- // range
- expect(hover.offset, findOffset('transform(n'));
- expect(hover.length, 'transform'.length);
- // element
- expect(hover.containingLibraryName, 'bin/test.dart');
- expect(hover.containingLibraryPath, testFile);
- expect(hover.elementDescription,
- 'Stream<S> transform<S>(StreamTransformer<int, S> streamTransformer)');
- expect(hover.elementKind, 'method');
- expect(hover.isDeprecated, isFalse);
- // types
- expect(hover.staticType,
- 'Stream<dynamic> Function(StreamTransformer<int, dynamic>)');
- expect(hover.propagatedType, isNull);
- // no parameter
- expect(hover.parameter, isNull);
- }
-
Future<void> test_mixin_declaration() async {
addTestFile('''
mixin A on B, C implements D, E {}
@@ -1002,110 +1231,6 @@
expect(hover.staticType, 'int');
}
- Future<void> test_setter_hasDocumentation() async {
- addTestFile('''
-class A {
- /// getting
- int get foo => 42;
- /// setting
- set foo(int x) {}
-}
-void f(A a) {
- a.foo = 123;
-}
-''');
- var hover = await prepareHover('foo = ');
- expect(hover.containingClassDescription, 'A');
- expect(hover.dartdoc, '''setting''');
- expect(hover.elementDescription, 'void set foo(int x)');
- expect(hover.elementKind, 'setter');
- }
-
- Future<void> test_setter_noDocumentation() async {
- addTestFile('''
-class A {
- /// getting
- int get foo => 42;
- set foo(int x) {}
-}
-void f(A a) {
- a.foo = 123;
-}
-''');
- var hover = await prepareHover('foo = ');
- expect(hover.containingClassDescription, 'A');
- expect(hover.dartdoc, '''getting''');
- expect(hover.elementDescription, 'void set foo(int x)');
- expect(hover.elementKind, 'setter');
- }
-
- Future<void> test_setter_super_hasDocumentation() async {
- addTestFile('''
-class A {
- /// pgetting
- int get foo => 42;
- /// psetting
- set foo(int x) {}
-}
-class B extends A {
- /// getting
- int get foo => 42;
- set foo(int x) {}
-}
-void f(B b) {
- b.foo = 123;
-}
-''');
- var hover = await prepareHover('foo = ');
- expect(hover.containingClassDescription, 'B');
- expect(hover.dartdoc, '''psetting\n\nCopied from `A`.''');
- expect(hover.elementDescription, 'void set foo(int x)');
- expect(hover.elementKind, 'setter');
- }
-
- Future<void> test_setter_super_noDocumentation() async {
- addTestFile('''
-class A {
- /// pgetting
- int get foo => 42;
- set foo(int x) {}
-}
-class B extends A {
- int get foo => 42;
- set foo(int x) {}
-}
-void f(B b) {
- b.foo = 123;
-}
-''');
- var hover = await prepareHover('foo = ');
- expect(hover.containingClassDescription, 'B');
- expect(hover.dartdoc, '''pgetting\n\nCopied from `A`.''');
- expect(hover.elementDescription, 'void set foo(int x)');
- expect(hover.elementKind, 'setter');
- }
-
- @failingTest
- Future<void> test_setter_super_noSetter() async {
- addTestFile('''
-class A {
- /// pgetting
- int get foo => 42;
-}
-class B extends A {
- set foo(int x) {}
-}
-void f(B b) {
- b.foo = 123;
-}
-''');
- var hover = await prepareHover('foo = ');
- expect(hover.containingClassDescription, 'B');
- expect(hover.dartdoc, '''pgetting''');
- expect(hover.elementDescription, 'void set foo(int x)');
- expect(hover.elementKind, 'setter');
- }
-
Future<void> test_simpleIdentifier_typedef_functionType() async {
addTestFile('''
typedef A = void Function(int);
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index ed4a472..3048a8c 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -656,9 +656,164 @@
assertHasRegion(HighlightRegionType.INSTANCE_SETTER_REFERENCE, 'f = 1');
}
- Future<void> test_ENUM() async {
+ Future<void> test_enum_constant() async {
+ addTestFile('''
+enum MyEnum {AAA, BBB}
+
+void f() {
+ MyEnum.AAA;
+ MyEnum.BBB;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'AAA, ');
+ assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB}');
+ assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'AAA;');
+ assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB;');
+ }
+
+ Future<void> test_enum_constructor() async {
+ addTestFile('''
+const a = 0;
+
+enum E<T> {
+ v<int>.named(a); // 1
+ E.named(T a); // 2
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'v<');
+ assertHasRegion(HighlightRegionType.CLASS, 'int>');
+ assertHasRegion(HighlightRegionType.CONSTRUCTOR, 'named(a)');
+ assertHasRegion(HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE, 'a); // 1');
+ assertHasRegion(HighlightRegionType.ENUM, 'E.named');
+ assertHasRegion(HighlightRegionType.CONSTRUCTOR, 'named(T');
+ assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T a');
+ assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'a); // 2');
+ }
+
+ Future<void> test_enum_field_instance() async {
+ addTestFile('''
+enum E {
+ v;
+ final int a = 0;
+ E(this.a);
+}
+
+void f(E e) {
+ e.a;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int ');
+ assertHasRegion(HighlightRegionType.INSTANCE_FIELD_DECLARATION, 'a = 0');
+ assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'a);');
+ assertHasRegion(HighlightRegionType.INSTANCE_GETTER_REFERENCE, 'a;');
+ }
+
+ Future<void> test_enum_field_static() async {
+ addTestFile('''
+enum E {
+ v;
+ static final int a = 0;
+}
+
+void f() {
+ E.a;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int ');
+ assertHasRegion(HighlightRegionType.STATIC_FIELD_DECLARATION, 'a = 0');
+ assertHasRegion(HighlightRegionType.STATIC_GETTER_REFERENCE, 'a;');
+ }
+
+ Future<void> test_enum_getter_instance() async {
+ addTestFile('''
+enum E {
+ v;
+ int get foo => 0;
+}
+
+void f(E e) {
+ e.foo;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int get');
+ assertHasRegion(HighlightRegionType.INSTANCE_GETTER_DECLARATION, 'foo =>');
+ assertHasRegion(HighlightRegionType.INSTANCE_GETTER_REFERENCE, 'foo;');
+ }
+
+ Future<void> test_enum_getter_static() async {
+ addTestFile('''
+enum E {
+ v;
+ static int get foo => 0;
+}
+
+void f() {
+ E.foo;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int get');
+ assertHasRegion(HighlightRegionType.STATIC_GETTER_DECLARATION, 'foo =>');
+ assertHasRegion(HighlightRegionType.STATIC_GETTER_REFERENCE, 'foo;');
+ }
+
+ Future<void> test_enum_method_instance() async {
+ addTestFile('''
+enum E {
+ v;
+ int foo(int a) {
+ return a;
+ }
+}
+
+void f(E e) {
+ e.foo();
+ e.foo;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int foo');
+ assertHasRegion(HighlightRegionType.INSTANCE_METHOD_DECLARATION, 'foo(int');
+ assertHasRegion(HighlightRegionType.CLASS, 'int a');
+ assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'a)');
+ assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'a;');
+ assertHasRegion(HighlightRegionType.INSTANCE_METHOD_REFERENCE, 'foo();');
+ assertHasRegion(HighlightRegionType.INSTANCE_METHOD_TEAR_OFF, 'foo;');
+ }
+
+ Future<void> test_enum_method_static() async {
+ addTestFile('''
+enum E {
+ v;
+ static int foo(int a) {
+ return a;
+ }
+}
+
+void f() {
+ E.foo();
+ E.foo;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int foo');
+ assertHasRegion(HighlightRegionType.STATIC_METHOD_DECLARATION, 'foo(int');
+ assertHasRegion(HighlightRegionType.CLASS, 'int a');
+ assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'a)');
+ assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'a;');
+ assertHasRegion(HighlightRegionType.STATIC_METHOD_REFERENCE, 'foo();');
+ assertHasRegion(HighlightRegionType.STATIC_METHOD_TEAR_OFF, 'foo;');
+ }
+
+ Future<void> test_enum_name() async {
addTestFile('''
enum MyEnum {A, B, C}
+
MyEnum value;
''');
await prepareHighlights();
@@ -666,19 +821,50 @@
assertHasRegion(HighlightRegionType.ENUM, 'MyEnum value;');
}
- Future<void> test_ENUM_CONSTANT() async {
+ Future<void> test_enum_setter_instance() async {
addTestFile('''
-enum MyEnum {AAA, BBB}
-void f() {
- print(MyEnum.AAA);
- print(MyEnum.BBB);
+enum E {
+ v;
+ set foo(int _) {}
+}
+
+void f(E e) {
+ e.foo = 0;
}
''');
await prepareHighlights();
- assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'AAA, ');
- assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB}');
- assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'AAA);');
- assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB);');
+ assertHasRegion(HighlightRegionType.CLASS, 'int _');
+ assertHasRegion(HighlightRegionType.INSTANCE_SETTER_DECLARATION, 'foo(int');
+ assertHasRegion(HighlightRegionType.INSTANCE_SETTER_REFERENCE, 'foo = 0;');
+ }
+
+ Future<void> test_enum_setter_static() async {
+ addTestFile('''
+enum E {
+ v;
+ static set foo(int _) {}
+}
+
+void f() {
+ E.foo = 0;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.CLASS, 'int _');
+ assertHasRegion(HighlightRegionType.STATIC_SETTER_DECLARATION, 'foo(int');
+ assertHasRegion(HighlightRegionType.STATIC_SETTER_REFERENCE, 'foo = 0;');
+ }
+
+ Future<void> test_enum_typeParameter() async {
+ addTestFile('''
+enum E<T> {
+ v;
+ T? foo() => null;
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T>');
+ assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T?');
}
Future<void> test_EXTENSION() async {
@@ -1150,6 +1336,19 @@
assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'bbb: 2');
}
+ Future<void> test_PARAMETER_named_anywhere() async {
+ addTestFile('''
+void f(int aaa, int bbb, {int? ccc, int? ddd}) {}
+
+void g() {
+ f(0, ccc: 2, 1, ddd: 3);
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'ccc: 2');
+ assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'ddd: 3');
+ }
+
Future<void> test_PARAMETER_super_children() async {
addTestFile('''
class A {
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index c0deb4e..a9db25d 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -150,7 +150,7 @@
assertHasImplementedClass('A {');
}
- Future<void> test_class_implemented() async {
+ Future<void> test_class_implementedBy_class() async {
addTestFile('''
class A {}
class B implements A {}
@@ -159,7 +159,67 @@
assertHasImplementedClass('A {');
}
- Future<void> test_class_inMixin() async {
+ Future<void> test_class_implementedBy_enum() async {
+ addTestFile('''
+class A {}
+
+enum E implements A {
+ v
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedClass('A {');
+ }
+
+ Future<void> test_class_implementedBy_enum_getterByGetter() async {
+ addTestFile('''
+class A {
+ int get foo => 0; // A
+}
+
+enum E implements A {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedMember('foo => 0; // A');
+ assertNoImplementedMember('foo => 0; // E');
+ }
+
+ Future<void> test_class_implementedBy_enum_methodByMethod() async {
+ addTestFile('''
+class A {
+ void foo() {} // A
+}
+
+enum E implements A {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedMember('foo() {} // A');
+ assertNoImplementedMember('foo() {} // E');
+ }
+
+ Future<void> test_class_implementedBy_enum_setterBySetter() async {
+ addTestFile('''
+class A {
+ set foo(int _) {} // A
+}
+
+enum E implements A {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedMember('foo(int _) {} // A');
+ assertNoImplementedMember('foo(int _) {} // E');
+ }
+
+ Future<void> test_class_implementedBy_mixin() async {
addTestFile('''
class A {} // ref
class B {} // ref
@@ -174,7 +234,7 @@
assertHasImplementedClass('D {} // ref');
}
- Future<void> test_class_mixed() async {
+ Future<void> test_class_mixedBy_class() async {
addTestFile('''
class A {}
class B = Object with A;
@@ -183,6 +243,33 @@
assertHasImplementedClass('A {');
}
+ Future<void> test_class_mixedBy_enum() async {
+ addTestFile('''
+mixin M {}
+enum E with M {
+ v
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedClass('M {}');
+ }
+
+ Future<void> test_class_mixedBy_enum_methodByMethod() async {
+ addTestFile('''
+class M {
+ void foo() {} // M
+}
+
+enum E with M {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareImplementedElements();
+ assertHasImplementedMember('foo() {} // M');
+ assertNoImplementedMember('foo() {} // E');
+ }
+
Future<void> test_field_withField() async {
addTestFile('''
class A {
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 3598517..506df55 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -92,6 +92,22 @@
assertHasFileTarget(testFile, offset, length);
}
+ /// TODO(scheglov) Improve target matching.
+ void assertHasTargetInDartCore(String search) {
+ var dartCoreFile = getFile('/sdk/lib/core/core.dart');
+ var dartCoreContent = dartCoreFile.readAsStringSync();
+
+ var offset = dartCoreContent.indexOf(search);
+ expect(offset, isNot(-1));
+
+ if (dartCoreContent.contains(search, offset + search.length)) {
+ fail('Not unique');
+ }
+
+ var length = findIdentifierLength(search);
+ assertHasFileTarget(dartCoreFile.path, offset, length);
+ }
+
/// Validates that there is a target in [testTargets] with [testFile], at the
/// offset of [str] in [testFile], and with the length of [str].
void assertHasTargetString(String str) {
@@ -347,19 +363,7 @@
assertHasRegion('myan // ref');
}
- Future<void> test_class_fromSDK() async {
- addTestFile('''
-int V = 42;
-''');
- await prepareNavigation();
- assertHasRegion('int V');
- var targetIndex = testTargetIndexes[0];
- var target = targets[targetIndex];
- expect(target.startLine, greaterThan(0));
- expect(target.startColumn, greaterThan(0));
- }
-
- Future<void> test_constructor_named() async {
+ Future<void> test_class_constructor_named() async {
addTestFile('''
class A {
A.named(BBB p) {}
@@ -377,7 +381,7 @@
assertHasRegionTarget('BBB p', 'BBB {}');
}
- Future<void> test_constructor_unnamed() async {
+ Future<void> test_class_constructor_unnamed() async {
addTestFile('''
class A {
A(BBB p) {}
@@ -392,7 +396,7 @@
assertHasRegionTarget('BBB p', 'BBB {}');
}
- Future<void> test_constructorReference_named() async {
+ Future<void> test_class_constructorReference_named() async {
addTestFile('''
class A {}
class B<T> {
@@ -408,7 +412,7 @@
assertHasRegionTarget('A>', 'A {}');
}
- Future<void> test_constructorReference_unnamed_declared() async {
+ Future<void> test_class_constructorReference_unnamed_declared() async {
addTestFile('''
class A {
A();
@@ -422,7 +426,7 @@
assertHasRegionTarget('new;', 'A();', targetLength: 0);
}
- Future<void> test_constructorReference_unnamed_declared_new() async {
+ Future<void> test_class_constructorReference_unnamed_declared_new() async {
addTestFile('''
class A {
A.new();
@@ -436,7 +440,7 @@
assertHasRegionTarget('new;', 'new();');
}
- Future<void> test_constructorReference_unnamed_default() async {
+ Future<void> test_class_constructorReference_unnamed_default() async {
addTestFile('''
class A {}
void f() {
@@ -448,55 +452,7 @@
assertHasRegionTarget('new;', 'A {}');
}
- Future<void> test_enum_constant() async {
- addTestFile('''
-enum E { a, b }
-void f() {
- E.a;
-}
-''');
- await prepareNavigation();
- assertHasRegion('a;');
- assertHasTarget('a,');
- }
-
- Future<void> test_enum_index() async {
- addTestFile('''
-enum E { a, b }
-void f() {
- E.a.index;
-}
-''');
- await prepareNavigation();
- assertHasRegion('index');
- assertHasTarget('E {');
- }
-
- Future<void> test_enum_values() async {
- addTestFile('''
-enum E { a, b }
-void f() {
- E.values;
-}
-''');
- await prepareNavigation();
- assertHasRegion('values');
- assertHasTarget('E');
- }
-
- Future<void> test_extension_on() async {
- addTestFile('''
-class C //1
-{}
-extension E on C //2
-{}
-''');
- await prepareNavigation();
- assertHasRegion('C //2');
- assertHasTarget('C //1');
- }
-
- Future<void> test_factoryRedirectingConstructor_implicit() async {
+ Future<void> test_class_factoryRedirectingConstructor_implicit() async {
addTestFile('''
class A {
factory A() = B;
@@ -510,7 +466,7 @@
}
Future<void>
- test_factoryRedirectingConstructor_implicit_withTypeArgument() async {
+ test_class_factoryRedirectingConstructor_implicit_withTypeArgument() async {
addTestFile('''
class A {}
class B {
@@ -529,7 +485,7 @@
}
}
- Future<void> test_factoryRedirectingConstructor_named() async {
+ Future<void> test_class_factoryRedirectingConstructor_named() async {
addTestFile('''
class A {
factory A() = B.named;
@@ -550,7 +506,7 @@
}
Future<void>
- test_factoryRedirectingConstructor_named_withTypeArgument() async {
+ test_class_factoryRedirectingConstructor_named_withTypeArgument() async {
addTestFile('''
class A {}
class B {
@@ -575,7 +531,7 @@
}
}
- Future<void> test_factoryRedirectingConstructor_unnamed() async {
+ Future<void> test_class_factoryRedirectingConstructor_unnamed() async {
addTestFile('''
class A {
factory A() = B;
@@ -590,7 +546,7 @@
}
Future<void>
- test_factoryRedirectingConstructor_unnamed_withTypeArgument() async {
+ test_class_factoryRedirectingConstructor_unnamed_withTypeArgument() async {
addTestFile('''
class A {}
class B {
@@ -611,7 +567,7 @@
}
}
- Future<void> test_factoryRedirectingConstructor_unresolved() async {
+ Future<void> test_class_factoryRedirectingConstructor_unresolved() async {
addTestFile('''
class A {
factory A() = B;
@@ -621,7 +577,7 @@
// don't check regions, but there should be no exceptions
}
- Future<void> test_fieldFormalParameter() async {
+ Future<void> test_class_fieldFormalParameter() async {
addTestFile('''
class AAA {
int fff = 123;
@@ -632,7 +588,7 @@
assertHasRegionTarget('fff);', 'fff = 123');
}
- Future<void> test_fieldFormalParameter_unresolved() async {
+ Future<void> test_class_fieldFormalParameter_unresolved() async {
addTestFile('''
class AAA {
AAA(this.fff);
@@ -642,6 +598,201 @@
assertNoRegion('fff);', 3);
}
+ Future<void> test_class_fromSDK() async {
+ addTestFile('''
+int V = 42;
+''');
+ await prepareNavigation();
+ assertHasRegion('int V');
+ var targetIndex = testTargetIndexes[0];
+ var target = targets[targetIndex];
+ expect(target.startLine, greaterThan(0));
+ expect(target.startColumn, greaterThan(0));
+ }
+
+ Future<void> test_enum_constant() async {
+ addTestFile('''
+enum E { a, b }
+void f() {
+ E.a;
+}
+''');
+ await prepareNavigation();
+ assertHasRegion('a;');
+ assertHasTarget('a,');
+ }
+
+ Future<void> test_enum_constructor_named() async {
+ addTestFile('''
+const a = 0;
+
+enum E<T> {
+ v<int>.named(a); // 1
+ E.named(int _) {}
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('v<int', 'named(int');
+ assertHasRegion('int>');
+ assertHasRegionTarget('named(a); // 1', 'named(int');
+ assertHasRegionTarget('a); // 1', 'a = 0');
+
+ assertHasRegion('int _');
+ }
+
+ Future<void> test_enum_constructor_unnamed() async {
+ addTestFile('''
+enum E {
+ v1,
+ v2(),
+ v3.new();
+ const E();
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('v1', 'E();', targetLength: 0);
+ assertHasRegionTarget('v2()', 'E();', targetLength: 0);
+ assertHasRegionTarget('v3', 'E();', targetLength: 0);
+ assertHasRegionTarget('new()', 'E();', targetLength: 0);
+ }
+
+ Future<void> test_enum_field() async {
+ addTestFile('''
+enum E {
+ v;
+ final int foo = 0;
+ void bar() {
+ foo;
+ foo = 1;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int foo');
+ assertHasRegionTarget('foo;', 'foo = 0;');
+ assertHasRegionTarget('foo = 1;', 'foo = 0;');
+ }
+
+ Future<void> test_enum_getter() async {
+ addTestFile('''
+enum E {
+ v;
+ int get foo => 0;
+ void bar() {
+ foo;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int get');
+ assertHasRegionTarget('foo;', 'foo =>');
+ }
+
+ Future<void> test_enum_implements() async {
+ addTestFile('''
+class A {}
+
+enum E implements A { // ref
+ v
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('A { // ref', 'A {}');
+ }
+
+ Future<void> test_enum_index() async {
+ addTestFile('''
+enum E { a, b }
+void f() {
+ E.a.index;
+}
+''');
+ await prepareNavigation();
+ assertHasRegion('index');
+ assertHasTargetInDartCore('index;');
+ }
+
+ Future<void> test_enum_method() async {
+ addTestFile('''
+enum E {
+ v;
+ void foo(int a) {}
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int ');
+ }
+
+ Future<void> test_enum_setter() async {
+ addTestFile('''
+enum E {
+ v;
+ set foo(int _) {}
+ void bar() {
+ foo = 0;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int _');
+ assertHasRegionTarget('foo = 0;', 'foo(');
+ }
+
+ Future<void> test_enum_typeParameter() async {
+ addTestFile('''
+enum E<T> {
+ v(0);
+ const E(T t);
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('T t', 'T>');
+ }
+
+ Future<void> test_enum_values() async {
+ addTestFile('''
+enum E { a, b }
+void f() {
+ E.values;
+}
+''');
+ await prepareNavigation();
+ assertHasRegion('values');
+ assertHasTarget('E');
+ }
+
+ Future<void> test_enum_with() async {
+ addTestFile('''
+mixin M {}
+
+enum E with M { // ref
+ v
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('M { // ref', 'M {}');
+ }
+
+ Future<void> test_extension_on() async {
+ addTestFile('''
+class C //1
+{}
+extension E on C //2
+{}
+''');
+ await prepareNavigation();
+ assertHasRegion('C //2');
+ assertHasTarget('C //1');
+ }
+
Future<void> test_functionReference_className_staticMethod() async {
addTestFile('''
class A {
@@ -932,6 +1083,19 @@
assertNoRegionAt('TEST');
}
+ Future<void> test_namedExpression_name() async {
+ addTestFile('''
+void f(int a, int b, {int? c, int? d}) {}
+
+void g() {
+ f(0, c: 2, 1, d: 3);
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('c: 2', 'c,');
+ assertHasRegionTarget('d: 3', 'd}) {}');
+ }
+
Future<void> test_operator_arithmetic() async {
addTestFile('''
class A {
diff --git a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
index 777e230..5bf1c3b 100644
--- a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
@@ -109,6 +109,113 @@
assertHasOffset('vvv);');
}
+ Future<void> test_enum() async {
+ addTestFile('''
+enum E {
+ v;
+}
+
+void f(E e) {
+ E.v;
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('E e');
+ expect(testOccurrences.element.kind, ElementKind.ENUM);
+ expect(testOccurrences.element.name, 'E');
+ assertHasOffset('E e');
+ assertHasOffset('E.v');
+ }
+
+ Future<void> test_enum_constant() async {
+ addTestFile('''
+enum E {
+ v; // 0
+}
+
+void f() {
+ E.v; // 1
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('v; // 0');
+ expect(testOccurrences.element.kind, ElementKind.ENUM_CONSTANT);
+ expect(testOccurrences.element.name, 'v');
+ assertHasOffset('v; // 1');
+ }
+
+ Future<void> test_enum_field() async {
+ addTestFile('''
+enum E {
+ v;
+ final int foo = 0;
+}
+
+void f(E e) {
+ e.foo;
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('foo = 0');
+ expect(testOccurrences.element.kind, ElementKind.FIELD);
+ expect(testOccurrences.element.name, 'foo');
+ assertHasOffset('foo;');
+ }
+
+ Future<void> test_enum_getter() async {
+ addTestFile('''
+enum E {
+ v;
+ int get foo => 0;
+}
+
+void f(E e) {
+ e.foo;
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('foo => 0');
+ expect(testOccurrences.element.kind, ElementKind.FIELD);
+ expect(testOccurrences.element.name, 'foo');
+ assertHasOffset('foo;');
+ }
+
+ Future<void> test_enum_method() async {
+ addTestFile('''
+enum E {
+ v;
+ void foo() {}
+}
+
+void f(E e) {
+ e.foo();
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('foo() {}');
+ expect(testOccurrences.element.kind, ElementKind.METHOD);
+ expect(testOccurrences.element.name, 'foo');
+ assertHasOffset('foo();');
+ }
+
+ Future<void> test_enum_setter() async {
+ addTestFile('''
+enum E {
+ v;
+ set foo(int _) {}
+}
+
+void f(E e) {
+ e.foo = 0;
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('foo(int _) {}');
+ expect(testOccurrences.element.kind, ElementKind.FIELD);
+ expect(testOccurrences.element.name, 'foo');
+ assertHasOffset('foo = 0;');
+ }
+
Future<void> test_field() async {
addTestFile('''
class A {
@@ -193,6 +300,52 @@
assertHasOffset('mmm(); // b');
}
+ Future<void> test_parameter_named() async {
+ addTestFile('''
+void f(int aaa, int bbb, {int? ccc, int? ddd}) {
+ ccc;
+ ddd;
+}
+
+void g() {
+ f(0, ccc: 2, 1, ddd: 3);
+}
+''');
+ await prepareOccurrences();
+
+ assertHasRegion('ccc: 2');
+ expect(testOccurrences.element.kind, ElementKind.PARAMETER);
+ assertHasOffset('ccc,');
+ assertHasOffset('ccc;');
+ assertHasOffset('ccc: 2');
+
+ assertHasRegion('ddd: 3');
+ expect(testOccurrences.element.kind, ElementKind.PARAMETER);
+ assertHasOffset('ddd})');
+ assertHasOffset('ddd;');
+ assertHasOffset('ddd: 3');
+ }
+
+ Future<void> test_superFormalParameter_requiredPositional() async {
+ addTestFile('''
+class A {
+ A(int x);
+}
+
+class B extends A {
+ int y;
+
+ B(super.x) : y = x * 2;
+}
+''');
+ await prepareOccurrences();
+ assertHasRegion('x) :');
+ expect(testOccurrences.element.kind, ElementKind.PARAMETER);
+ expect(testOccurrences.element.name, 'x');
+ assertHasOffset('x) :');
+ assertHasOffset('x * 2');
+ }
+
Future<void> test_topLevelVariable() async {
addTestFile('''
var VVV = 1;
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index bc48633..3ce1928 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -142,7 +142,7 @@
assertHasInterfaceMember('m() {} // in A');
}
- Future<void> test_BAD_fieldByMethod() async {
+ Future<void> test_class_BAD_fieldByMethod() async {
addTestFile('''
class A {
int fff; // in A
@@ -155,7 +155,7 @@
assertNoOverride('fff() {} // in B');
}
- Future<void> test_BAD_getterByMethod() async {
+ Future<void> test_class_BAD_getterByMethod() async {
addTestFile('''
class A {
get fff => null;
@@ -168,7 +168,7 @@
assertNoOverride('fff() {}');
}
- Future<void> test_BAD_getterBySetter() async {
+ Future<void> test_class_BAD_getterBySetter() async {
addTestFile('''
class A {
get fff => null;
@@ -181,7 +181,7 @@
assertNoOverride('fff(x) {}');
}
- Future<void> test_BAD_methodByField() async {
+ Future<void> test_class_BAD_methodByField() async {
addTestFile('''
class A {
fff() {} // in A
@@ -194,7 +194,7 @@
assertNoOverride('fff; // in B');
}
- Future<void> test_BAD_methodByGetter() async {
+ Future<void> test_class_BAD_methodByGetter() async {
addTestFile('''
class A {
fff() {}
@@ -207,7 +207,7 @@
assertNoOverride('fff => null');
}
- Future<void> test_BAD_methodBySetter() async {
+ Future<void> test_class_BAD_methodBySetter() async {
addTestFile('''
class A {
fff(x) {} // A
@@ -220,7 +220,7 @@
assertNoOverride('fff(x) {} // B');
}
- Future<void> test_BAD_privateByPrivate_inDifferentLib() async {
+ Future<void> test_class_BAD_privateByPrivate_inDifferentLib() async {
newFile(join(testFolder, 'lib.dart'), content: r'''
class A {
void _m() {}
@@ -236,7 +236,7 @@
assertNoOverride('_m() {} // in B');
}
- Future<void> test_BAD_setterByGetter() async {
+ Future<void> test_class_BAD_setterByGetter() async {
addTestFile('''
class A {
set fff(x) {}
@@ -249,7 +249,7 @@
assertNoOverride('fff => null;');
}
- Future<void> test_BAD_setterByMethod() async {
+ Future<void> test_class_BAD_setterByMethod() async {
addTestFile('''
class A {
set fff(x) {} // A
@@ -262,7 +262,7 @@
assertNoOverride('fff(x) {} // B');
}
- Future<void> test_definedInInterface_ofInterface() async {
+ Future<void> test_class_definedInInterface_ofInterface() async {
addTestFile('''
class A {
m() {} // in A
@@ -278,7 +278,7 @@
assertHasInterfaceMember('m() {} // in A');
}
- Future<void> test_definedInInterface_ofSuper() async {
+ Future<void> test_class_definedInInterface_ofSuper() async {
addTestFile('''
class A {
m() {} // in A
@@ -294,39 +294,7 @@
assertHasInterfaceMember('m() {} // in A');
}
- Future<void> test_inMixin_interface_method_direct_single() async {
- addTestFile('''
-class A {
- m() {} // in A
-}
-
-mixin M implements A {
- m() {} // in M
-}
-''');
- await prepareOverrides();
- assertHasOverride('m() {} // in M');
- assertNoSuperMember();
- assertHasInterfaceMember('m() {} // in A');
- }
-
- Future<void> test_inMixin_superclassConstraint_method_direct() async {
- addTestFile('''
-class A {
- m() {} // in A
-}
-
-mixin M on A {
- m() {} // in M
-}
-''');
- await prepareOverrides();
- assertHasOverride('m() {} // in M');
- assertHasSuperElement('m() {} // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_interface_method_direct_multiple() async {
+ Future<void> test_class_interface_method_direct_multiple() async {
addTestFile('''
class IA {
m() {} // in IA
@@ -345,7 +313,7 @@
assertHasInterfaceMember('m() {} // in IB');
}
- Future<void> test_interface_method_direct_single() async {
+ Future<void> test_class_interface_method_direct_single() async {
addTestFile('''
class A {
m() {} // in A
@@ -360,7 +328,7 @@
assertHasInterfaceMember('m() {} // in A');
}
- Future<void> test_interface_method_indirect_single() async {
+ Future<void> test_class_interface_method_indirect_single() async {
addTestFile('''
class A {
m() {} // in A
@@ -377,7 +345,7 @@
assertHasInterfaceMember('m() {} // in A');
}
- Future<void> test_interface_stopWhenFound() async {
+ Future<void> test_class_interface_stopWhenFound() async {
addTestFile('''
class A {
m() {} // in A
@@ -395,7 +363,7 @@
assertHasInterfaceMember('m() {} // in B');
}
- Future<void> test_mix_sameMethod() async {
+ Future<void> test_class_mix_sameMethod() async {
addTestFile('''
class A {
m() {} // in A
@@ -412,7 +380,7 @@
assertNoInterfaceMembers();
}
- Future<void> test_mix_sameMethod_Object_hashCode() async {
+ Future<void> test_class_mix_sameMethod_Object_hashCode() async {
addTestFile('''
class A {}
abstract class B {}
@@ -426,6 +394,536 @@
expect(overrideObject.interfaceMembers, isNull);
}
+ Future<void> test_class_staticMembers() async {
+ addTestFile('''
+class A {
+ static int F = 0;
+ static void M() {}
+ static int get G => 0;
+ static void set S(int v) {}
+}
+class B extends A {
+ static int F = 0;
+ static void M() {}
+ static int get G => 0;
+ static void set S(int v) {}
+}
+''');
+ await prepareOverrides();
+ expect(overridesList, isEmpty);
+ }
+
+ Future<void> test_class_super_fieldByField() async {
+ addTestFile('''
+class A {
+ int fff; // in A
+}
+class B extends A {
+ int fff; // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff; // in B');
+ assertHasSuperElement('fff; // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_fieldByGetter() async {
+ addTestFile('''
+class A {
+ int fff; // in A
+}
+class B extends A {
+ get fff => 0; // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff => 0; // in B');
+ assertHasSuperElement('fff; // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_fieldBySetter() async {
+ addTestFile('''
+class A {
+ int fff; // in A
+}
+class B extends A {
+ set fff(x) {} // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff(x) {} // in B');
+ assertHasSuperElement('fff; // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_getterByField() async {
+ addTestFile('''
+class A {
+ get fff => 0; // in A
+ set fff(x) {} // in A
+}
+class B extends A {
+ int fff; // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff; // in B');
+ assertHasSuperElement('fff => 0; // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_getterByGetter() async {
+ addTestFile('''
+class A {
+ get fff => 0; // in A
+}
+class B extends A {
+ get fff => 0; // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff => 0; // in B');
+ assertHasSuperElement('fff => 0; // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_method_direct() async {
+ addTestFile('''
+class A {
+ m() {} // in A
+}
+class B extends A {
+ m() {} // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('m() {} // in B');
+ assertHasSuperElement('m() {} // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_method_indirect() async {
+ addTestFile('''
+class A {
+ m() {} // in A
+}
+class B extends A {
+}
+class C extends B {
+ m() {} // in C
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('m() {} // in C');
+ assertHasSuperElement('m() {} // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_method_privateByPrivate() async {
+ addTestFile('''
+class A {
+ _m() {} // in A
+}
+class B extends A {
+ _m() {} // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('_m() {} // in B');
+ assertHasSuperElement('_m() {} // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_class_super_method_superTypeCycle() async {
+ addTestFile('''
+class A extends B {
+ m() {} // in A
+}
+class B extends A {
+ m() {} // in B
+}
+''');
+ await prepareOverrides();
+ // must finish
+ }
+
+ Future<void> test_class_super_setterBySetter() async {
+ addTestFile('''
+class A {
+ set fff(x) {} // in A
+}
+class B extends A {
+ set fff(x) {} // in B
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('fff(x) {} // in B');
+ assertHasSuperElement('fff(x) {} // in A');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_interface_getterByGetter() async {
+ addTestFile('''
+class A {
+ int get foo => 0; // A
+}
+
+enum E implements A {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo => 0; // E');
+ assertNoSuperMember();
+ assertHasInterfaceMember('foo => 0; // A');
+ }
+
+ Future<void> test_enum_interface_methodByMethod() async {
+ addTestFile('''
+class A {
+ void foo() {} // A
+}
+
+enum E implements A {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo() {} // E');
+ assertNoSuperMember();
+ assertHasInterfaceMember('foo() {} // A');
+ }
+
+ Future<void> test_enum_interface_methodByMethod2() async {
+ addTestFile('''
+class A {
+ void foo() {} // A
+}
+
+class B {
+ void foo() {} // B
+}
+
+enum E implements A, B {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo() {} // E');
+ assertNoSuperMember();
+ assertHasInterfaceMember('foo() {} // A');
+ assertHasInterfaceMember('foo() {} // B');
+ }
+
+ Future<void> test_enum_interface_methodByMethod_indirect() async {
+ addTestFile('''
+abstract class A {
+ void foo(); // A
+}
+
+abstract class B implements A {}
+
+enum E implements B {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo() {} // E');
+ assertNoSuperMember();
+ assertHasInterfaceMember('foo(); // A');
+ }
+
+ Future<void> test_enum_interface_setterBySetter() async {
+ addTestFile('''
+class A {
+ set foo(int _) {} // A
+}
+
+enum E implements A {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo(int _) {} // E');
+ assertNoSuperMember();
+ assertHasInterfaceMember('foo(int _) {} // A');
+ }
+
+ Future<void> test_enum_super_fieldByField() async {
+ addTestFile('''
+mixin M {
+ final int foo = 0; // M
+}
+
+enum E with M {
+ v;
+ final int foo = 0; // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo = 0; // E');
+ assertHasSuperElement('foo = 0; // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_super_fieldByGetter() async {
+ addTestFile('''
+mixin M {
+ final int foo = 0; // M
+}
+
+enum E with M {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo => 0; // E');
+ assertHasSuperElement('foo = 0; // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_super_fieldByMethod() async {
+ addTestFile('''
+mixin M {
+ final int foo = 0; // M
+}
+
+enum E with M {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo() {} // E');
+ }
+
+ Future<void> test_enum_super_fieldBySetter() async {
+ addTestFile('''
+mixin M {
+ final int foo = 0; // M
+}
+
+enum E with M {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo(int _) {} // E');
+ }
+
+ Future<void> test_enum_super_getterByField() async {
+ addTestFile('''
+mixin M {
+ int get foo => 0; // M
+}
+
+enum E with M {
+ v;
+ final int foo = 0; // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo = 0; // E');
+ assertHasSuperElement('foo => 0; // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_super_getterByGetter() async {
+ addTestFile('''
+mixin M {
+ int get foo => 0; // M
+}
+
+enum E with M {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo => 0; // E');
+ assertHasSuperElement('foo => 0; // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_super_getterByMethod() async {
+ addTestFile('''
+mixin M {
+ int get foo => 0; // M
+}
+
+enum E with M {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo() {} // E');
+ }
+
+ Future<void> test_enum_super_getterBySetter() async {
+ addTestFile('''
+mixin M {
+ int get foo => 0; // M
+}
+
+enum E with M {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo(int _) {} // E');
+ }
+
+ Future<void> test_enum_super_methodByField() async {
+ addTestFile('''
+mixin M {
+ void foo() {} // M
+}
+
+enum E with M {
+ v;
+ final int foo = 0; // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo = 0; // E');
+ }
+
+ Future<void> test_enum_super_methodByGetter() async {
+ addTestFile('''
+mixin M {
+ void foo() {} // M
+}
+
+enum E with M {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo => 0; // E');
+ }
+
+ Future<void> test_enum_super_methodByMethod() async {
+ addTestFile('''
+mixin M {
+ void foo() {} // M
+}
+
+enum E with M {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo() {} // E');
+ assertHasSuperElement('foo() {} // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_enum_super_methodBySetter() async {
+ addTestFile('''
+mixin M {
+ void foo() {} // M
+}
+
+enum E with M {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo(int _) {} // E');
+ }
+
+ Future<void> test_enum_super_setterByField() async {
+ addTestFile('''
+mixin M {
+ set foo(int _) {} // M
+}
+
+enum E with M {
+ v;
+ final int foo = 0; // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo = 0; // E');
+ }
+
+ Future<void> test_enum_super_setterByGetter() async {
+ addTestFile('''
+mixin M {
+ set foo(int _) {} // M
+}
+
+enum E with M {
+ v;
+ int get foo => 0; // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo => 0; // E');
+ }
+
+ Future<void> test_enum_super_setterByMethod() async {
+ addTestFile('''
+mixin M {
+ set foo(int _) {} // M
+}
+
+enum E with M {
+ v;
+ void foo() {} // E
+}
+''');
+ await prepareOverrides();
+ assertNoOverride('foo() {} // E');
+ }
+
+ Future<void> test_enum_super_setterBySetter() async {
+ addTestFile('''
+mixin M {
+ set foo(int _) {} // M
+}
+
+enum E with M {
+ v;
+ set foo(int _) {} // E
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('foo(int _) {} // E');
+ assertHasSuperElement('foo(int _) {} // M');
+ assertNoInterfaceMembers();
+ }
+
+ Future<void> test_mixin_interface_method_direct_single() async {
+ addTestFile('''
+class A {
+ m() {} // in A
+}
+
+mixin M implements A {
+ m() {} // in M
+}
+''');
+ await prepareOverrides();
+ assertHasOverride('m() {} // in M');
+ assertNoSuperMember();
+ assertHasInterfaceMember('m() {} // in A');
+ }
+
Future<void> test_mixin_method_direct() async {
addTestFile('''
class A {
@@ -475,173 +973,19 @@
assertNoInterfaceMembers();
}
- Future<void> test_staticMembers() async {
- addTestFile('''
-class A {
- static int F = 0;
- static void M() {}
- static int get G => 0;
- static void set S(int v) {}
-}
-class B extends A {
- static int F = 0;
- static void M() {}
- static int get G => 0;
- static void set S(int v) {}
-}
-''');
- await prepareOverrides();
- expect(overridesList, isEmpty);
- }
-
- Future<void> test_super_fieldByField() async {
- addTestFile('''
-class A {
- int fff; // in A
-}
-class B extends A {
- int fff; // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff; // in B');
- assertHasSuperElement('fff; // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_fieldByGetter() async {
- addTestFile('''
-class A {
- int fff; // in A
-}
-class B extends A {
- get fff => 0; // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff => 0; // in B');
- assertHasSuperElement('fff; // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_fieldBySetter() async {
- addTestFile('''
-class A {
- int fff; // in A
-}
-class B extends A {
- set fff(x) {} // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff(x) {} // in B');
- assertHasSuperElement('fff; // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_getterByField() async {
- addTestFile('''
-class A {
- get fff => 0; // in A
- set fff(x) {} // in A
-}
-class B extends A {
- int fff; // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff; // in B');
- assertHasSuperElement('fff => 0; // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_getterByGetter() async {
- addTestFile('''
-class A {
- get fff => 0; // in A
-}
-class B extends A {
- get fff => 0; // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff => 0; // in B');
- assertHasSuperElement('fff => 0; // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_method_direct() async {
+ Future<void> test_mixin_superclassConstraint_method_direct() async {
addTestFile('''
class A {
m() {} // in A
}
-class B extends A {
- m() {} // in B
+
+mixin M on A {
+ m() {} // in M
}
''');
await prepareOverrides();
- assertHasOverride('m() {} // in B');
+ assertHasOverride('m() {} // in M');
assertHasSuperElement('m() {} // in A');
assertNoInterfaceMembers();
}
-
- Future<void> test_super_method_indirect() async {
- addTestFile('''
-class A {
- m() {} // in A
-}
-class B extends A {
-}
-class C extends B {
- m() {} // in C
-}
-''');
- await prepareOverrides();
- assertHasOverride('m() {} // in C');
- assertHasSuperElement('m() {} // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_method_privateByPrivate() async {
- addTestFile('''
-class A {
- _m() {} // in A
-}
-class B extends A {
- _m() {} // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('_m() {} // in B');
- assertHasSuperElement('_m() {} // in A');
- assertNoInterfaceMembers();
- }
-
- Future<void> test_super_method_superTypeCycle() async {
- addTestFile('''
-class A extends B {
- m() {} // in A
-}
-class B extends A {
- m() {} // in B
-}
-''');
- await prepareOverrides();
- // must finish
- }
-
- Future<void> test_super_setterBySetter() async {
- addTestFile('''
-class A {
- set fff(x) {} // in A
-}
-class B extends A {
- set fff(x) {} // in B
-}
-''');
- await prepareOverrides();
- assertHasOverride('fff(x) {} // in B');
- assertHasSuperElement('fff(x) {} // in A');
- assertNoInterfaceMembers();
- }
}
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 3045889..df45776 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -202,11 +202,7 @@
server = createAnalysisServer();
server.pluginManager = pluginManager;
handler = analysisHandler;
- // listen for notifications
- var notificationStream = serverChannel.notificationController.stream;
- notificationStream.listen((Notification notification) {
- processNotification(notification);
- });
+ serverChannel.notifications.listen(processNotification);
}
@mustCallSuper
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 3546ca2..9ac113c 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -135,10 +135,10 @@
// Track diagnostics that arrive.
final errorsByFile = <String, List<AnalysisError>>{};
- channel.notificationController.stream
+ channel.notifications
.where((notification) => notification.event == 'analysis.errors')
- .listen((notificaton) {
- final params = AnalysisErrorsParams.fromNotification(notificaton);
+ .listen((notification) {
+ final params = AnalysisErrorsParams.fromNotification(notification);
errorsByFile[params.file] = params.errors;
});
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 52c2abf..47c6443 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -4,12 +4,11 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/services/completion/dart/utilities.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
-import 'package:meta/meta.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../domain_completion_test.dart';
import '../services/completion/dart/completion_check.dart';
import '../services/completion/dart/completion_contributor_util.dart';
import 'impl/completion_driver.dart';
@@ -23,30 +22,33 @@
});
}
-abstract class AbstractCompletionDriverTest with ResourceProviderMixin {
+abstract class AbstractCompletionDriverTest
+ extends PubPackageAnalysisServerTest {
late CompletionDriver driver;
- Map<String, String> packageRoots = {};
late List<CompletionSuggestion> suggestions;
- String get projectName => 'project';
-
- String get projectPath => '/$projectName';
+ bool get isProtocolVersion2 {
+ return protocol == TestingCompletionProtocol.version2;
+ }
TestingCompletionProtocol get protocol;
AnalysisServerOptions get serverOptions => AnalysisServerOptions();
- bool get supportsAvailableSuggestions;
-
- String get testFilePath => '$projectPath/bin/test.dart';
+ bool get _isProtocolVersion1 {
+ return protocol == TestingCompletionProtocol.version1;
+ }
Future<void> addProjectFile(String relativePath, String content) async {
- newFile('$projectPath/$relativePath', content: content);
+ newFile('$testPackageRootPath/$relativePath', content: content);
// todo (pq): handle more than lib
expect(relativePath, startsWith('lib/'));
var packageRelativePath = relativePath.substring(4);
- var uriStr = 'package:$projectName/$packageRelativePath';
- await driver.waitForSetWithUri(uriStr);
+ var uriStr = 'package:test/$packageRelativePath';
+
+ if (_isProtocolVersion1) {
+ await driver.waitForSetWithUri(uriStr);
+ }
}
Future<List<CompletionSuggestion>> addTestFile(String content,
@@ -108,7 +110,7 @@
}
Future<List<CompletionSuggestion>> getSuggestions() async {
- if (supportsAvailableSuggestions) {
+ if (_isProtocolVersion1) {
await driver.waitForSetWithUri('dart:core');
await driver.waitForSetWithUri('dart:async');
}
@@ -148,23 +150,20 @@
}
}
- @mustCallSuper
+ @override
Future<void> setUp() async {
- driver = CompletionDriver(
- supportsAvailableSuggestions: supportsAvailableSuggestions,
- projectPath: projectPath,
- testFilePath: testFilePath,
- resourceProvider: resourceProvider,
- serverOptions: serverOptions,
- );
- await driver.createProject(packageRoots: packageRoots);
+ super.setUp();
- newPubspecYamlFile(projectPath, '''
-name: project
+ writeTestPackagePubspecYamlFile(r'''
+name: test
''');
- newDotPackagesFile(projectPath, content: '''
-project:${toUri('$projectPath/lib')}
-''');
+
+ driver = CompletionDriver(
+ supportsAvailableSuggestions: _isProtocolVersion1,
+ server: this,
+ );
+ await driver.createProject();
+
// todo (pq): add logic (possibly to driver) that waits for SDK suggestions
}
@@ -240,9 +239,6 @@
}
mixin BasicCompletionTestCases on AbstractCompletionDriverTest {
- @override
- bool get supportsAvailableSuggestions => false;
-
/// Duplicates (and potentially replaces DeprecatedMemberRelevanceTest).
Future<void> test_deprecated_member_relevance() async {
await addTestFile('''
@@ -307,12 +303,6 @@
}
mixin CompletionWithSuggestionsTestCases on AbstractCompletionDriverTest {
- @override
- bool get supportsAvailableSuggestions => true;
-
- @override
- String get testFilePath => '$projectPath/lib/test.dart';
-
Future<void> test_project_filterImports_defaultConstructor() async {
await addProjectFile('lib/a.dart', r'''
class A {}
diff --git a/pkg/analysis_server/test/client/impl/abstract_client.dart b/pkg/analysis_server/test/client/impl/abstract_client.dart
deleted file mode 100644
index d1ad27f..0000000
--- a/pkg/analysis_server/test/client/impl/abstract_client.dart
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/protocol/protocol.dart';
-import 'package:analysis_server/protocol/protocol_generated.dart'
- hide AnalysisOptions;
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analysis_server/src/domain_completion.dart';
-import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
-import 'package:analysis_server/src/utilities/mocks.dart';
-import 'package:analysis_server/src/utilities/progress.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:matcher/matcher.dart';
-import 'package:meta/meta.dart';
-
-import '../../mocks.dart';
-
-abstract class AbstractClient {
- final MockServerChannel serverChannel;
- final TestPluginManager pluginManager;
- late AnalysisServer server;
-
- final List<GeneralAnalysisService> generalServices =
- <GeneralAnalysisService>[];
- final Map<AnalysisService, List<String>> analysisSubscriptions = {};
-
- final String projectPath;
- final String testFilePath;
- late String testCode;
-
- final AnalysisServerOptions serverOptions;
-
- AbstractClient({
- required this.projectPath,
- required this.testFilePath,
- required String sdkPath,
- required this.serverOptions,
- }) : serverChannel = MockServerChannel(),
- pluginManager = TestPluginManager() {
- server = createAnalysisServer(sdkPath);
- var notificationStream = serverChannel.notificationController.stream;
- notificationStream.listen((Notification notification) {
- processNotification(notification);
- });
- }
-
- AnalysisDomainHandler get analysisHandler =>
- server.handlers.singleWhere((handler) => handler is AnalysisDomainHandler)
- as AnalysisDomainHandler;
-
- AnalysisOptions get analysisOptions => testDriver.analysisOptions;
-
- CompletionDomainHandler get completionHandler =>
- server.handlers.whereType<CompletionDomainHandler>().single;
-
- MemoryResourceProvider get resourceProvider;
-
- AnalysisDriver get testDriver => server.getAnalysisDriver(testFilePath)!;
-
- void addAnalysisOptionsFile(String content) {
- newFile(
- resourceProvider.pathContext.join(projectPath, 'analysis_options.yaml'),
- content);
- }
-
- void addAnalysisSubscription(AnalysisService service, String file) {
- // add file to subscription
- var files = analysisSubscriptions[service];
- if (files == null) {
- files = <String>[];
- analysisSubscriptions[service] = files;
- }
- files.add(file);
- // set subscriptions
- var request =
- AnalysisSetSubscriptionsParams(analysisSubscriptions).toRequest('0');
- handleSuccessfulRequest(request);
- }
-
- void addGeneralAnalysisSubscription(GeneralAnalysisService service) {
- generalServices.add(service);
- var request =
- AnalysisSetGeneralSubscriptionsParams(generalServices).toRequest('0');
- handleSuccessfulRequest(request);
- }
-
- String addTestFile(String content) {
- newFile(testFilePath, content);
- testCode = content;
- return testFilePath;
- }
-
- void assertValidId(String id) {
- expect(id, isNotNull);
- expect(id.isNotEmpty, isTrue);
- }
-
- /// Create an analysis server with the given [sdkPath].
- AnalysisServer createAnalysisServer(String sdkPath) {
- createMockSdk(
- resourceProvider: resourceProvider,
- root: newFolder(sdkPath),
- );
- return AnalysisServer(
- serverChannel,
- resourceProvider,
- serverOptions,
- DartSdkManager(sdkPath),
- CrashReportingAttachmentsBuilder.empty,
- InstrumentationService.NULL_SERVICE);
- }
-
- /// Create a project at [projectPath].
- @mustCallSuper
- Future<void> createProject({Map<String, String>? packageRoots}) async {
- newFolder(projectPath);
-
- await setRoots(
- included: [projectPath], excluded: [], packageRoots: packageRoots);
- }
-
- void expect(actual, matcher, {String reason});
-
- /// Validate that the given [request] is handled successfully.
- Response handleSuccessfulRequest(Request request, {RequestHandler? handler}) {
- handler ??= analysisHandler;
- var response = handler.handleRequest(request, NotCancelableToken())!;
- expect(response, isResponseSuccess(request.id));
- return response;
- }
-
- File newFile(String path, String content);
-
- Folder newFolder(String path);
-
- void processNotification(Notification notification);
-
- Future<Response> setRoots({
- required List<String> included,
- required List<String> excluded,
- Map<String, String>? packageRoots,
- }) async {
- var request = AnalysisSetAnalysisRootsParams(included, excluded,
- packageRoots: packageRoots)
- .toRequest('0');
- var response = await waitResponse(request);
- expect(response, isResponseSuccess(request.id));
- return response;
- }
-
- /// Returns a [Future] that completes when the server's analysis is complete.
- Future waitForTasksFinished() => server.onAnalysisComplete;
-
- /// Completes with a successful [Response] for the given [request].
- /// Otherwise fails.
- Future<Response> waitResponse(Request request,
- {bool throwOnError = true}) async {
- return serverChannel.sendRequest(request, throwOnError: throwOnError);
- }
-}
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 4907915..095db29 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -9,15 +9,12 @@
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart'
hide AnalysisOptions;
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:matcher/matcher.dart';
import 'package:meta/meta.dart';
import '../../constants.dart';
-import 'abstract_client.dart';
+import '../../domain_completion_test.dart';
import 'expect_mixin.dart';
CompletionSuggestion _createCompletionSuggestionFromAvailableSuggestion(
@@ -39,9 +36,16 @@
}
}
+ // todo (pq): in IDEA, this is "UNKNOWN" but here we need a value; figure out what's up.
+ var suggestionKind = CompletionSuggestionKind.IDENTIFIER;
+ if (suggestion.element.kind == ElementKind.CONSTRUCTOR ||
+ suggestion.element.kind == ElementKind.FUNCTION ||
+ suggestion.element.kind == ElementKind.METHOD) {
+ suggestionKind = CompletionSuggestionKind.INVOCATION;
+ }
+
return CompletionSuggestion(
- // todo (pq): in IDEA, this is "UNKNOWN" but here we need a value; figure out what's up.
- CompletionSuggestionKind.INVOCATION,
+ suggestionKind,
suggestionSetRelevance + relevanceBoost,
suggestion.label,
0,
@@ -56,9 +60,9 @@
);
}
-class CompletionDriver extends AbstractClient with ExpectMixin {
+class CompletionDriver with ExpectMixin {
+ final PubPackageAnalysisServerTest server;
final bool supportsAvailableSuggestions;
- final MemoryResourceProvider _resourceProvider;
Map<String, Completer<void>> receivedSuggestionsCompleters = {};
List<CompletionSuggestion> suggestions = [];
@@ -78,51 +82,50 @@
CompletionDriver({
required this.supportsAvailableSuggestions,
- AnalysisServerOptions? serverOptions,
- required MemoryResourceProvider resourceProvider,
- required String projectPath,
- required String testFilePath,
- }) : _resourceProvider = resourceProvider,
- super(
- serverOptions: serverOptions ?? AnalysisServerOptions(),
- projectPath: resourceProvider.convertPath(projectPath),
- testFilePath: resourceProvider.convertPath(testFilePath),
- sdkPath: resourceProvider.convertPath('/sdk'));
+ required this.server,
+ }) {
+ server.serverChannel.notifications.listen(processNotification);
+ }
- @override
- MemoryResourceProvider get resourceProvider => _resourceProvider;
-
- @override
- String addTestFile(String content, {int? offset}) {
+ void addTestFile(String content, {int? offset}) {
completionOffset = content.indexOf('^');
if (offset != null) {
expect(completionOffset, -1, reason: 'cannot supply offset and ^');
completionOffset = offset;
- return super.addTestFile(content);
+ server.newFile(server.testFilePath, content: content);
+ } else {
+ expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+ var nextOffset = content.indexOf('^', completionOffset + 1);
+ expect(nextOffset, equals(-1), reason: 'too many ^');
+ server.newFile(server.testFilePath,
+ content: content.substring(0, completionOffset) +
+ content.substring(completionOffset + 1));
}
- expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
- var nextOffset = content.indexOf('^', completionOffset + 1);
- expect(nextOffset, equals(-1), reason: 'too many ^');
- return super.addTestFile(content.substring(0, completionOffset) +
- content.substring(completionOffset + 1));
}
- @override
- Future<void> createProject({Map<String, String>? packageRoots}) async {
- await super.createProject(packageRoots: packageRoots);
+ void assertValidId(String id) {
+ expect(id, isNotNull);
+ expect(id.isNotEmpty, isTrue);
+ }
+
+ Future<void> createProject() async {
+ await server.setRoots(included: [server.workspaceRootPath], excluded: []);
+
if (supportsAvailableSuggestions) {
- var request = CompletionSetSubscriptionsParams(
- [CompletionService.AVAILABLE_SUGGESTION_SETS]).toRequest('0');
- handleSuccessfulRequest(request, handler: completionHandler);
+ await server.handleRequest(
+ CompletionSetSubscriptionsParams([
+ CompletionService.AVAILABLE_SUGGESTION_SETS,
+ ]).toRequest('0'),
+ );
}
}
Future<List<CompletionSuggestion>> getSuggestions() async {
- await waitForTasksFinished();
-
- var request = CompletionGetSuggestionsParams(testFilePath, completionOffset)
- .toRequest('0');
- var response = await waitResponse(request);
+ var request = CompletionGetSuggestionsParams(
+ server.convertPath(server.testFilePath),
+ completionOffset,
+ ).toRequest('0');
+ var response = await server.handleRequest(request);
var result = CompletionGetSuggestionsResult.fromResponse(response);
completionId = result.id;
assertValidId(completionId);
@@ -131,30 +134,19 @@
}
Future<List<CompletionSuggestion>> getSuggestions2() async {
- await waitForTasksFinished();
-
var request = CompletionGetSuggestions2Params(
- testFilePath,
+ server.convertPath(server.testFilePath),
completionOffset,
1 << 16,
timeout: 60 * 1000,
).toRequest('0');
- var response = await waitResponse(request);
+ var response = await server.handleRequest(request);
var result = CompletionGetSuggestions2Result.fromResponse(response);
replacementOffset = result.replacementOffset;
replacementLength = result.replacementLength;
return result.suggestions;
}
- @override
- File newFile(String path, String content) =>
- resourceProvider.newFile(resourceProvider.convertPath(path), content);
-
- @override
- Folder newFolder(String path) =>
- resourceProvider.newFolder(resourceProvider.convertPath(path));
-
- @override
@mustCallSuper
Future<void> processNotification(Notification notification) async {
if (notification.event == COMPLETION_RESULTS) {
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index fe0da92..21b79b3 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -25,6 +25,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'analysis_abstract.dart';
+import 'domain_completion_test.dart';
import 'mocks.dart';
void main() {
@@ -44,8 +45,6 @@
String get myPackageTestFilePath => '$myPackageLibPath/test.dart';
- String get workspaceRootPath => '/workspace';
-
@override
void setUp() {
super.setUp();
@@ -347,15 +346,8 @@
@reflectiveTest
class AnalysisDomainPubTest extends _AnalysisDomainTest {
- String get testFilePath => '$testPackageLibPath/test.dart';
-
- String get testPackageLibPath => '$testPackageRootPath/lib';
-
- String get testPackageRootPath => '$workspaceRootPath/test';
-
- String get workspaceRootPath => '/home';
-
Future<void> test_fileSystem_addFile_analysisOptions() async {
+ deleteTestPackageAnalysisOptionsFile();
var a_path = '$testPackageLibPath/a.dart';
var b_path = '$testPackageLibPath/b.dart';
@@ -389,6 +381,7 @@
}
Future<void> test_fileSystem_addFile_analysisOptions_analysis() async {
+ deleteTestPackageAnalysisOptionsFile();
var a_path = '$testPackageLibPath/a.dart';
var options_path = '$testPackageRootPath/analysis_options.yaml';
@@ -460,16 +453,15 @@
}
Future<void> test_fileSystem_addFile_dart_dotFolder() async {
- var a_path = '$projectPath/lib/.foo/a.dart';
- var b_path = '$projectPath/lib/b.dart';
+ var a_path = '$testPackageLibPath/.foo/a.dart';
+ var b_path = '$testPackageLibPath/b.dart';
newFile(b_path, content: r'''
import '.foo/a.dart';
void f(A a) {}
''');
- await createProject();
- await pumpEventQueue();
+ await setRoots(included: [workspaceRootPath], excluded: []);
await server.onAnalysisComplete;
// We don't have a.dart, so the import cannot be resolved.
@@ -489,10 +481,10 @@
}
Future<void> test_fileSystem_addFile_dart_excluded() async {
- var a_path = '$projectPath/lib/a.dart';
- var b_path = '$projectPath/lib/b.dart';
+ var a_path = '$testPackageLibPath/a.dart';
+ var b_path = '$testPackageLibPath/b.dart';
- newAnalysisOptionsYamlFile(projectPath, content: r'''
+ newAnalysisOptionsYamlFile(testPackageRootPath, content: r'''
analyzer:
exclude:
- "**/a.dart"
@@ -503,8 +495,7 @@
void f(A a) {}
''');
- await createProject();
- await pumpEventQueue();
+ await setRoots(included: [workspaceRootPath], excluded: []);
await server.onAnalysisComplete;
// We don't have a.dart, so the import cannot be resolved.
@@ -524,6 +515,7 @@
}
Future<void> test_fileSystem_addFile_dotPackagesFile() async {
+ deleteTestPackageConfigJsonFile();
var aaaLibPath = '/packages/aaa/lib';
var a_path = '$aaaLibPath/a.dart';
@@ -562,12 +554,6 @@
newFile('$testPackageLibPath/a.dart', content: '');
- // Make sure that it is a package.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder(),
- );
-
await setRoots(included: [workspaceRootPath], excluded: []);
// No `fix_data.yaml` to analyze yet.
@@ -605,9 +591,9 @@
assertHasErrors(testFilePath);
// Write `package_config.json`, recreate analysis contexts.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder()..add(name: 'aaa', rootPath: aaaRootPath),
+ writeTestPackageConfig(
+ config: PackageConfigFileBuilder()
+ ..add(name: 'aaa', rootPath: aaaRootPath),
);
await pumpEventQueue();
@@ -857,6 +843,7 @@
}
Future<void> test_fileSystem_changeFile_dotPackagesFile() async {
+ deleteTestPackageConfigJsonFile();
var aaaLibPath = '/packages/aaa/lib';
var a_path = '$aaaLibPath/a.dart';
@@ -898,12 +885,6 @@
newFile('$testPackageLibPath/a.dart', content: '');
- // Make sure that it is a package.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder(),
- );
-
// This file has an error.
newFile(path, content: '0: 1');
@@ -935,12 +916,6 @@
class A {}
''');
- // Write the empty file, without `package:aaa`.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder(),
- );
-
newFile(testFilePath, content: '''
import 'package:aaa/a.dart';
void f(A a) {}
@@ -949,13 +924,14 @@
await setRoots(included: [workspaceRootPath], excluded: []);
await server.onAnalysisComplete;
+ // The default `package_config.json` is without `package:aaa`.
// We cannot resolve `package:aaa/a.dart`
assertHasErrors(testFilePath);
// Write `package_config.json`, recreate analysis contexts.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder()..add(name: 'aaa', rootPath: aaaRootPath),
+ writeTestPackageConfig(
+ config: PackageConfigFileBuilder()
+ ..add(name: 'aaa', rootPath: aaaRootPath),
);
await pumpEventQueue();
@@ -1090,6 +1066,7 @@
}
Future<void> test_fileSystem_deleteFile_dotPackagesFile() async {
+ deleteTestPackageConfigJsonFile();
var aaaLibPath = '/packages/aaa/lib';
var a_path = '$aaaLibPath/a.dart';
@@ -1130,12 +1107,6 @@
newFile('$testPackageLibPath/a.dart', content: '');
- // Make sure that it is a package.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder(),
- );
-
// This file has an error.
newFile(path, content: '0: 1');
@@ -1161,9 +1132,9 @@
''');
// Write the empty file, without `package:aaa`.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder()..add(name: 'aaa', rootPath: aaaRootPath),
+ writeTestPackageConfig(
+ config: PackageConfigFileBuilder()
+ ..add(name: 'aaa', rootPath: aaaRootPath),
);
newFile(testFilePath, content: '''
@@ -1193,6 +1164,7 @@
}
Future<void> test_setRoots_dotPackagesFile() async {
+ deleteTestPackageConfigJsonFile();
var aaaLibPath = '/packages/aaa/lib';
var a_path = '$aaaLibPath/a.dart';
@@ -1373,13 +1345,7 @@
Future<void> test_setRoots_notDartFile_fixDataYaml() async {
var path = '$testPackageLibPath/fix_data.yaml';
- // Make sure that it is a package.
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder(),
- );
-
- // So, `lib/fix_data.yaml` will be analyzed.
+ // `lib/fix_data.yaml` will be analyzed.
newFile(path, content: '0: 1');
await setRoots(included: [workspaceRootPath], excluded: []);
@@ -1395,9 +1361,9 @@
class A {}
''');
- writePackageConfig(
- '$testPackageRootPath/.dart_tool/package_config.json',
- PackageConfigFileBuilder()..add(name: 'aaa', rootPath: aaaRootPath),
+ writeTestPackageConfig(
+ config: PackageConfigFileBuilder()
+ ..add(name: 'aaa', rootPath: aaaRootPath),
);
newFile(testFilePath, content: '''
@@ -1454,8 +1420,7 @@
InstrumentationService.NULL_SERVICE);
handler = AnalysisDomainHandler(server);
// listen for notifications
- var notificationStream = serverChannel.notificationController.stream;
- notificationStream.listen((Notification notification) {
+ serverChannel.notifications.listen((Notification notification) {
if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
var decoded = AnalysisErrorsParams.fromNotification(notification);
filesErrors[decoded.file] = decoded.errors;
@@ -1763,7 +1728,7 @@
}
}
-class _AnalysisDomainTest extends AbstractAnalysisTest {
+class _AnalysisDomainTest extends PubPackageAnalysisServerTest {
final Map<String, List<AnalysisError>> filesErrors = {};
/// The files for which `analysis.flushResults` was received.
@@ -1801,10 +1766,6 @@
}
}
- void writePackageConfig(String path, PackageConfigFileBuilder config) {
- newFile(path, content: config.toContent(toUriStr: toUriStr));
- }
-
void _assertAnalyzedFiles({
required List<String> hasErrors,
List<String> noErrors = const [],
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 82c6e44..37bf033 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -14,6 +14,7 @@
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
@@ -39,6 +40,52 @@
});
}
+/// TODO(scheglov) this is duplicate
+class AnalysisOptionsFileConfig {
+ final List<String> experiments;
+ final bool implicitCasts;
+ final bool implicitDynamic;
+ final List<String> lints;
+ final bool strictCasts;
+ final bool strictInference;
+ final bool strictRawTypes;
+
+ AnalysisOptionsFileConfig({
+ this.experiments = const [],
+ this.implicitCasts = true,
+ this.implicitDynamic = true,
+ this.lints = const [],
+ this.strictCasts = false,
+ this.strictInference = false,
+ this.strictRawTypes = false,
+ });
+
+ String toContent() {
+ var buffer = StringBuffer();
+
+ buffer.writeln('analyzer:');
+ buffer.writeln(' enable-experiment:');
+ for (var experiment in experiments) {
+ buffer.writeln(' - $experiment');
+ }
+ buffer.writeln(' language:');
+ buffer.writeln(' strict-casts: $strictCasts');
+ buffer.writeln(' strict-inference: $strictInference');
+ buffer.writeln(' strict-raw-types: $strictRawTypes');
+ buffer.writeln(' strong-mode:');
+ buffer.writeln(' implicit-casts: $implicitCasts');
+ buffer.writeln(' implicit-dynamic: $implicitDynamic');
+
+ buffer.writeln('linter:');
+ buffer.writeln(' rules:');
+ for (var lint in lints) {
+ buffer.writeln(' - $lint');
+ }
+
+ return buffer.toString();
+ }
+}
+
@reflectiveTest
class CompletionDomainHandlerGetSuggestionDetails2Test
extends PubPackageAnalysisServerTest {
@@ -149,7 +196,7 @@
testFilePathPlatform, 0, 'Random', '[foo]:bar')
.toRequest('0');
- var response = await _handleRequest(request);
+ var response = await handleRequest(request);
expect(response.error?.code, RequestErrorCode.INVALID_PARAMETER);
// TODO(scheglov) Check that says "libraryUri".
}
@@ -161,7 +208,7 @@
CompletionGetSuggestionDetails2Params('foo', 0, 'Random', 'dart:math')
.toRequest('0');
- var response = await _handleRequest(request);
+ var response = await handleRequest(request);
expect(response.error?.code, RequestErrorCode.INVALID_FILE_PATH_FORMAT);
}
@@ -1162,10 +1209,14 @@
check(response).suggestions.matches([
(suggestion) => suggestion
..completion.isEqualTo('foo01')
- ..isGetter,
+ ..isGetter
+ ..libraryUri.isNull
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('foo02')
- ..isGetter,
+ ..isGetter
+ ..libraryUri.isNull
+ ..isNotImported.isNull,
]);
}
@@ -1609,6 +1660,29 @@
]);
}
+ Future<void> test_prefixed_importPrefix_class() async {
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'dart:math' as math;
+
+void f() {
+ math.Rand^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ check(response).suggestions.withElementClass.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('Random')
+ ..libraryUri.isEqualTo('dart:math')
+ ..isNotImported.isNull,
+ ]);
+ }
+
Future<void> test_unprefixed_filters() async {
await _configureWithWorkspaceRoot();
@@ -1664,10 +1738,14 @@
check(response).suggestions.withElementClass.matches([
(suggestion) => suggestion
..completion.isEqualTo('A01')
- ..isClass,
+ ..isClass
+ ..libraryUri.isEqualTo('package:test/a.dart')
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('A02')
- ..isClass,
+ ..isClass
+ ..libraryUri.isEqualTo('package:test/b.dart')
+ ..isNotImported.isNull,
]);
}
@@ -1698,10 +1776,14 @@
check(response).suggestions.matches([
(suggestion) => suggestion
..completion.isEqualTo('foo01')
- ..isTopLevelVariable,
+ ..isTopLevelVariable
+ ..libraryUri.isEqualTo('package:test/a.dart')
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('foo02')
- ..isTopLevelVariable,
+ ..isTopLevelVariable
+ ..libraryUri.isEqualTo('package:test/b.dart')
+ ..isNotImported.isNull,
]);
}
@@ -1724,7 +1806,8 @@
check(response).suggestions.withElementClass.matches([
(suggestion) => suggestion
..completion.isEqualTo('math.Random')
- ..libraryUriToImport.isNull,
+ ..libraryUri.isEqualTo('dart:math')
+ ..isNotImported.isNull,
]);
}
@@ -1918,7 +2001,7 @@
0,
1 << 10,
).toRequest(id);
- var futureResponse = _handleRequest(request);
+ var futureResponse = handleRequest(request);
return RequestWithFutureResponse(offset, request, futureResponse);
}
}
@@ -2058,8 +2141,8 @@
Future<void> test_ArgumentList_imported_function_named_param_label3() async {
addTestFile('void f() { int.parse("16", ^: 16);}');
await getSuggestions();
- assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix: ');
- assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError: ');
+ assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix');
+ assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError');
expect(suggestions, hasLength(2));
}
@@ -2846,6 +2929,12 @@
return server.handlers.whereType<CompletionDomainHandler>().single;
}
+ List<String> get experiments => [
+ EnableString.enhanced_enums,
+ EnableString.named_arguments_anywhere,
+ EnableString.super_parameters,
+ ];
+
String get testFileContent => getFile(testFilePath).readAsStringSync();
String get testFilePath => '$testPackageLibPath/test.dart';
@@ -2862,6 +2951,20 @@
String get workspaceRootPath => '/home';
+ void deleteTestPackageAnalysisOptionsFile() {
+ deleteAnalysisOptionsYamlFile(testPackageRootPath);
+ }
+
+ void deleteTestPackageConfigJsonFile() {
+ deletePackageConfigJsonFile(testPackageRootPath);
+ }
+
+ Future<Response> handleRequest(Request request) async {
+ return await serverChannel.sendRequest(request);
+ }
+
+ void processNotification(Notification notification) {}
+
Future<void> setRoots({
required List<String> included,
required List<String> excluded,
@@ -2877,6 +2980,7 @@
);
}
+ @mustCallSuper
void setUp() {
serverChannel = MockServerChannel();
@@ -2888,6 +2992,14 @@
writeTestPackageConfig();
+ writeTestPackageAnalysisOptionsFile(
+ AnalysisOptionsFileConfig(
+ experiments: experiments,
+ ),
+ );
+
+ serverChannel.notifications.listen(processNotification);
+
server = AnalysisServer(
serverChannel,
resourceProvider,
@@ -2907,6 +3019,13 @@
);
}
+ void writeTestPackageAnalysisOptionsFile(AnalysisOptionsFileConfig config) {
+ newAnalysisOptionsYamlFile(
+ testPackageRootPath,
+ content: config.toContent(),
+ );
+ }
+
void writeTestPackageConfig({
PackageConfigFileBuilder? config,
String? languageVersion,
@@ -2935,13 +3054,9 @@
await server.onAnalysisComplete;
}
- Future<Response> _handleRequest(Request request) async {
- return await serverChannel.sendRequest(request);
- }
-
/// Validates that the given [request] is handled successfully.
Future<Response> _handleSuccessfulRequest(Request request) async {
- var response = await _handleRequest(request);
+ var response = await handleRequest(request);
expect(response, isResponseSuccess(request.id));
return response;
}
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index 4ae4511..74507b0 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/domain_server.dart';
import 'package:analysis_server/src/edit/edit_domain.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
@@ -27,15 +28,6 @@
});
}
-/// Wrapper around the test package's `fail` function.
-///
-/// Unlike the test package's `fail` function, this function is not annotated
-/// with @alwaysThrows, so we can call it at the top of a test method without
-/// causing the rest of the method to be flagged as dead code.
-void _fail(String message) {
- fail(message);
-}
-
@reflectiveTest
class ConvertGetterMethodToMethodTest extends _AbstractGetRefactoring_Test {
Future<void> test_function() {
@@ -1325,9 +1317,7 @@
class MoveFileTest extends _AbstractGetRefactoring_Test {
late MoveFileOptions options;
- @failingTest
- Future<void> test_OK() {
- _fail('The move file refactoring is not supported under the new driver');
+ Future<void> test_file_OK() {
newFile('/project/bin/lib.dart');
addTestFile('''
import 'dart:math';
@@ -1335,16 +1325,59 @@
''');
_setOptions('/project/test.dart');
return assertSuccessfulRefactoring(() {
- return _sendMoveRequest();
+ return _sendMoveRequest(testFile);
}, '''
import 'dart:math';
import 'bin/lib.dart';
''');
}
- Future<Response> _sendMoveRequest() {
+ Future<void> test_folder_cancel() {
+ newFile('/project/bin/original_folder/file.dart');
+ addTestFile('''
+import 'dart:math';
+import 'original_folder/file.dart';
+''');
+ _setOptions('/project/bin/new_folder');
+ return assertEmptySuccessfulRefactoring(() async {
+ return _sendAndCancelMoveRequest(
+ convertPath('/project/bin/original_folder'));
+ });
+ }
+
+ Future<void> test_folder_OK() {
+ newFile('/project/bin/original_folder/file.dart');
+ addTestFile('''
+import 'dart:math';
+import 'original_folder/file.dart';
+''');
+ _setOptions('/project/bin/new_folder');
+ return assertSuccessfulRefactoring(() async {
+ return _sendMoveRequest(convertPath('/project/bin/original_folder'));
+ }, '''
+import 'dart:math';
+import 'new_folder/file.dart';
+''');
+ }
+
+ Future<Response> _cancelMoveRequest() {
+ // 0 is the id from _sendMoveRequest
+ // 1 is another aribtrary id for the cancel request
+ var request = ServerCancelRequestParams('0').toRequest('1');
+ return serverChannel.sendRequest(request);
+ }
+
+ Future<Response> _sendAndCancelMoveRequest(String item) async {
+ final responses = await Future.wait([
+ _sendMoveRequest(item),
+ _cancelMoveRequest(),
+ ]);
+ return responses.first;
+ }
+
+ Future<Response> _sendMoveRequest(String item) {
var request = EditGetRefactoringParams(
- RefactoringKind.MOVE_FILE, testFile, 0, 0, false,
+ RefactoringKind.MOVE_FILE, item, 0, 0, false,
options: options)
.toRequest('0');
return serverChannel.sendRequest(request);
@@ -1860,6 +1893,58 @@
);
}
+ Future<void> test_enum_constructor_add_toSynthetic() {
+ addTestFile('''
+enum E {
+ v1, v2.new()
+}
+''');
+ return assertSuccessfulRefactoring(
+ () {
+ return sendRenameRequest('new()', 'newName');
+ },
+ '''
+enum E {
+ v1.newName(), v2.newName();
+
+ const E.newName();
+}
+''',
+ feedbackValidator: (feedback) {
+ var renameFeedback = feedback as RenameFeedback;
+ expect(renameFeedback.offset, 17);
+ expect(renameFeedback.length, 4);
+ },
+ );
+ }
+
+ Future<void> test_enum_constructor_change() {
+ addTestFile('''
+enum E {
+ v1.test(), v2.test();
+
+ const E.test();
+}
+''');
+ return assertSuccessfulRefactoring(
+ () {
+ return sendRenameRequest('test();', 'newName');
+ },
+ '''
+enum E {
+ v1.newName(), v2.newName();
+
+ const E.newName();
+}
+''',
+ feedbackValidator: (feedback) {
+ var renameFeedback = feedback as RenameFeedback;
+ expect(renameFeedback.offset, 24);
+ expect(renameFeedback.length, 5);
+ },
+ );
+ }
+
Future<void> test_feedback() {
addTestFile('''
class Test {}
@@ -2201,6 +2286,26 @@
class _AbstractGetRefactoring_Test extends AbstractAnalysisTest {
bool shouldWaitForFullAnalysis = true;
+ Future assertEmptySuccessfulRefactoring(
+ Future<Response> Function() requestSender,
+ {void Function(RefactoringFeedback?)? feedbackValidator}) async {
+ var result = await getRefactoringResult(requestSender);
+ assertResultProblemsOK(result);
+ if (feedbackValidator != null) {
+ feedbackValidator(result.feedback);
+ }
+ assertNoTestRefactoringResult(result);
+ }
+
+ /// Asserts that the given [EditGetRefactoringResult] does not have a change
+ /// for [testFile].
+ void assertNoTestRefactoringResult(EditGetRefactoringResult result) {
+ var change = result.change!;
+ if (change.edits.any((edit) => edit.file == testFile)) {
+ fail('Found a SourceFileEdit for $testFile in $change');
+ }
+ }
+
/// Asserts that [problems] has a single ERROR problem.
void assertResultProblemsError(List<RefactoringProblem> problems,
[String? message]) {
@@ -2292,7 +2397,9 @@
Future<void> setUp() async {
super.setUp();
await createProject();
- handler = EditDomainHandler(server);
- server.handlers = [handler];
+ server.handlers = [
+ EditDomainHandler(server),
+ ServerDomainHandler(server),
+ ];
}
}
diff --git a/pkg/analysis_server/test/integration/edit/import_elements_test.dart b/pkg/analysis_server/test/integration/edit/import_elements_test.dart
index 43ecb92..40e370d 100644
--- a/pkg/analysis_server/test/integration/edit/import_elements_test.dart
+++ b/pkg/analysis_server/test/integration/edit/import_elements_test.dart
@@ -4,8 +4,8 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
-import 'package:cli_util/cli_util.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index c12b23d..bf671b2 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -500,9 +500,10 @@
/// the normal package: URI resolution mechanism.
///
/// If a package root is a file, then the analyzer will behave as though
- /// that file is a ".packages" file in the source directory. The effect is
- /// the same as specifying the file as a "--packages" parameter to the Dart
- /// VM when executing any Dart file inside the source directory.
+ /// that file is a ".dart_tool/package_config.json" file in the source
+ /// directory. The effect is the same as specifying the file as a
+ /// "--packages" parameter to the Dart VM when executing any Dart file
+ /// inside the source directory.
///
/// Files in any directories that are not overridden by this mapping have
/// their package: URI's resolved using the normal pubspec.yaml mechanism.
@@ -993,6 +994,11 @@
/// suggestions after filtering is greater than the maxResults, then
/// isIncomplete is set to true.
///
+ /// completionCaseMatchingMode: CompletionCaseMatchingMode (optional)
+ ///
+ /// The mode of code completion being invoked. If no value is provided,
+ /// MATCH_FIRST_CHAR will be assumed.
+ ///
/// Returns
///
/// replacementOffset: int
@@ -1029,10 +1035,12 @@
/// requested maxResults.
Future<CompletionGetSuggestions2Result> sendCompletionGetSuggestions2(
String file, int offset, int maxResults,
- {CompletionMode? completionMode,
+ {CompletionCaseMatchingMode? completionCaseMatchingMode,
+ CompletionMode? completionMode,
int? invocationCount,
int? timeout}) async {
var params = CompletionGetSuggestions2Params(file, offset, maxResults,
+ completionCaseMatchingMode: completionCaseMatchingMode,
completionMode: completionMode,
invocationCount: invocationCount,
timeout: timeout)
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 1e7cde4..ddf2b9b 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -230,6 +230,16 @@
final Matcher isClosingLabel = LazyMatcher(() => MatchesJsonObject(
'ClosingLabel', {'offset': isInt, 'length': isInt, 'label': isString}));
+/// CompletionCaseMatchingMode
+///
+/// enum {
+/// FIRST_CHAR
+/// ALL_CHARS
+/// NONE
+/// }
+final Matcher isCompletionCaseMatchingMode = MatchesEnum(
+ 'CompletionCaseMatchingMode', ['FIRST_CHAR', 'ALL_CHARS', 'NONE']);
+
/// CompletionId
///
/// String
@@ -305,6 +315,7 @@
'hasNamedParameters': isBool,
'parameterName': isString,
'parameterType': isString,
+ 'libraryUri': isString,
'isNotImported': isBool
}));
@@ -384,8 +395,7 @@
'parameters': isString,
'returnType': isString,
'typeParameters': isString,
- 'aliasedType': isString,
- 'libraryUri': isString
+ 'aliasedType': isString
}));
/// ElementDeclaration
@@ -2148,17 +2158,19 @@
/// "file": FilePath
/// "offset": int
/// "maxResults": int
+/// "completionCaseMatchingMode": optional CompletionCaseMatchingMode
/// }
-final Matcher isCompletionGetSuggestions2Params = LazyMatcher(() =>
- MatchesJsonObject('completion.getSuggestions2 params', {
- 'file': isFilePath,
- 'offset': isInt,
- 'maxResults': isInt
- }, optionalFields: {
- 'completionMode': isCompletionMode,
- 'invocationCount': isInt,
- 'timeout': isInt
- }));
+final Matcher isCompletionGetSuggestions2Params =
+ LazyMatcher(() => MatchesJsonObject('completion.getSuggestions2 params', {
+ 'file': isFilePath,
+ 'offset': isInt,
+ 'maxResults': isInt
+ }, optionalFields: {
+ 'completionCaseMatchingMode': isCompletionCaseMatchingMode,
+ 'completionMode': isCompletionMode,
+ 'invocationCount': isInt,
+ 'timeout': isInt
+ }));
/// completion.getSuggestions2 result
///
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 925b13b..9a541dc 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -341,7 +341,7 @@
}
Future<void> test_outsideRoot() async {
- final otherFilePath = '/home/otherProject/foo.dart';
+ final otherFilePath = convertPath('/home/otherProject/foo.dart');
final otherFileUri = Uri.file(otherFilePath);
newFile(otherFilePath, content: 'bad code to create error');
await initialize(
diff --git a/pkg/analysis_server/test/lsp/completion.dart b/pkg/analysis_server/test/lsp/completion.dart
index 6d70a26..ea8d26b 100644
--- a/pkg/analysis_server/test/lsp/completion.dart
+++ b/pkg/analysis_server/test/lsp/completion.dart
@@ -101,10 +101,10 @@
return null;
}
- /// Replaces the LSP snippet placeholder '${0:}' with '^' for easier verifying
+ /// Replaces the LSP snippet placeholder '$0' with '^' for easier verifying
/// of the cursor position in completions.
String withCaret(String contents, InsertTextFormat? format) =>
format == InsertTextFormat.Snippet
- ? contents.replaceFirst(r'${0:}', '^')
+ ? contents.replaceFirst(r'$0', '^')
: contents;
}
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 01f2b09..1b9520b 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -5,6 +5,7 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analysis_server/src/services/snippets/dart/flutter_snippet_producers.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart';
@@ -19,6 +20,9 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(CompletionTest);
+ defineReflectiveTests(DartSnippetCompletionTest);
+ defineReflectiveTests(FlutterSnippetCompletionTest);
+ defineReflectiveTests(FlutterSnippetCompletionWithNullSafetyTest);
defineReflectiveTests(CompletionTestWithNullSafetyTest);
});
}
@@ -354,7 +358,7 @@
// Ensure the snippet comes through in the expected format with the expected
// placeholders.
expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
- expect(item.insertText, equals('setState(() {\n \${0:}\n \\});'));
+ expect(item.insertText, equals('setState(() {\n \$0\n });'));
final textEdit = toTextEdit(item.textEdit!);
expect(textEdit.newText, equals(item.insertText));
expect(textEdit.range, equals(rangeFromMarkers(content)));
@@ -396,9 +400,9 @@
await openFile(mainFileUri, withoutMarkers(content));
final res = await getCompletion(mainFileUri, positionFromMarker(content));
final item = res.singleWhere((c) => c.label == 'myFunction(…)');
- // With no required params, there should still be parens and a tabstop inside.
+ // With no required params, there should still be parens/tab stop inside.
expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
- expect(item.insertText, equals(r'myFunction(${0:})'));
+ expect(item.insertText, equals(r'myFunction($0)'));
final textEdit = toTextEdit(item.textEdit!);
expect(textEdit.newText, equals(item.insertText));
expect(textEdit.range, equals(rangeFromMarkers(content)));
@@ -1143,9 +1147,9 @@
// Ensure the snippet comes through in the expected format with the expected
// placeholder.
expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
- expect(item.insertText, equals(r'one: ${0:},'));
+ expect(item.insertText, equals(r'one: $0,'));
final textEdit = toTextEdit(item.textEdit!);
- expect(textEdit.newText, equals(r'one: ${0:},'));
+ expect(textEdit.newText, equals(r'one: $0,'));
expect(
textEdit.range,
equals(Range(
@@ -2363,3 +2367,411 @@
expect(completion.detail, '(int? a, [int b = 1]) → String?');
}
}
+
+@reflectiveTest
+class DartSnippetCompletionTest extends SnippetCompletionTest {
+ Future<void> test_snippets_disabled() async {
+ final content = '^';
+
+ // Advertise support (this is done by the editor), but with the user
+ // preference disabled.
+ await provideConfig(
+ () => initialize(
+ textDocumentCapabilities: withCompletionItemSnippetSupport(
+ emptyTextDocumentClientCapabilities),
+ workspaceCapabilities:
+ withConfigurationSupport(emptyWorkspaceClientCapabilities),
+ ),
+ {'enableSnippets': true},
+ );
+
+ await expectNoSnippet(
+ content,
+ FlutterStatelessWidgetSnippetProducer.prefix,
+ );
+ }
+
+ Future<void>
+ test_snippets_flutterStateless_notAvailable_notFlutterProject() async {
+ final content = '''
+class A {}
+
+stle^
+
+class B {}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ await expectNoSnippet(
+ content,
+ FlutterStatelessWidgetSnippetProducer.prefix,
+ );
+ }
+
+ Future<void> test_snippets_notSupported() async {
+ final content = '^';
+
+ // If we don't send support for Snippet CompletionItem kinds, we don't
+ // expect any snippets at all.
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+ expect(res.any((c) => c.kind == CompletionItemKind.Snippet), isFalse);
+ }
+}
+
+@reflectiveTest
+class FlutterSnippetCompletionTest extends SnippetCompletionTest {
+ /// Nullability suffix expected in this test class.
+ ///
+ /// Used to allow all tests to be run in both modes without having to
+ /// duplicate all tests ([FlutterSnippetCompletionWithNullSafetyTest]
+ /// overrides this).
+ String get questionSuffix => '';
+
+ @override
+ void setUp() {
+ super.setUp();
+ writePackageConfig(
+ projectFolderPath,
+ flutter: true,
+ );
+ }
+
+ Future<void> test_snippets_flutterStateful() async {
+ final content = '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+stful^
+
+class B {}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix: FlutterStatefulWidgetSnippetProducer.prefix,
+ label: FlutterStatefulWidgetSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+class \${1:MyWidget} extends StatefulWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ State<\${1:MyWidget}> createState() => _\${1:MyWidget}State();
+}
+
+class _\${1:MyWidget}State extends State<\${1:MyWidget}> {
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+
+class B {}
+''');
+ }
+
+ Future<void> test_snippets_flutterStatefulWithAnimationController() async {
+ final content = '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+stanim^
+
+class B {}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix:
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer.prefix,
+ label: FlutterStatefulWidgetWithAnimationControllerSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+class \${1:MyWidget} extends StatefulWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ State<\${1:MyWidget}> createState() => _\${1:MyWidget}State();
+}
+
+class _\${1:MyWidget}State extends State<\${1:MyWidget}>
+ with SingleTickerProviderStateMixin {
+ late AnimationController _controller;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = AnimationController(vsync: this);
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _controller.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+
+class B {}
+''');
+ }
+
+ Future<void> test_snippets_flutterStateless() async {
+ final content = '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+stle^
+
+class B {}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix: FlutterStatelessWidgetSnippetProducer.prefix,
+ label: FlutterStatelessWidgetSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/widgets.dart';
+
+class A {}
+
+class \${1:MyWidget} extends StatelessWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+
+class B {}
+''');
+ }
+
+ Future<void> test_snippets_flutterStateless_addsImports() async {
+ final content = '''
+class A {}
+
+stle^
+
+class B {}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix: FlutterStatelessWidgetSnippetProducer.prefix,
+ label: FlutterStatelessWidgetSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+
+class A {}
+
+class \${1:MyWidget} extends StatelessWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+
+class B {}
+''');
+ }
+
+ Future<void> test_snippets_flutterStateless_addsImports_onlyPrefix() async {
+ final content = '''
+stless^
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix: FlutterStatelessWidgetSnippetProducer.prefix,
+ label: FlutterStatelessWidgetSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+
+class \${1:MyWidget} extends StatelessWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+''');
+ }
+
+ Future<void> test_snippets_flutterStateless_addsImports_zeroOffset() async {
+ final content = '''
+^
+'''; // Deliberate trailing newline to ensure imports aren't inserted at "end".
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final updated = await expectAndApplySnippet(
+ content,
+ prefix: FlutterStatelessWidgetSnippetProducer.prefix,
+ label: FlutterStatelessWidgetSnippetProducer.label,
+ );
+
+ expect(updated, '''
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+
+class \${1:MyWidget} extends StatelessWidget {
+ const \${1:MyWidget}({Key$questionSuffix key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ \$0
+ }
+}
+''');
+ }
+
+ Future<void> test_snippets_flutterStateless_notAvailable_notTopLevel() async {
+ final content = '''
+class A {
+
+ stle^
+
+}
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ await expectNoSnippet(
+ content,
+ FlutterStatelessWidgetSnippetProducer.prefix,
+ );
+ }
+
+ Future<void> test_snippets_flutterStateless_outsideAnalysisRoot() async {
+ final content = '''
+stle^
+''';
+
+ await initializeWithSnippetSupportAndPreviewFlag();
+ final otherFileUri = Uri.file(convertPath('/other/file.dart'));
+ await openFile(otherFileUri, withoutMarkers(content));
+ final res = await getCompletion(otherFileUri, positionFromMarker(content));
+ final snippetItems = res.where((c) => c.kind == CompletionItemKind.Snippet);
+ expect(snippetItems, hasLength(0));
+ }
+}
+
+@reflectiveTest
+class FlutterSnippetCompletionWithNullSafetyTest
+ extends FlutterSnippetCompletionTest {
+ @override
+ String get questionSuffix => '?';
+
+ @override
+ String get testPackageLanguageVersion => latestLanguageVersion;
+}
+
+abstract class SnippetCompletionTest extends AbstractLspAnalysisServerTest
+ with CompletionTestMixin {
+ /// Expect that there is a snippet for [prefix] at [position] with the label
+ /// [label] and return the results of applying it to [content].
+ Future<String> expectAndApplySnippet(
+ String content, {
+ required String prefix,
+ required String label,
+ }) async {
+ final snippet = await expectSnippet(
+ content,
+ prefix: prefix,
+ label: label,
+ );
+
+ // Also apply the edit and check that it went in the right place with the
+ // correct formatting. Edit groups will just appear in the raw textmate
+ // snippet syntax here, as we don't do any special handling of them (and
+ // assume what's coded here is correct, and that the client will correctly
+ // interpret them).
+ final updated = applyTextEdits(
+ withoutMarkers(content),
+ [toTextEdit(snippet.textEdit!)]
+ .followedBy(snippet.additionalTextEdits!)
+ .toList(),
+ );
+ return updated;
+ }
+
+ /// Expect that there is no snippet for [prefix] at the position of `^` within
+ /// [content].
+ Future<void> expectNoSnippet(
+ String content,
+ String prefix,
+ ) async {
+ await openFile(mainFileUri, withoutMarkers(content));
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+ final hasSnippet = res.any((c) => c.filterText == prefix);
+ expect(hasSnippet, isFalse);
+ }
+
+ /// Expect that there is a snippet for [prefix] with the label [label] at
+ /// [position] in [content].
+ Future<CompletionItem> expectSnippet(
+ String content, {
+ required String prefix,
+ required String label,
+ }) async {
+ await openFile(mainFileUri, withoutMarkers(content));
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+ final item = res.singleWhere(
+ (c) => c.filterText == prefix && c.label == label,
+ );
+ expect(item.insertTextFormat, InsertTextFormat.Snippet);
+ expect(item.insertText, isNull);
+ expect(item.textEdit, isNotNull);
+ return item;
+ }
+
+ Future<void> initializeWithSnippetSupport() => initialize(
+ textDocumentCapabilities: withCompletionItemSnippetSupport(
+ emptyTextDocumentClientCapabilities),
+ );
+
+ Future<void> initializeWithSnippetSupportAndPreviewFlag() => provideConfig(
+ () => initialize(
+ textDocumentCapabilities: withCompletionItemSnippetSupport(
+ emptyTextDocumentClientCapabilities),
+ workspaceCapabilities:
+ withConfigurationSupport(emptyWorkspaceClientCapabilities),
+ ),
+ {'previewEnableSnippets': true},
+ );
+}
diff --git a/pkg/analysis_server/test/lsp/document_symbols_test.dart b/pkg/analysis_server/test/lsp/document_symbols_test.dart
index a37882a..48ddc1b 100644
--- a/pkg/analysis_server/test/lsp/document_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/document_symbols_test.dart
@@ -206,8 +206,10 @@
newFile(mainFilePath, content: content);
await initialize(allowEmptyRootUri: true);
- await expectLater(getDocumentSymbols(mainFileUri.toString()),
- throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)));
+ await expectLater(
+ getDocumentSymbols(mainFileUri.toString()),
+ throwsA(isResponseError(ServerErrorCodes.FileNotAnalyzed,
+ message: 'File is not being analyzed')));
}
Future<void> test_nonDartFile() async {
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart
index 7ffff8a..f3d24e8 100644
--- a/pkg/analysis_server/test/lsp/format_test.dart
+++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -640,7 +640,8 @@
await expectLater(
formatDocument(
Uri.file(join(projectFolderPath, 'missing.dart')).toString()),
- throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'File does not exist')),
);
}
@@ -649,8 +650,9 @@
await expectLater(
// Add some invalid path characters to the end of a valid file:// URI.
- formatDocument(mainFileUri.toString() + '***.dart'),
- throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)),
+ formatDocument(mainFileUri.toString() + r'***###\\\///:::.dart'),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'File URI did not contain a valid file path')),
);
}
@@ -659,7 +661,8 @@
await expectLater(
formatDocument('a:/a.dart'),
- throwsA(isResponseError(ServerErrorCodes.InvalidFilePath)),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'URI was not a valid file:// URI')),
);
}
diff --git a/pkg/analysis_server/test/lsp/mapping_test.dart b/pkg/analysis_server/test/lsp/mapping_test.dart
index b55938b..196b547 100644
--- a/pkg/analysis_server/test/lsp/mapping_test.dart
+++ b/pkg/analysis_server/test/lsp/mapping_test.dart
@@ -117,38 +117,6 @@
expect(results2, equals(expectedOrder));
}
- Future<void> test_tabStopsInSnippets_contains() async {
- var result = lsp.buildSnippetStringWithTabStops('a, b, c', [3, 1]);
- expect(result, equals(r'a, ${0:b}, c'));
- }
-
- Future<void> test_tabStopsInSnippets_empty() async {
- var result = lsp.buildSnippetStringWithTabStops('a, b', []);
- expect(result, equals(r'a, b'));
- }
-
- Future<void> test_tabStopsInSnippets_endsWith() async {
- var result = lsp.buildSnippetStringWithTabStops('a, b', [3, 1]);
- expect(result, equals(r'a, ${0:b}'));
- }
-
- Future<void> test_tabStopsInSnippets_escape() async {
- var result = lsp.buildSnippetStringWithTabStops(
- r'te$tstri}ng, te$tstri}ng, te$tstri}ng', [13, 11]);
- expect(result, equals(r'te\$tstri\}ng, ${0:te\$tstri\}ng}, te\$tstri\}ng'));
- }
-
- Future<void> test_tabStopsInSnippets_multiple() async {
- var result =
- lsp.buildSnippetStringWithTabStops('a, b, c', [0, 1, 3, 1, 6, 1]);
- expect(result, equals(r'${1:a}, ${2:b}, ${3:c}'));
- }
-
- Future<void> test_tabStopsInSnippets_startsWith() async {
- var result = lsp.buildSnippetStringWithTabStops('a, b', [0, 1]);
- expect(result, equals(r'${0:a}, b'));
- }
-
/// Verifies that [kind] maps to [expectedKind] when the client supports
/// [supportedKinds].
void verifyCompletionItemKind({
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index 22608c0..48d0109 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -2,11 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:io';
+
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../tool/lsp_spec/matchers.dart';
import 'server_abstract.dart';
void main() {
@@ -44,6 +48,67 @@
await server.exited.timeout(const Duration(seconds: 10));
}
+ Future<void> test_path_doesNotExist() async {
+ final missingFileUri = Uri.file(join(projectFolderPath, 'missing.dart'));
+ await initialize();
+ await expectLater(
+ getHover(missingFileUri, startOfDocPos),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'File does not exist')),
+ );
+ }
+
+ Future<void> test_path_invalidFormat() async {
+ await initialize();
+ await expectLater(
+ // Add some invalid path characters to the end of a valid file:// URI.
+ formatDocument(mainFileUri.toString() + r'***###\\\///:::.dart'),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'File URI did not contain a valid file path')),
+ );
+ }
+
+ Future<void> test_path_missingDriveLetterWindows() async {
+ // This test is only valid on Windows, as a URI in the format:
+ // file:///foo/bar.dart
+ // is valid for non-Windows platforms, but not valid on Windows as it does
+ // not have a drive letter.
+ if (!Platform.isWindows) {
+ return;
+ }
+ final missingDriveLetterFileUri = Uri.file('/foo/bar.dart');
+ await initialize();
+ await expectLater(
+ getHover(missingDriveLetterFileUri, startOfDocPos),
+ // The Uri.file() above translates to a non-file:// URI of just 'a/b.dart'
+ // so will get the not-file-scheme error message.
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'URI was not an absolute file path (missing drive letter)')),
+ );
+ }
+
+ Future<void> test_path_notFileScheme() async {
+ final relativeFileUri = Uri(scheme: 'foo', path: '/a/b.dart');
+ await initialize();
+ await expectLater(
+ getHover(relativeFileUri, startOfDocPos),
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'URI was not a valid file:// URI')),
+ );
+ }
+
+ Future<void> test_path_relative() async {
+ final relativeFileUri = Uri.file('a/b.dart');
+ await initialize();
+ await expectLater(
+ getHover(relativeFileUri, startOfDocPos),
+ // The Uri.file() above translates to a non-file:// URI of just 'a/b.dart'
+ // so will get the not-file-scheme error message.
+ throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
+ message: 'URI was not a valid file:// URI')),
+ );
+ }
+
Future<void> test_shutdown_initialized() async {
await initialize();
final response = await sendShutdown();
diff --git a/pkg/analysis_server/test/lsp/snippets_test.dart b/pkg/analysis_server/test/lsp/snippets_test.dart
new file mode 100644
index 0000000..a126c9b
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/snippets_test.dart
@@ -0,0 +1,318 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/lsp/snippets.dart' as lsp;
+import 'package:analysis_server/src/lsp/snippets.dart';
+import 'package:analysis_server/src/protocol_server.dart' as server;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SnippetsTest);
+ defineReflectiveTests(SnippetBuilderTest);
+ });
+}
+
+@reflectiveTest
+class SnippetBuilderTest {
+ Future<void> test_appendChoice() async {
+ final builder = SnippetBuilder()
+ ..appendChoice({r'a'})
+ ..appendChoice([r'a', r'b', r'a'])
+ ..appendChoice([], placeholderNumber: 6)
+ ..appendChoice([r'aaa', r'bbb'], placeholderNumber: 12)
+ ..appendChoice([r'aaa', r'bbb $ bbb | bbb } bbb']);
+
+ expect(
+ builder.value,
+ r'${1:a}'
+ r'${2|a,b|}'
+ r'$6'
+ r'${12|aaa,bbb|}'
+ r'${13|aaa,bbb \$ bbb \| bbb \} bbb|}',
+ );
+ }
+
+ Future<void> test_appendPlaceholder() async {
+ final builder = SnippetBuilder()
+ ..appendPlaceholder(r'placeholder $ 1')
+ ..appendPlaceholder(r'')
+ ..appendPlaceholder(r'placeholder } 3', placeholderNumber: 6);
+
+ expect(
+ builder.value,
+ r'${1:placeholder \$ 1}'
+ r'$2'
+ r'${6:placeholder \} 3}',
+ );
+ }
+
+ Future<void> test_appendTabStop() async {
+ final builder = SnippetBuilder()
+ ..appendTabStop()
+ ..appendTabStop(placeholderNumber: 10)
+ ..appendTabStop();
+
+ expect(
+ builder.value,
+ r'$1'
+ r'$10'
+ r'$11',
+ );
+ }
+
+ Future<void> test_appendText() async {
+ final builder = SnippetBuilder()
+ ..appendText(r'text 1')
+ ..appendText(r'text ${that needs} escaping $0')
+ ..appendText(r'text 2');
+
+ expect(
+ builder.value,
+ r'text 1'
+ r'text \${that needs} escaping \$0'
+ r'text 2',
+ );
+ }
+
+ Future<void> test_extension_appendPlaceholders() async {
+ final code = r'''
+012345678
+012345678
+012345678
+012345678
+012345678
+''';
+
+ final placeholders = [
+ lsp.SnippetPlaceholder(2, 2),
+ lsp.SnippetPlaceholder(12, 2, isFinal: true),
+ lsp.SnippetPlaceholder(22, 2, suggestions: ['aaa', 'bbb']),
+ lsp.SnippetPlaceholder(32, 2, linkedGroupId: 123),
+ lsp.SnippetPlaceholder(42, 2, linkedGroupId: 123),
+ ];
+
+ final builder = SnippetBuilder()..appendPlaceholders(code, placeholders);
+
+ expect(builder.value, r'''
+01${1:23}45678
+01${0:23}45678
+01${2|23,aaa,bbb|}45678
+01${3:23}45678
+01${3:23}45678
+''');
+ }
+
+ Future<void> test_mixed() async {
+ final builder = SnippetBuilder()
+ ..appendText('text1')
+ ..appendPlaceholder('placeholder')
+ ..appendText('text2')
+ ..appendChoice(['aaa', 'bbb'])
+ ..appendText('text3')
+ ..appendTabStop()
+ ..appendText('text4');
+
+ expect(
+ builder.value,
+ r'text1'
+ r'${1:placeholder}'
+ r'text2'
+ r'${2|aaa,bbb|}'
+ r'text3'
+ r'$3'
+ r'text4',
+ );
+ }
+}
+
+@reflectiveTest
+class SnippetsTest {
+ /// Paths aren't used for anything except filtering edit groups positions
+ /// so the specific values are not important.
+ final mainPath = '/home/test.dart';
+ final otherPath = '/home/other.dart';
+
+ Future<void> test_editGroups_choices() async {
+ var result = lsp.buildSnippetStringForEditGroups(
+ r'''
+var a = 1;
+''',
+ filePath: mainPath,
+ editOffset: 0,
+ editGroups: [
+ server.LinkedEditGroup(
+ [_pos(4)],
+ 1,
+ [
+ _suggestion('aaa'),
+ _suggestion(r'bbb${},|'), // test for escaping
+ _suggestion('ccc'),
+ ],
+ ),
+ ],
+ );
+ expect(result, equals(r'''
+var ${1|a,aaa,bbb\${\}\,\|,ccc|} = 1;
+'''));
+ }
+
+ Future<void> test_editGroups_emptyGroup() async {
+ var result = lsp.buildSnippetStringForEditGroups(
+ r'''
+class {
+ ();
+}
+''',
+ filePath: mainPath,
+ editOffset: 0,
+ editGroups: [
+ server.LinkedEditGroup(
+ [
+ _pos(6),
+ _pos(11),
+ ],
+ 0,
+ [],
+ ),
+ ],
+ );
+ expect(result, equals(r'''
+class $1 {
+ $1();
+}
+'''));
+ }
+
+ Future<void> test_editGroups_positionsInOtherFiles() async {
+ var result = lsp.buildSnippetStringForEditGroups(
+ r'''
+class A {
+ A();
+}
+''',
+ filePath: mainPath,
+ editOffset: 0,
+ editGroups: [
+ server.LinkedEditGroup(
+ [
+ _pos(6),
+ _pos(10, otherPath), // Should not be included.
+ _pos(12),
+ ],
+ 1,
+ [],
+ ),
+ ],
+ );
+ expect(result, equals(r'''
+class ${1:A} {
+ ${1:A}();
+}
+'''));
+ }
+
+ Future<void> test_editGroups_simpleGroup() async {
+ var result = lsp.buildSnippetStringForEditGroups(
+ r'''
+class A {
+ A();
+}
+''',
+ filePath: mainPath,
+ editOffset: 0,
+ editGroups: [
+ server.LinkedEditGroup(
+ [
+ _pos(6),
+ _pos(12),
+ ],
+ 1,
+ [],
+ ),
+ ],
+ );
+ expect(result, equals(r'''
+class ${1:A} {
+ ${1:A}();
+}
+'''));
+ }
+
+ Future<void> test_editGroups_withOffset() async {
+ var result = lsp.buildSnippetStringForEditGroups(
+ r'''
+class A {
+ A();
+}
+''',
+ filePath: mainPath,
+ // This means the edit will be inserted at offset 100, so all linked edit
+ // offsets will be 100 more than in the supplied text.
+ editOffset: 100,
+ editGroups: [
+ server.LinkedEditGroup(
+ [
+ _pos(100 + 6),
+ _pos(100 + 12),
+ ],
+ 1,
+ [],
+ ),
+ ],
+ );
+ expect(result, equals(r'''
+class ${1:A} {
+ ${1:A}();
+}
+'''));
+ }
+
+ Future<void> test_tabStops_contains() async {
+ var result = lsp.buildSnippetStringWithTabStops('a, b, c', [3, 1]);
+ expect(result, equals(r'a, ${0:b}, c'));
+ }
+
+ Future<void> test_tabStops_empty() async {
+ var result = lsp.buildSnippetStringWithTabStops('a, b', []);
+ expect(result, equals(r'a, b'));
+ }
+
+ Future<void> test_tabStops_endsWith() async {
+ var result = lsp.buildSnippetStringWithTabStops('a, b', [3, 1]);
+ expect(result, equals(r'a, ${0:b}'));
+ }
+
+ Future<void> test_tabStops_escape() async {
+ var result = lsp.buildSnippetStringWithTabStops(
+ r'te$tstri}ng, te$tstri}ng, te$tstri}ng', [13, 11]);
+ expect(result, equals(r'te\$tstri}ng, ${0:te\$tstri\}ng}, te\$tstri}ng'));
+ }
+
+ Future<void> test_tabStops_multiple() async {
+ var result =
+ lsp.buildSnippetStringWithTabStops('a, b, c', [0, 1, 3, 1, 6, 1]);
+ expect(result, equals(r'${1:a}, ${2:b}, ${3:c}'));
+ }
+
+ Future<void> test_tabStops_null() async {
+ var result = lsp.buildSnippetStringWithTabStops('a, b', null);
+ expect(result, equals(r'a, b'));
+ }
+
+ Future<void> test_tabStops_startsWith() async {
+ var result = lsp.buildSnippetStringWithTabStops('a, b', [0, 1]);
+ expect(result, equals(r'${0:a}, b'));
+ }
+
+ server.Position _pos(int offset, [String? path]) =>
+ server.Position(path ?? mainPath, offset);
+
+ server.LinkedEditSuggestion _suggestion(String text) =>
+ server.LinkedEditSuggestion(
+ text,
+ server.LinkedEditSuggestionKind.TYPE, // We don't use type.
+ );
+}
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index bd22081..5e5c5f5 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -41,6 +41,7 @@
import 'semantic_tokens_test.dart' as semantic_tokens;
import 'server_test.dart' as server;
import 'signature_help_test.dart' as signature_help;
+import 'snippets_test.dart' as snippets;
import 'super_test.dart' as get_super;
import 'will_rename_files_test.dart' as will_rename_files;
import 'workspace_symbols_test.dart' as workspace_symbols;
@@ -85,6 +86,7 @@
semantic_tokens.main();
server.main();
signature_help.main();
+ snippets.main();
will_rename_files.main();
workspace_symbols.main();
}, name: 'lsp');
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/animation.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/animation.dart
new file mode 100644
index 0000000..8dd7d64
--- /dev/null
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/animation.dart
@@ -0,0 +1,5 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export 'src/animation/animation_controller.dart';
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/animation/animation_controller.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/animation/animation_controller.dart
new file mode 100644
index 0000000..4c4e4e6
--- /dev/null
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/animation/animation_controller.dart
@@ -0,0 +1,5 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+class AnimationController {}
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/cupertino/colors.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/cupertino/colors.dart
index 62356d5..92f600e 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/cupertino/colors.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/cupertino/colors.dart
@@ -41,7 +41,6 @@
darkElevatedColor,
highContrastElevatedColor,
darkHighContrastElevatedColor,
- null,
);
const CupertinoDynamicColor.withBrightnessAndContrast({
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/foundation/diagnostics.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/foundation/diagnostics.dart
index c2bae69..f8fa737 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/foundation/diagnostics.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/foundation/diagnostics.dart
@@ -7,7 +7,9 @@
mixin Diagnosticable {}
-abstract class DiagnosticableTree with Diagnosticable {}
+abstract class DiagnosticableTree with Diagnosticable {
+ const DiagnosticableTree();
+}
class DiagnosticPropertiesBuilder {
void add(DiagnosticsNode property) {}
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/basic.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/basic.dart
index 303d1e8..020e8fd 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/basic.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/basic.dart
@@ -6,6 +6,7 @@
import 'framework.dart';
+export 'package:flutter/animation.dart';
export 'package:flutter/painting.dart';
export 'package:flutter/rendering.dart';
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/ticker_provider.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/ticker_provider.dart
new file mode 100644
index 0000000..f0419ff
--- /dev/null
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/ticker_provider.dart
@@ -0,0 +1,7 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/src/widgets/framework.dart';
+
+mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> {}
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/widgets.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/widgets.dart
index 76d58efd..b8eedd8 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/widgets.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/widgets.dart
@@ -8,4 +8,5 @@
export 'src/widgets/framework.dart';
export 'src/widgets/gesture_detector.dart';
export 'src/widgets/icon.dart';
+export 'src/widgets/ticker_provider.dart';
export 'src/widgets/text.dart';
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index 708a951..130ca0d 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -281,24 +281,6 @@
expect(element.flags, Element.FLAG_CONST | Element.FLAG_STATIC);
}
{
- var engineElement = findElement.field('index', of: 'E2');
- // create notification Element
- var element = convertElement(engineElement, withNullability: true);
- expect(element.kind, ElementKind.FIELD);
- expect(element.name, 'index');
- {
- var location = element.location!;
- expect(location.file, testFile);
- expect(location.offset, -1);
- expect(location.length, 'index'.length);
- expect(location.startLine, 1);
- expect(location.startColumn, 0);
- }
- expect(element.parameters, isNull);
- expect(element.returnType, 'int');
- expect(element.flags, Element.FLAG_FINAL);
- }
- {
var engineElement = findElement.field('values', of: 'E2');
// create notification Element
var element = convertElement(engineElement, withNullability: true);
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 83f3e8f..02e6971 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -256,6 +256,8 @@
// use SearchResultKind inside the analysis server?
EnumTester<MatchKind, SearchResultKind>()
.run(newSearchResultKind_fromEngine, exceptions: {
+ MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS:
+ SearchResultKind.INVOCATION,
MatchKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF: SearchResultKind.REFERENCE,
});
}
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index 326a8eb..2902a26 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -40,7 +40,7 @@
}
}
- Future<void> test_constructor_named() async {
+ Future<void> test_class_constructor_named() async {
addTestFile('''
/// [new A.named] 1
class A {
@@ -69,7 +69,7 @@
assertHasResult(SearchResultKind.REFERENCE, '.named; // 6', 6);
}
- Future<void> test_constructor_named_potential() async {
+ Future<void> test_class_constructor_named_potential() async {
// Constructors in other classes shouldn't be considered potential matches.
// Unresolved method calls should also not be considered potential matches,
// because constructor call sites are statically bound to their targets.
@@ -92,7 +92,7 @@
assertHasResult(SearchResultKind.INVOCATION, '.named(1)', 6);
}
- Future<void> test_constructor_unnamed() async {
+ Future<void> test_class_constructor_unnamed() async {
addTestFile('''
/// [new A] 1
/// [A.new] 2
@@ -123,7 +123,7 @@
assertHasResult(SearchResultKind.REFERENCE, '.new; // 7', 4);
}
- Future<void> test_constructor_unnamed_potential() async {
+ Future<void> test_class_constructor_unnamed_potential() async {
// Constructors in other classes shouldn't be considered potential matches,
// even if they are also unnamed (since constructor call sites are
// statically bound to their targets).
@@ -151,26 +151,7 @@
assertHasResult(SearchResultKind.INVOCATION, '(1)', 0);
}
- Future<void> test_extension() async {
- addTestFile('''
-extension E on int {
- static void foo() {}
- void bar() {}
-}
-
-void f() {
- E.foo();
- E(0).bar();
-}
-''');
- await findElementReferences('E on int', false);
- expect(searchElement!.kind, ElementKind.EXTENSION);
- expect(results, hasLength(2));
- assertHasResult(SearchResultKind.REFERENCE, 'E.foo();');
- assertHasResult(SearchResultKind.REFERENCE, 'E(0)');
- }
-
- Future<void> test_field_explicit() async {
+ Future<void> test_class_field_explicit() async {
addTestFile('''
class A {
var fff; // declaration
@@ -207,7 +188,7 @@
assertHasResult(SearchResultKind.READ, 'fff(); // in f()');
}
- Future<void> test_field_implicit() async {
+ Future<void> test_class_field_implicit() async {
addTestFile('''
class A {
var get fff => null;
@@ -241,7 +222,7 @@
}
}
- Future<void> test_field_inFormalParameter() async {
+ Future<void> test_class_field_inFormalParameter() async {
addTestFile('''
class A {
var fff; // declaration
@@ -260,7 +241,205 @@
assertHasResult(SearchResultKind.READ, 'fff); // in m()');
}
- Future<void> test_field_ofExtension_explicit_static() async {
+ Future<void> test_class_method() async {
+ addTestFile('''
+class A {
+ mmm(p) {}
+ m() {
+ mmm(1);
+ print(mmm); // in m()
+ }
+}
+void f(A a) {
+ a.mmm(10);
+ print(a.mmm); // in f()
+}
+''');
+ await findElementReferences('mmm(p) {}', false);
+ expect(searchElement!.kind, ElementKind.METHOD);
+ expect(results, hasLength(4));
+ assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);');
+ assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()');
+ assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
+ assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in f()');
+ }
+
+ Future<void> test_class_method_propagatedType() async {
+ addTestFile('''
+class A {
+ mmm(p) {}
+}
+void f() {
+ var a = new A();
+ a.mmm(10);
+ print(a.mmm);
+}
+''');
+ await findElementReferences('mmm(p) {}', false);
+ expect(searchElement!.kind, ElementKind.METHOD);
+ expect(results, hasLength(2));
+ assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
+ assertHasResult(SearchResultKind.REFERENCE, 'mmm);');
+ }
+
+ Future<void> test_enum_constructor_named() async {
+ addTestFile('''
+/// [new E.named] 1
+enum E {
+ v.named(); // 2
+ const E.named(); // 3
+ const E.other() : this.named(); // 4
+}
+''');
+ await findElementReferences('named(); // 3', false);
+ expect(searchElement!.kind, ElementKind.CONSTRUCTOR);
+ expect(results, hasLength(3));
+ assertHasResult(SearchResultKind.REFERENCE, '.named] 1', 6);
+ assertHasResult(SearchResultKind.INVOCATION, '.named(); // 2', 6);
+ assertHasResult(SearchResultKind.INVOCATION, '.named(); // 4', 6);
+ }
+
+ Future<void> test_enum_constructor_unnamed() async {
+ addTestFile('''
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+ const E(); // 5
+ const E.other() : this(); // 6
+}
+''');
+ await findElementReferences('E(); // 5', false);
+ expect(searchElement!.kind, ElementKind.CONSTRUCTOR);
+ expect(results, hasLength(5));
+ assertHasResult(SearchResultKind.REFERENCE, '] 1', 0);
+ assertHasResult(SearchResultKind.INVOCATION, ', // 2', 0);
+ assertHasResult(SearchResultKind.INVOCATION, '(), // 3', 0);
+ assertHasResult(SearchResultKind.INVOCATION, '.new(); // 4', 4);
+ assertHasResult(SearchResultKind.INVOCATION, '(); // 6', 0);
+ }
+
+ Future<void> test_enum_field_explicit() async {
+ addTestFile('''
+enum E {
+ v;
+ var fff; // 01
+ E(this.fff); // 02
+ E.named() : fff = 0; // 03
+ void foo() {
+ fff = 0; // 04
+ fff += 0; // 05
+ fff; // 06
+ fff(); // 07
+ }
+}
+
+void f(E e) {
+ e.fff = 0; // 08
+ e.fff += 0; // 09
+ e.fff; // 10
+ e.fff(); // 11
+}
+''');
+ await findElementReferences('fff; // 01', false);
+ expect(searchElement!.kind, ElementKind.FIELD);
+ expect(results, hasLength(10));
+ assertHasResult(SearchResultKind.WRITE, 'fff); // 02');
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 03');
+ // foo()
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 04');
+ assertHasResult(SearchResultKind.WRITE, 'fff += 0; // 05');
+ assertHasResult(SearchResultKind.READ, 'fff; // 06');
+ assertHasResult(SearchResultKind.READ, 'fff(); // 07');
+ // f()
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 08');
+ assertHasResult(SearchResultKind.WRITE, 'fff += 0; // 09');
+ assertHasResult(SearchResultKind.READ, 'fff; // 10');
+ assertHasResult(SearchResultKind.READ, 'fff(); // 11');
+ }
+
+ Future<void> test_enum_field_implicit() async {
+ addTestFile('''
+enum E {
+ v;
+ int get fff => 0;
+ void set fff(_) {}
+ void foo() {
+ fff; // 1
+ fff = 0; // 2
+ }
+}
+
+void f(E e) {
+ e.fff; // 3
+ e.fff = 0; // 4
+}
+''');
+ {
+ await findElementReferences('fff =>', false);
+ expect(searchElement!.kind, ElementKind.FIELD);
+ expect(results, hasLength(4));
+ assertHasResult(SearchResultKind.READ, 'fff; // 1');
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 2');
+ assertHasResult(SearchResultKind.READ, 'fff; // 3');
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 4');
+ }
+ {
+ await findElementReferences('fff(_) {}', false);
+ expect(results, hasLength(4));
+ assertHasResult(SearchResultKind.READ, 'fff; // 1');
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 2');
+ assertHasResult(SearchResultKind.READ, 'fff; // 3');
+ assertHasResult(SearchResultKind.WRITE, 'fff = 0; // 4');
+ }
+ }
+
+ Future<void> test_enum_method() async {
+ addTestFile('''
+enum E {
+ v;
+ void foo() {}
+ void bar() {
+ foo(); // 1
+ this.foo(); // 2
+ }
+}
+
+void f(E e) {
+ e.foo(); // 3
+ e.foo; // 4
+}
+''');
+ await findElementReferences('foo() {}', false);
+ expect(searchElement!.kind, ElementKind.METHOD);
+ expect(results, hasLength(4));
+ assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 1');
+ assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 2');
+ assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 3');
+ assertHasResult(SearchResultKind.REFERENCE, 'foo; // 4');
+ }
+
+ Future<void> test_extension() async {
+ addTestFile('''
+extension E on int {
+ static void foo() {}
+ void bar() {}
+}
+
+void f() {
+ E.foo();
+ E(0).bar();
+}
+''');
+ await findElementReferences('E on int', false);
+ expect(searchElement!.kind, ElementKind.EXTENSION);
+ expect(results, hasLength(2));
+ assertHasResult(SearchResultKind.REFERENCE, 'E.foo();');
+ assertHasResult(SearchResultKind.REFERENCE, 'E(0)');
+ }
+
+ Future<void> test_extension_field_explicit_static() async {
addTestFile('''
extension E on int {
static var fff; // declaration
@@ -295,7 +474,7 @@
assertHasResult(SearchResultKind.READ, 'fff(); // in f()');
}
- Future<void> test_field_ofExtension_implicit_instance() async {
+ Future<void> test_extension_field_implicit_instance() async {
addTestFile('''
extension E on int {
var get fff => null;
@@ -329,7 +508,7 @@
}
}
- Future<void> test_field_ofExtension_implicit_static() async {
+ Future<void> test_extension_field_implicit_static() async {
addTestFile('''
extension E on int {
static var get fff => null;
@@ -363,6 +542,28 @@
}
}
+ Future<void> test_extension_method() async {
+ addTestFile('''
+extension E on int {
+ void foo() {}
+}
+
+void f() {
+ E(0).foo(); // 1
+ E(0).foo; // 2
+ 0.foo(); // 3
+ 0.foo; // 4
+}
+''');
+ await findElementReferences('foo() {}', false);
+ expect(searchElement!.kind, ElementKind.METHOD);
+ expect(results, hasLength(4));
+ assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 1');
+ assertHasResult(SearchResultKind.REFERENCE, 'foo; // 2');
+ assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 3');
+ assertHasResult(SearchResultKind.REFERENCE, 'foo; // 4');
+ }
+
Future<void> test_function() async {
addTestFile('''
fff(p) {}
@@ -511,69 +712,6 @@
assertHasResult(SearchResultKind.READ, 'vvv();');
}
- Future<void> test_method() async {
- addTestFile('''
-class A {
- mmm(p) {}
- m() {
- mmm(1);
- print(mmm); // in m()
- }
-}
-void f(A a) {
- a.mmm(10);
- print(a.mmm); // in f()
-}
-''');
- await findElementReferences('mmm(p) {}', false);
- expect(searchElement!.kind, ElementKind.METHOD);
- expect(results, hasLength(4));
- assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);');
- assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()');
- assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
- assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in f()');
- }
-
- Future<void> test_method_ofExtension() async {
- addTestFile('''
-extension E on int {
- void foo() {}
-}
-
-void f() {
- E(0).foo(); // 1
- E(0).foo; // 2
- 0.foo(); // 3
- 0.foo; // 4
-}
-''');
- await findElementReferences('foo() {}', false);
- expect(searchElement!.kind, ElementKind.METHOD);
- expect(results, hasLength(4));
- assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 1');
- assertHasResult(SearchResultKind.REFERENCE, 'foo; // 2');
- assertHasResult(SearchResultKind.INVOCATION, 'foo(); // 3');
- assertHasResult(SearchResultKind.REFERENCE, 'foo; // 4');
- }
-
- Future<void> test_method_propagatedType() async {
- addTestFile('''
-class A {
- mmm(p) {}
-}
-void f() {
- var a = new A();
- a.mmm(10);
- print(a.mmm);
-}
-''');
- await findElementReferences('mmm(p) {}', false);
- expect(searchElement!.kind, ElementKind.METHOD);
- expect(results, hasLength(2));
- assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
- assertHasResult(SearchResultKind.REFERENCE, 'mmm);');
- }
-
Future<void> test_mixin() async {
addTestFile('''
mixin A {}
@@ -834,6 +972,23 @@
assertHasResult(SearchResultKind.REFERENCE, 'ppp.Stream');
}
+ Future<void> test_topFunction_parameter_optionalNamed_anywhere() async {
+ addTestFile('''
+void foo(int a, int b, {int? test}) {
+ test;
+}
+
+void g() {
+ foo(0, test: 2, 1);
+}
+''');
+ await findElementReferences('test})', false);
+ expect(searchElement!.kind, ElementKind.PARAMETER);
+ expect(results, hasLength(2));
+ assertHasResult(SearchResultKind.READ, 'test;');
+ assertHasResult(SearchResultKind.REFERENCE, 'test: 2');
+ }
+
Future<void> test_topLevelVariable_explicit() async {
addTestFile('''
var vvv = 1;
diff --git a/pkg/analysis_server/test/search/member_declarations_test.dart b/pkg/analysis_server/test/search/member_declarations_test.dart
index d838f8e..29e27c9 100644
--- a/pkg/analysis_server/test/search/member_declarations_test.dart
+++ b/pkg/analysis_server/test/search/member_declarations_test.dart
@@ -45,6 +45,185 @@
return null;
}
+ Future<void> test_class_methodField() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ int foo;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.FIELD, 'B');
+ }
+
+ Future<void> test_class_methodGetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ get foo => null;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ }
+
+ Future<void> test_class_methodGetterSetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ get foo => null;
+ set foo(x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(3));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_class_methodMethod() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ foo() {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.METHOD, 'B');
+ }
+
+ Future<void> test_class_methodSetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ set foo(x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_enum_methodField() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int foo;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.FIELD, 'B');
+ }
+
+ Future<void> test_enum_methodGetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int get foo => 0;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ }
+
+ Future<void> test_enum_methodGetterSetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int get foo => 0;
+ set foo(int x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(3));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_enum_methodMethod() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ void foo() {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.METHOD, 'B');
+ }
+
+ Future<void> test_enums_methodSetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ set foo(int x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
Future<void> test_localVariable() async {
addTestFile('''
class A {
@@ -69,86 +248,4 @@
await findMemberDeclarations('foo');
expect(results, isEmpty);
}
-
- Future<void> test_methodField() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- int foo;
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.FIELD, 'B');
- }
-
- Future<void> test_methodGetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- get foo => null;
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.GETTER, 'B');
- }
-
- Future<void> test_methodGetterSetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- get foo => null;
- set foo(x) {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(3));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.GETTER, 'B');
- assertHasDeclaration(ElementKind.SETTER, 'B');
- }
-
- Future<void> test_methodMethod() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- foo() {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.METHOD, 'B');
- }
-
- Future<void> test_methodSetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- set foo(x) {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.SETTER, 'B');
- }
}
diff --git a/pkg/analysis_server/test/search/member_references_test.dart b/pkg/analysis_server/test/search/member_references_test.dart
index a2c7b18..b5df9ae 100644
--- a/pkg/analysis_server/test/search/member_references_test.dart
+++ b/pkg/analysis_server/test/search/member_references_test.dart
@@ -29,75 +29,179 @@
return waitForSearchResults();
}
- Future<void> test_fields_explicit() async {
+ Future<void> test_class_fields_explicit() async {
addTestFile('''
class A {
var foo;
}
+
class B {
var foo;
}
-mainResolved(A a, B b) {
+
+void whenResolved(A a, B b) {
a.foo = 1;
b.foo = 2;
- print(a.foo); // resolved A
- print(b.foo); // resolved B
+ a.foo; // resolved A
+ b.foo; // resolved B
}
-mainUnresolved(a, b) {
+
+void whenUnresolved(a, b) {
a.foo = 10;
b.foo = 20;
- print(a.foo); // unresolved A
- print(b.foo); // unresolved B
+ a.foo; // unresolved A
+ b.foo; // unresolved B
}
''');
await findMemberReferences('foo');
assertNoResult(SearchResultKind.WRITE, 'foo = 1;');
assertNoResult(SearchResultKind.WRITE, 'foo = 2;');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved A');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved B');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
}
- Future<void> test_fields_implicit() async {
+ Future<void> test_class_fields_implicit() async {
addTestFile('''
class A {
- get foo => null;
+ int get foo => 0;
}
+
class B {
- get foo => null;
+ int get foo => 0;
}
-mainResolved(A a, B b) {
- print(a.foo); // resolved A
- print(b.foo); // resolved B
+
+void whenResolved(A a, B b) {
+ a.foo; // resolved A
+ b.foo; // resolved B
}
-mainUnresolved(a, b) {
- print(a.foo); // unresolved A
- print(b.foo); // unresolved B
+
+void whenUnresolved(a, b) {
+ a.foo; // unresolved A
+ b.foo; // unresolved B
}
''');
await findMemberReferences('foo');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved A');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved B');
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
}
- Future<void> test_methods() async {
+ Future<void> test_class_methods() async {
addTestFile('''
class A {
- foo() {}
+ void foo() {}
}
+
class B {
- foo() {}
+ void foo() {}
}
-mainResolved(A a, B b) {
+
+void whenResolved(A a, B b) {
a.foo(1);
b.foo(2);
}
-mainUnresolved(a, b) {
+
+void whenUnresolved(a, b) {
+ a.foo(10);
+ b.foo(20);
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.INVOCATION, 'foo(1)');
+ assertNoResult(SearchResultKind.INVOCATION, 'foo(2)');
+ assertHasRef(SearchResultKind.INVOCATION, 'foo(10)', true);
+ assertHasRef(SearchResultKind.INVOCATION, 'foo(20)', true);
+ }
+
+ Future<void> test_enum_fields_explicit() async {
+ addTestFile('''
+enum A {
+ v;
+ final foo = 0;
+}
+
+enum B {
+ v;
+ final foo = 0;
+}
+
+void whenResolved(A a, B b) {
+ a.foo = 1;
+ b.foo = 2;
+ a.foo; // resolved A
+ b.foo; // resolved B
+}
+
+whenUnresolved(a, b) {
+ a.foo = 10;
+ b.foo = 20;
+ a.foo; // unresolved A
+ b.foo; // unresolved B
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.WRITE, 'foo = 1;');
+ assertNoResult(SearchResultKind.WRITE, 'foo = 2;');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
+ assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
+ }
+
+ Future<void> test_enum_fields_implicit() async {
+ addTestFile('''
+enum A {
+ v;
+ int get foo => 0;
+}
+
+enum B {
+ v;
+ int get foo => 0;
+}
+
+void whenResolved(A a, B b) {
+ a.foo; // resolved A
+ b.foo; // resolved B
+}
+
+void whenUnresolved(a, b) {
+ a.foo; // unresolved A
+ b.foo; // unresolved B
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
+ }
+
+ Future<void> test_enum_methods() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+}
+
+enum B {
+ v;
+ void foo() {}
+}
+
+void whenResolved(A a, B b) {
+ a.foo(1);
+ b.foo(2);
+}
+
+void whenUnresolved(a, b) {
a.foo(10);
b.foo(20);
}
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 2242204..977f966 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -53,6 +53,31 @@
return null;
}
+ Future<void> test_enum_startEndPattern() async {
+ addTestFile('''
+enum A {
+ v
+}
+
+enum A2 {
+ v
+}
+
+enum B {
+ v
+}
+
+enum D {
+ v
+}
+''');
+ await findTopLevelDeclarations('^[A-C]\$');
+ assertHasDeclaration(ElementKind.ENUM, 'A');
+ assertHasDeclaration(ElementKind.ENUM, 'B');
+ assertNoDeclaration(ElementKind.ENUM, 'A2');
+ assertNoDeclaration(ElementKind.ENUM, 'D');
+ }
+
Future<void> test_extensionDeclaration() async {
addTestFile('''
extension MyExtension on int {}
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 28f9cba..c0d0616 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -64,8 +64,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -77,8 +76,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -118,8 +116,7 @@
'kind': 'CLASS',
'name': 'AAA',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -131,8 +128,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -143,8 +139,7 @@
'kind': 'CLASS',
'name': 'BBB',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -156,8 +151,7 @@
'kind': 'CLASS',
'name': 'CCC',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -210,8 +204,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -223,8 +216,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -235,8 +227,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -248,8 +239,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -275,8 +265,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -288,8 +277,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -301,8 +289,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -313,8 +300,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -340,8 +326,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -353,8 +338,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -366,8 +350,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 3,
'interfaces': [],
@@ -379,8 +362,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -389,255 +371,7 @@
]);
}
- Future<void> test_class_implementsTypes() async {
- addTestFile('''
-class MA {}
-class MB {}
-class B extends A {
-}
-class T implements MA, MB {
-}
-''');
- var items = await _getTypeHierarchy('T implements');
- expect(_toJson(items), [
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'T',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [2, 3],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'Object',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'MA',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'MB',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- }
- ]);
- }
-
- Future<void> test_class_order() async {
- addTestFile('''
-class A {}
-class D extends A {}
-class C extends A {}
-class B extends A {}
-class G extends B {}
-class F extends B {}
-class E extends A {}
-''');
- var items = await _getTypeHierarchy('A {}');
- expect(_toJson(items), [
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'A',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': [2, 3, 4, 5]
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'Object',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'B',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 0,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': [6, 7]
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'C',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 0,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'D',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 0,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'E',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 0,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'F',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 4,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'G',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 4,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- }
- ]);
- }
-
- Future<void> test_class_withTypes() async {
- addTestFile('''
-class MA {}
-class MB {}
-class B extends A {
-}
-class T extends Object with MA, MB {
-}
-''');
- var items = await _getTypeHierarchy('T extends Object');
- expect(_toJson(items), [
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'T',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [2, 3],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'Object',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'MA',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- },
- {
- 'classElement': {
- 'kind': 'CLASS',
- 'name': 'MB',
- 'location': anything,
- 'flags': 0,
- 'libraryUri': anything
- },
- 'superclass': 1,
- 'interfaces': [],
- 'mixins': [],
- 'subclasses': []
- }
- ]);
- }
-
- Future<void> test_fromField_toMixinGetter() async {
+ Future<void> test_class_fromField_toMixinGetter() async {
addTestFile('''
abstract class A {
var test = 1;
@@ -656,7 +390,7 @@
expect(memberB.location!.offset, findOffset('test => 2;'));
}
- Future<void> test_fromField_toMixinSetter() async {
+ Future<void> test_class_fromField_toMixinSetter() async {
addTestFile('''
abstract class A {
var test = 1;
@@ -675,7 +409,68 @@
expect(memberB.location!.offset, findOffset('test(m) {}'));
}
- Future<void> test_member_fromField_toField() async {
+ Future<void> test_class_implementsTypes() async {
+ addTestFile('''
+class MA {}
+class MB {}
+class B extends A {
+}
+class T implements MA, MB {
+}
+''');
+ var items = await _getTypeHierarchy('T implements');
+ expect(_toJson(items), [
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'T',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [2, 3],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Object',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'MA',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'MB',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ }
+ ]);
+ }
+
+ Future<void> test_class_member_fromField_toField() async {
addTestFile('''
class A {
var test = 1;
@@ -698,7 +493,7 @@
checkItems(await _getTypeHierarchy('test = 2;'));
}
- Future<void> test_member_fromField_toGetter() async {
+ Future<void> test_class_member_fromField_toGetter() async {
addTestFile('''
class A {
get test => 1;
@@ -721,7 +516,7 @@
checkItems(await _getTypeHierarchy('test = 2;'));
}
- Future<void> test_member_fromField_toSetter() async {
+ Future<void> test_class_member_fromField_toSetter() async {
addTestFile('''
class A {
set test(a) {}
@@ -744,7 +539,7 @@
checkItems(await _getTypeHierarchy('test = 2;'));
}
- Future<void> test_member_fromFinalField_toGetter() async {
+ Future<void> test_class_member_fromFinalField_toGetter() async {
addTestFile('''
class A {
get test => 1;
@@ -767,7 +562,7 @@
checkItems(await _getTypeHierarchy('test = 2;'));
}
- Future<void> test_member_fromFinalField_toSetter() async {
+ Future<void> test_class_member_fromFinalField_toSetter() async {
addTestFile('''
class A {
set test(x) {}
@@ -783,7 +578,7 @@
expect(itemB.memberElement!.location!.offset, findOffset('test = 2;'));
}
- Future<void> test_member_getter() async {
+ Future<void> test_class_member_getter() async {
addTestFile('''
class A {
get test => null; // in A
@@ -815,7 +610,7 @@
findOffset('test => null; // in D'));
}
- Future<void> test_member_method() async {
+ Future<void> test_class_member_method() async {
addTestFile('''
class A {
test() {} // in A
@@ -847,7 +642,7 @@
itemD.memberElement!.location!.offset, findOffset('test() {} // in D'));
}
- Future<void> test_member_method_private_differentLib() async {
+ Future<void> test_class_member_method_private_differentLib() async {
newFile(join(testFolder, 'lib.dart'), content: r'''
import 'test.dart';
class A {
@@ -881,7 +676,7 @@
expect(itemD.memberElement, isNotNull);
}
- Future<void> test_member_method_private_sameLib() async {
+ Future<void> test_class_member_method_private_sameLib() async {
addTestFile('''
class A {
_m() {} // in A
@@ -908,7 +703,7 @@
itemC.memberElement!.location!.offset, findOffset('_m() {} // in C'));
}
- Future<void> test_member_ofMixin2_method() async {
+ Future<void> test_class_member_ofMixin2_method() async {
addTestFile('''
class M1 {
void test() {} // in M1
@@ -956,7 +751,7 @@
}
}
- Future<void> test_member_ofMixin_getter() async {
+ Future<void> test_class_member_ofMixin_getter() async {
addTestFile('''
abstract class Base {
get test; // in Base
@@ -982,7 +777,7 @@
member2.location!.offset, findOffset('test => null; // in Derived2'));
}
- Future<void> test_member_ofMixin_method() async {
+ Future<void> test_class_member_ofMixin_method() async {
addTestFile('''
abstract class Base {
void test(); // in Base
@@ -1007,7 +802,7 @@
expect(member2.location!.offset, findOffset('test() {} // in Derived2'));
}
- Future<void> test_member_ofMixin_setter() async {
+ Future<void> test_class_member_ofMixin_setter() async {
addTestFile('''
abstract class Base {
set test(x); // in Base
@@ -1032,7 +827,7 @@
expect(member2.location!.offset, findOffset('test(x) {} // in Derived2'));
}
- Future<void> test_member_ofSuperclassConstraint_getter() async {
+ Future<void> test_class_member_ofSuperclassConstraint_getter() async {
addTestFile('''
class A {
get test => 0; // in A
@@ -1051,7 +846,7 @@
_assertMember(inM, 'test => 0; // in M');
}
- Future<void> test_member_ofSuperclassConstraint_method() async {
+ Future<void> test_class_member_ofSuperclassConstraint_method() async {
addTestFile('''
class A {
void test() {} // in A
@@ -1070,7 +865,7 @@
_assertMember(inM, 'test() {} // in M');
}
- Future<void> test_member_ofSuperclassConstraint_setter() async {
+ Future<void> test_class_member_ofSuperclassConstraint_setter() async {
addTestFile('''
class A {
set test(x) {} // in A
@@ -1089,7 +884,7 @@
_assertMember(inM, 'test(x) {} // in M');
}
- Future<void> test_member_operator() async {
+ Future<void> test_class_member_operator() async {
addTestFile('''
class A {
operator ==(x) => null; // in A
@@ -1121,7 +916,7 @@
findOffset('==(x) => null; // in D'));
}
- Future<void> test_member_setter() async {
+ Future<void> test_class_member_setter() async {
addTestFile('''
class A {
set test(x) {} // in A
@@ -1153,7 +948,117 @@
findOffset('test(x) {} // in D'));
}
- Future<void> test_superOnly() async {
+ Future<void> test_class_order() async {
+ addTestFile('''
+class A {}
+class D extends A {}
+class C extends A {}
+class B extends A {}
+class G extends B {}
+class F extends B {}
+class E extends A {}
+''');
+ var items = await _getTypeHierarchy('A {}');
+ expect(_toJson(items), [
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'A',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': [2, 3, 4, 5]
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Object',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'B',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 0,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': [6, 7]
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'C',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 0,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'D',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 0,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'E',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 0,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'F',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 4,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'G',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 4,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ }
+ ]);
+ }
+
+ Future<void> test_class_superOnly() async {
addTestFile('''
class A {}
class B {}
@@ -1167,8 +1072,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [3],
@@ -1180,8 +1084,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -1193,8 +1096,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -1205,8 +1107,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -1216,7 +1117,7 @@
]);
}
- Future<void> test_superOnly_fileDoesNotExist() async {
+ Future<void> test_class_superOnly_fileDoesNotExist() async {
var request = SearchGetTypeHierarchyParams(
convertPath('/does/not/exist.dart'), 0,
superOnly: true)
@@ -1227,6 +1128,337 @@
expect(items, isNull);
}
+ Future<void> test_class_withTypes() async {
+ addTestFile('''
+class MA {}
+class MB {}
+class B extends A {
+}
+class T extends Object with MA, MB {
+}
+''');
+ var items = await _getTypeHierarchy('T extends Object');
+ expect(_toJson(items), [
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'T',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [2, 3],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Object',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'MA',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'MB',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ }
+ ]);
+ }
+
+ Future<void> test_enum_displayName() async {
+ addTestFile('''
+mixin M<T> {}
+
+enum E with M<int> {
+ v;
+}
+''');
+ var items = await _getTypeHierarchy('E with');
+
+ var itemB = items[0];
+ expect(itemB.classElement.name, 'E');
+
+ var itemA = items[itemB.superclass!];
+ expect(itemA.classElement.name, 'Enum');
+ expect(itemA.displayName, isNull);
+
+ expect(itemB.mixins, hasLength(1));
+ var itemM = items[itemB.mixins[0]];
+ expect(itemM.classElement.name, 'M');
+ expect(itemM.displayName, 'M<int>');
+ }
+
+ Future<void> test_enum_implements() async {
+ addTestFile('''
+class A {}
+class B {}
+enum E implements A, B {
+ v;
+}
+''');
+ var items = await _getTypeHierarchy('E implements');
+ expect(_toJson(items), [
+ {
+ 'classElement': {
+ 'kind': 'ENUM',
+ 'name': 'E',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [3, 4],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Enum',
+ 'location': anything,
+ 'flags': 1
+ },
+ 'superclass': 2,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Object',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'A',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 2,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'B',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 2,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ }
+ ]);
+ }
+
+ Future<void> test_enum_member_getter() async {
+ addTestFile('''
+class A {
+ int get test => 0; // in A
+}
+class B extends A {
+ int get test => 0; // in B
+}
+class C extends B {
+}
+enum E implements C {
+ v;
+ int get test => 0; // in D
+}
+''');
+ var items = await _getTypeHierarchy('test => 0; // in B');
+ var itemB = items[0];
+ var itemA = items[itemB.superclass!];
+ var itemC = items[itemB.subclasses[0]];
+ var itemE = items[itemC.subclasses[0]];
+ expect(itemA.classElement.name, 'A');
+ expect(itemB.classElement.name, 'B');
+ expect(itemC.classElement.name, 'C');
+ expect(itemE.classElement.name, 'E');
+ expect(
+ itemA.memberElement!.location!.offset,
+ findOffset('test => 0; // in A'),
+ );
+ expect(
+ itemB.memberElement!.location!.offset,
+ findOffset('test => 0; // in B'),
+ );
+ expect(itemC.memberElement, isNull);
+ expect(
+ itemE.memberElement!.location!.offset,
+ findOffset('test => 0; // in D'),
+ );
+ }
+
+ Future<void> test_enum_member_method() async {
+ addTestFile('''
+class A {
+ void test() {} // in A
+}
+class B extends A {
+ void test() {} // in B
+}
+class C extends B {
+}
+enum E implements C {
+ v;
+ void test() {} // in E
+}
+''');
+ var items = await _getTypeHierarchy('test() {} // in B');
+ var itemB = items[0];
+ var itemA = items[itemB.superclass!];
+ var itemC = items[itemB.subclasses[0]];
+ var itemE = items[itemC.subclasses[0]];
+ expect(itemA.classElement.name, 'A');
+ expect(itemB.classElement.name, 'B');
+ expect(itemC.classElement.name, 'C');
+ expect(itemE.classElement.name, 'E');
+ expect(
+ itemA.memberElement!.location!.offset,
+ findOffset('test() {} // in A'),
+ );
+ expect(
+ itemB.memberElement!.location!.offset,
+ findOffset('test() {} // in B'),
+ );
+ expect(itemC.memberElement, isNull);
+ expect(
+ itemE.memberElement!.location!.offset,
+ findOffset('test() {} // in E'),
+ );
+ }
+
+ Future<void> test_enum_member_setter() async {
+ addTestFile('''
+class A {
+ set test(int x) {} // in A
+}
+class B extends A {
+ set test(int x) {} // in B
+}
+class C extends B {
+}
+enum E implements C {
+ v;
+ set test(int x) {} // in E
+}
+''');
+ var items = await _getTypeHierarchy('test(int x) {} // in B');
+ var itemB = items[0];
+ var itemA = items[itemB.superclass!];
+ var itemC = items[itemB.subclasses[0]];
+ var itemE = items[itemC.subclasses[0]];
+ expect(itemA.classElement.name, 'A');
+ expect(itemB.classElement.name, 'B');
+ expect(itemC.classElement.name, 'C');
+ expect(itemE.classElement.name, 'E');
+ expect(
+ itemA.memberElement!.location!.offset,
+ findOffset('test(int x) {} // in A'),
+ );
+ expect(
+ itemB.memberElement!.location!.offset,
+ findOffset('test(int x) {} // in B'),
+ );
+ expect(itemC.memberElement, isNull);
+ expect(
+ itemE.memberElement!.location!.offset,
+ findOffset('test(int x) {} // in E'),
+ );
+ }
+
+ Future<void> test_enum_with() async {
+ addTestFile('''
+mixin M {}
+enum E with M {
+ v;
+}
+''');
+ var items = await _getTypeHierarchy('E with');
+ expect(_toJson(items), [
+ {
+ 'classElement': {
+ 'kind': 'ENUM',
+ 'name': 'E',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'superclass': 1,
+ 'interfaces': [],
+ 'mixins': [3],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Enum',
+ 'location': anything,
+ 'flags': 1
+ },
+ 'superclass': 2,
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'CLASS',
+ 'name': 'Object',
+ 'location': anything,
+ 'flags': 0
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ },
+ {
+ 'classElement': {
+ 'kind': 'MIXIN',
+ 'name': 'M',
+ 'location': anything,
+ 'flags': 1
+ },
+ 'interfaces': [],
+ 'mixins': [],
+ 'subclasses': []
+ }
+ ]);
+ }
+
void _assertMember(TypeHierarchyItem item, String search) {
expect(item.memberElement!.location!.offset, findOffset(search));
}
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 7bf72fe..142d6f6 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -168,6 +168,27 @@
});
}
+ Future<void> test_flutter_InstanceCreationExpression_3() async {
+ // Ensure a trailing comma is not added when only replacing the name.
+ writeTestPackageConfig(flutter: true);
+
+ addTestSource('''
+import 'package:flutter/material.dart';
+
+build() => new Row(
+ ke^: null,
+ );
+''');
+
+ var response = await computeSuggestions2();
+ _checkNamedArguments(response).containsMatch((suggestion) {
+ suggestion
+ ..completion.isEqualTo('key')
+ ..defaultArgumentListString.isNull
+ ..hasSelection(offset: 3);
+ });
+ }
+
Future<void>
test_flutter_InstanceCreationExpression_children_dynamic() async {
// Ensure we don't generate unneeded <dynamic> param if a future API doesn't
@@ -660,17 +681,15 @@
check: (response) {
_checkNamedArguments(response).matchesInAnyOrder([
(suggestion) => suggestion
- // TODO(scheglov) This does not seem right.
- ..completion.isEqualTo('two: ')
+ ..completion.isEqualTo('two')
..parameterType.isEqualTo('int')
..hasEmptyReplacement()
- ..hasSelection(offset: 5),
+ ..hasSelection(offset: 3),
(suggestion) => suggestion
- // TODO(scheglov) This does not seem right.
- ..completion.isEqualTo('three: ')
+ ..completion.isEqualTo('three')
..parameterType.isEqualTo('double')
..hasEmptyReplacement()
- ..hasSelection(offset: 7),
+ ..hasSelection(offset: 5),
]);
},
);
@@ -740,6 +759,16 @@
''');
await computeAndCheck();
+ // Enum constant.
+ addTestSource2('''
+$languageVersionLine
+enum E {
+ v$arguments;
+ const E$parameters;
+}
+''');
+ await computeAndCheck();
+
// Function expression invocation.
addTestSource2('''
$languageVersionLine
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
index 57a911e..a7094e8 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_check.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -3,9 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer_utilities/check/check.dart';
import 'package:meta/meta.dart';
+typedef CompletionSuggestionChecker = void Function(
+ CompletionSuggestionTarget suggestion,
+);
+
+typedef CompletionSuggestionTarget
+ = CheckTarget<CompletionSuggestionForTesting>;
+
class CompletionResponseForTesting {
final int requestOffset;
final int replacementOffset;
@@ -179,6 +187,16 @@
element.isNotNull.kind.isConstructor;
}
+ void get isEnum {
+ kind.isIdentifier;
+ element.isNotNull.kind.isEnum;
+ }
+
+ void get isEnumConstant {
+ kind.isIdentifier;
+ element.isNotNull.kind.isEnumConstant;
+ }
+
void get isField {
kind.isIdentifier;
element.isNotNull.kind.isField;
@@ -194,11 +212,30 @@
element.isNotNull.kind.isGetter;
}
+ void get isImportPrefix {
+ kind.isIdentifier;
+ element.isNotNull.kind.isPrefix;
+ }
+
+ void get isKeywordAny {
+ kind.isKeyword;
+ }
+
void get isMethodInvocation {
kind.isInvocation;
element.isNotNull.kind.isMethod;
}
+ void get isMixin {
+ kind.isIdentifier;
+ element.isNotNull.kind.isMixin;
+ }
+
+ void get isNamedArgument {
+ kind.isNamedArgument;
+ element.isNull;
+ }
+
@useResult
CheckTarget<bool?> get isNotImported {
return nest(
@@ -231,10 +268,18 @@
}
@useResult
+ CheckTarget<String?> get libraryUri {
+ return nest(
+ value.suggestion.libraryUri,
+ (selected) => 'has libraryUri ${valueStr(selected)}',
+ );
+ }
+
+ @useResult
CheckTarget<String?> get libraryUriToImport {
return nest(
value.suggestion.isNotImported == true
- ? value.suggestion.element?.libraryUri
+ ? value.suggestion.libraryUri
: null,
(selected) => 'has libraryUriToImport ${valueStr(selected)}',
);
@@ -307,6 +352,11 @@
selectionOffset.isEqualTo(offset);
selectionLength.isEqualTo(length);
}
+
+ void isKeyword(Keyword keyword) {
+ kind.isKeyword;
+ completion.isEqualTo(keyword.lexeme);
+ }
}
extension CompletionSuggestionKindExtension
@@ -318,6 +368,14 @@
void get isInvocation {
isEqualTo(CompletionSuggestionKind.INVOCATION);
}
+
+ void get isKeyword {
+ isEqualTo(CompletionSuggestionKind.KEYWORD);
+ }
+
+ void get isNamedArgument {
+ isEqualTo(CompletionSuggestionKind.NAMED_ARGUMENT);
+ }
}
extension CompletionSuggestionsExtension
@@ -352,6 +410,18 @@
(selected) => 'withElementClass ${valueStr(selected)}',
);
}
+
+ @useResult
+ CheckTarget<Iterable<CompletionSuggestionForTesting>> get withKindKeyword {
+ var result = value
+ .where((suggestion) =>
+ suggestion.suggestion.kind == CompletionSuggestionKind.KEYWORD)
+ .toList();
+ return nest(
+ result,
+ (selected) => 'withKindKeyword ${valueStr(selected)}',
+ );
+ }
}
extension ElementExtension on CheckTarget<Element> {
@@ -381,6 +451,14 @@
isEqualTo(ElementKind.CONSTRUCTOR);
}
+ void get isEnum {
+ isEqualTo(ElementKind.ENUM);
+ }
+
+ void get isEnumConstant {
+ isEqualTo(ElementKind.ENUM_CONSTANT);
+ }
+
void get isField {
isEqualTo(ElementKind.FIELD);
}
@@ -397,10 +475,18 @@
isEqualTo(ElementKind.METHOD);
}
+ void get isMixin {
+ isEqualTo(ElementKind.MIXIN);
+ }
+
void get isParameter {
isEqualTo(ElementKind.PARAMETER);
}
+ void get isPrefix {
+ isEqualTo(ElementKind.PREFIX);
+ }
+
void get isSetter {
isEqualTo(ElementKind.SETTER);
}
@@ -409,3 +495,10 @@
isEqualTo(ElementKind.TOP_LEVEL_VARIABLE);
}
}
+
+extension KeywordsExtension on Iterable<Keyword> {
+ List<CompletionSuggestionChecker> get asKeywordChecks {
+ return map((e) => (CompletionSuggestionTarget suggestion) =>
+ suggestion.isKeyword(e)).toList();
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index f721cc8..c05f315 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -49,7 +49,7 @@
var builder = SuggestionBuilder(request);
var contributor = createContributor(request, builder);
await contributor.computeSuggestions();
- return builder.suggestions.toList();
+ return builder.suggestions.map((e) => e.build()).toList();
}
DartCompletionContributor createContributor(
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
index 842ac90..d154a6e 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
@@ -28,60 +28,285 @@
}
mixin EnumTestCases on AbstractCompletionDriverTest {
- @override
- bool get supportsAvailableSuggestions => true;
+ Future<void> test_enumConstantName() async {
+ await _check_locations(
+ declaration: 'enum MyEnum { foo01 }',
+ codeAtCompletion: 'foo0^',
+ validator: (response) {
+ check(response).hasReplacement(left: 4);
- Future<void> test_unprefixed_imported() async {
+ if (isProtocolVersion2) {
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum.foo01')
+ ..isEnumConstant,
+ ]);
+ // No other suggestions.
+ } else {
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum.foo01')
+ ..isEnumConstant,
+ // The response includes much more, such as `MyEnum` itself.
+ // We don't expect though that the client will show it.
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ ]);
+ }
+ },
+ );
+ }
+
+ Future<void> test_enumConstantName_imported_withPrefix() async {
+ await addProjectFile('lib/a.dart', r'''
+enum MyEnum { foo01 }
+''');
+
+ var response = await getTestCodeSuggestions('''
+import 'a.dart' as prefix;
+
+void f() {
+ foo0^
+}
+''');
+
+ check(response).hasReplacement(left: 4);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix.MyEnum.foo01')
+ ..isEnumConstant,
+ ]);
+ } else {
+ // TODO(scheglov) This is wrong.
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum.foo01')
+ ..isEnumConstant,
+ ]);
+ }
+ }
+
+ Future<void> test_enumName() async {
+ await _check_locations(
+ declaration: 'enum MyEnum { foo01 }',
+ codeAtCompletion: 'MyEnu^',
+ validator: (response) {
+ check(response).hasReplacement(left: 5);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ ]);
+ // No enum constants.
+ } else {
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ ]);
+ }
+ },
+ );
+ }
+
+ Future<void> test_enumName_imported_withPrefix() async {
+ await addProjectFile('lib/a.dart', r'''
+enum MyEnum { foo01 }
+''');
+
+ var response = await getTestCodeSuggestions('''
+import 'a.dart' as prefix;
+
+void f() {
+ MyEnu^
+}
+''');
+
+ check(response).hasReplacement(left: 5);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix.MyEnum')
+ ..isEnum,
+ ]);
+ } else {
+ // TODO(scheglov) This is wrong.
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ ]);
+ }
+ }
+
+ @FailingTest(reason: 'element.kind is LIBRARY')
+ Future<void> test_importPrefix() async {
await addProjectFile('lib/a.dart', r'''
enum MyEnum { v }
''');
var response = await getTestCodeSuggestions('''
-import 'a.dart';
+import 'a.dart' as prefix01;
void f() {
- ^
+ prefix0^
}
''');
- _checkUnprefixed(response);
+ check(response).hasReplacement(left: 7);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix01')
+ ..isImportPrefix,
+ ]);
+ } else {
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix01')
+ ..isImportPrefix,
+ ]);
+ }
}
- Future<void> test_unprefixed_local() async {
- var response = await getTestCodeSuggestions('''
-enum MyEnum { v }
-
-void f() {
- ^
-}
-''');
-
- _checkUnprefixed(response);
- }
-
- Future<void> test_unprefixed_notImported() async {
+ Future<void> test_importPrefix_dot() async {
await addProjectFile('lib/a.dart', r'''
enum MyEnum { v }
''');
var response = await getTestCodeSuggestions('''
+import 'a.dart' as prefix;
+
void f() {
- ^
+ prefix.^
}
''');
- _checkUnprefixed(response);
- }
+ check(response).hasEmptyReplacement();
- void _checkUnprefixed(CompletionResponseForTesting response) {
check(response).suggestions
..includesAll([
- (suggestion) => suggestion.completion.isEqualTo('MyEnum.v'),
- ])
- ..excludesAll([
(suggestion) => suggestion
- ..completion.startsWith('MyEnum')
- ..isConstructorInvocation,
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ ])
+ // TODO(scheglov) This is wrong.
+ // Should include constants, as [test_nothing_imported_withPrefix] does.
+ ..excludesAll([
+ (suggestion) => suggestion.isEnumConstant,
]);
}
+
+ Future<void> test_nothing() async {
+ await _check_locations(
+ declaration: 'enum MyEnum { v }',
+ codeAtCompletion: '^',
+ validator: (response) {
+ check(response).hasEmptyReplacement();
+
+ check(response).suggestions
+ ..includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum.v')
+ ..isEnumConstant,
+ ])
+ ..excludesAll([
+ (suggestion) => suggestion
+ ..completion.startsWith('MyEnum')
+ ..isConstructorInvocation,
+ ]);
+ },
+ );
+ }
+
+ Future<void> test_nothing_imported_withPrefix() async {
+ await addProjectFile('lib/a.dart', r'''
+enum MyEnum { v }
+''');
+
+ var response = await getTestCodeSuggestions('''
+import 'a.dart' as prefix;
+
+void f() {
+ ^
+}
+''');
+
+ check(response).hasEmptyReplacement();
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix.MyEnum')
+ ..isEnum,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('prefix.MyEnum.v')
+ ..isEnumConstant,
+ ]);
+ } else {
+ // TODO(scheglov) This is wrong.
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum')
+ ..isEnum,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('MyEnum.v')
+ ..isEnumConstant,
+ ]);
+ }
+ }
+
+ Future<void> _check_locations({
+ required String declaration,
+ required String codeAtCompletion,
+ required void Function(CompletionResponseForTesting response) validator,
+ }) async {
+ // local
+ {
+ var response = await getTestCodeSuggestions('''
+$declaration
+void f() {
+ $codeAtCompletion
+}
+''');
+ validator(response);
+ }
+
+ // imported
+ {
+ await addProjectFile('lib/a.dart', '''
+$declaration
+''');
+ var response = await getTestCodeSuggestions('''
+import 'a.dart';
+void f() {
+ $codeAtCompletion
+}
+''');
+ validator(response);
+ }
+
+ // not imported
+ {
+ await addProjectFile('lib/a.dart', '''
+$declaration
+''');
+ var response = await getTestCodeSuggestions('''
+void f() {
+ $codeAtCompletion
+}
+''');
+ validator(response);
+ }
+ }
}
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/library_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/library_test.dart
new file mode 100644
index 0000000..e5eea3f
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/library_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(LibraryTest1);
+ defineReflectiveTests(LibraryTest2);
+ });
+}
+
+mixin EnumTestCases on AbstractCompletionDriverTest {
+ Future<void> test_dart_noInternalLibraries() async {
+ var response = await getTestCodeSuggestions('''
+void f() {
+ ^
+}
+''');
+
+ check(response).suggestions.excludesAll([
+ (suggestion) => suggestion.libraryUri.isNotNull.startsWith('dart:_'),
+ ]);
+ }
+}
+
+@reflectiveTest
+class LibraryTest1 extends AbstractCompletionDriverTest with EnumTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class LibraryTest2 extends AbstractCompletionDriverTest with EnumTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart b/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart
index b1de9ef..12cf693 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart
@@ -5,10 +5,12 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'enum_test.dart' as enum_;
+import 'library_test.dart' as library_;
/// Tests suggestions produced for various kinds of declarations.
void main() {
defineReflectiveSuite(() {
enum_.main();
+ library_.main();
});
}
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
deleted file mode 100644
index d63a695..0000000
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
-import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
-import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analyzer_utilities/check/check.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'completion_check.dart';
-import 'completion_contributor_util.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(FieldFormalContributorTest);
- });
-}
-
-@reflectiveTest
-class FieldFormalContributorTest extends DartCompletionContributorTest {
- @override
- DartCompletionContributor createContributor(
- DartCompletionRequest request,
- SuggestionBuilder builder,
- ) {
- return FieldFormalContributor(request, builder);
- }
-
- /// https://github.com/dart-lang/sdk/issues/39028
- Future<void> test_mixin_constructor() async {
- addTestSource('''
-mixin M {
- var field = 0;
- M(this.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response).suggestions.isEmpty;
- }
-
- Future<void> test_replacement_left() async {
- addTestSource('''
-class A {
- var field = 0;
- A(this.f^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasReplacement(left: 1)
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('field')
- ..isField
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_replacement_right() async {
- addTestSource('''
-class A {
- var field = 0;
- A(this.^f);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasReplacement(right: 1)
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('field')
- ..isField
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_suggestions_onlyLocal() async {
- addTestSource('''
-class A {
- var inherited = 0;
-}
-
-class B extends A {
- var first = 0;
- var second = 1.2;
- B(this.^);
- B.constructor() {}
- void method() {}
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isField
- ..returnType.isEqualTo('int'),
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isField
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_suggestions_onlyNotSpecified_optionalNamed() async {
- addTestSource('''
-class Point {
- final int x;
- final int y;
- Point({this.x, this.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('y')
- ..isField
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_suggestions_onlyNotSpecified_requiredPositional() async {
- addTestSource('''
-class Point {
- final int x;
- final int y;
- Point(this.x, this.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('y')
- ..isField
- ..returnType.isEqualTo('int'),
- ]);
- }
-}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index c2c05ab..1918e2d 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -394,6 +394,7 @@
Keyword.ABSTRACT,
Keyword.CONST,
Keyword.COVARIANT,
+ Keyword.DYNAMIC,
Keyword.EXTERNAL,
Keyword.FINAL
];
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index c463ed9..235ed40 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -1658,7 +1658,7 @@
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
- assertSuggestParameter('e', 'E');
+ assertSuggestLocalVariable('e', 'E');
assertSuggestMethod('a', 'A', null);
assertNotSuggested('Object');
assertNotSuggested('x');
@@ -1671,8 +1671,8 @@
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
- assertSuggestParameter('e', 'Object');
- assertSuggestParameter('s', 'StackTrace');
+ assertSuggestLocalVariable('e', 'Object');
+ assertSuggestLocalVariable('s', 'StackTrace');
assertSuggestMethod('a', 'A', null);
assertNotSuggested('Object');
assertNotSuggested('x');
diff --git a/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart b/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart
new file mode 100644
index 0000000..d473b9f
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/class_body_test.dart
@@ -0,0 +1,322 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ClassBodyTest1);
+ defineReflectiveTests(ClassBodyTest2);
+ });
+}
+
+@reflectiveTest
+class ClassBodyTest1 extends AbstractCompletionDriverTest
+ with ClassBodyTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class ClassBodyTest2 extends AbstractCompletionDriverTest
+ with ClassBodyTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin ClassBodyTestCases on AbstractCompletionDriverTest {
+ /// It does not really matter which classes we list here, in this test
+ /// suite we only need to know that we suggest classes at all.
+ List<CompletionSuggestionChecker> get sampleClassChecks {
+ return const {
+ 'Object',
+ }.map((name) {
+ return (CompletionSuggestionTarget suggestion) {
+ suggestion
+ ..completion.isEqualTo(name)
+ ..isClass;
+ };
+ }).toList();
+ }
+
+ Future<void> test_nothing_x() async {
+ await _checkContainers(
+ line: '^',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ // TODO(scheglov) Not quite right, without static.
+ Keyword.CONST,
+ if (context.isClass || context.isMixin) Keyword.COVARIANT,
+ Keyword.DYNAMIC,
+ // TODO(scheglov) This does not look right, mixin.
+ if (context.isClass || context.isMixin) Keyword.FACTORY,
+ Keyword.FINAL,
+ Keyword.GET,
+ Keyword.LATE,
+ Keyword.OPERATOR,
+ Keyword.SET,
+ Keyword.STATIC,
+ Keyword.VAR,
+ Keyword.VOID,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_static_const_x() async {
+ await _checkContainers(
+ line: 'static const ^',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.DYNAMIC,
+ Keyword.VOID,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_static_final_Ox() async {
+ await _checkContainers(
+ line: 'static final O^',
+ validator: (context, response) {
+ if (isProtocolVersion2) {
+ check(response).suggestions
+ ..withKindKeyword.isEmpty
+ ..includesAll(sampleClassChecks);
+ } else {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.DYNAMIC,
+ Keyword.VOID,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ }
+ },
+ );
+ }
+
+ Future<void> test_static_final_x() async {
+ await _checkContainers(
+ line: 'static final ^',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.DYNAMIC,
+ Keyword.VOID,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_static_fx() async {
+ await _checkContainers(
+ line: 'static f^',
+ validator: (context, response) {
+ if (isProtocolVersion2) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.FINAL,
+ }.asKeywordChecks,
+ )
+ ..includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('FutureOr')
+ ..isClass,
+ ]);
+ } else {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.ABSTRACT,
+ Keyword.CONST,
+ Keyword.COVARIANT,
+ Keyword.DYNAMIC,
+ Keyword.EXTERNAL,
+ Keyword.FINAL,
+ Keyword.LATE,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ }
+ },
+ );
+ }
+
+ Future<void> test_static_late_x() async {
+ await _checkContainers(
+ line: 'static late ^',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.DYNAMIC,
+ Keyword.FINAL,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_static_x() async {
+ await _checkContainers(
+ line: 'static ^',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.CONST,
+ Keyword.DYNAMIC,
+ Keyword.FINAL,
+ Keyword.LATE,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_static_x_name_eq() async {
+ await _checkContainers(
+ line: 'static ^ name = 0;',
+ validator: (context, response) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ // TODO(scheglov) This does not look right.
+ Keyword.ABSTRACT,
+ Keyword.CONST,
+ // TODO(scheglov) This does not look right.
+ Keyword.COVARIANT,
+ Keyword.DYNAMIC,
+ // TODO(scheglov) This does not look right.
+ Keyword.EXTERNAL,
+ Keyword.FINAL,
+ Keyword.LATE,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ },
+ );
+ }
+
+ Future<void> test_sx() async {
+ await _checkContainers(
+ line: 's^',
+ validator: (context, response) {
+ if (isProtocolVersion2) {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ Keyword.SET,
+ Keyword.STATIC,
+ }.asKeywordChecks,
+ )
+ ..includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('String')
+ ..isClass,
+ ]);
+ } else {
+ check(response).suggestions
+ ..withKindKeyword.matchesInAnyOrder(
+ {
+ // TODO(scheglov) Not quite right, without static.
+ Keyword.CONST,
+ if (context.isClass || context.isMixin) Keyword.COVARIANT,
+ Keyword.DYNAMIC,
+ // TODO(scheglov) This does not look right, mixin.
+ if (context.isClass || context.isMixin) Keyword.FACTORY,
+ Keyword.FINAL,
+ Keyword.GET,
+ Keyword.LATE,
+ Keyword.OPERATOR,
+ Keyword.SET,
+ Keyword.STATIC,
+ Keyword.VAR,
+ Keyword.VOID,
+ }.asKeywordChecks,
+ )
+ ..includesAll(sampleClassChecks);
+ }
+ },
+ );
+ }
+
+ Future<void> _checkContainers({
+ required String line,
+ required void Function(
+ _Context context,
+ CompletionResponseForTesting response,
+ )
+ validator,
+ }) async {
+ // class
+ {
+ var response = await getTestCodeSuggestions('''
+class A {
+ $line
+}
+''');
+ validator(_Context(isClass: true), response);
+ }
+ // enum
+ {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v;
+ $line
+}
+''');
+ validator(_Context(), response);
+ }
+ // extension
+ {
+ var response = await getTestCodeSuggestions('''
+extension on Object {
+ $line
+}
+''');
+ validator(_Context(), response);
+ }
+ // mixin
+ {
+ var response = await getTestCodeSuggestions('''
+mixin M {
+ $line
+}
+''');
+ validator(_Context(isMixin: true), response);
+ }
+ }
+}
+
+class _Context {
+ final bool isClass;
+ final bool isMixin;
+
+ _Context({
+ this.isClass = false,
+ this.isMixin = false,
+ });
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/enum_constant_test.dart b/pkg/analysis_server/test/services/completion/dart/location/enum_constant_test.dart
new file mode 100644
index 0000000..90a8f54
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/enum_constant_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(EnumConstantDeclarationTest1);
+ defineReflectiveTests(EnumConstantDeclarationTest2);
+ });
+}
+
+@reflectiveTest
+class EnumConstantDeclarationTest1 extends AbstractCompletionDriverTest
+ with EnumConstantDeclarationTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class EnumConstantDeclarationTest2 extends AbstractCompletionDriverTest
+ with EnumConstantDeclarationTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin EnumConstantDeclarationTestCases on AbstractCompletionDriverTest {
+ Future<void> test_afterName_atEnd() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v^
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/enum_test.dart b/pkg/analysis_server/test/services/completion/dart/location/enum_test.dart
new file mode 100644
index 0000000..5ebb1ac
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/enum_test.dart
@@ -0,0 +1,338 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(EnumDeclarationTest1);
+ defineReflectiveTests(EnumDeclarationTest2);
+ });
+}
+
+@reflectiveTest
+class EnumDeclarationTest1 extends AbstractCompletionDriverTest
+ with EnumDeclarationTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class EnumDeclarationTest2 extends AbstractCompletionDriverTest
+ with EnumDeclarationTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+
+ Future<void> test_afterName_w() async {
+ var response = await getTestCodeSuggestions('''
+enum E w^ {
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.WITH,
+ }.asKeywordChecks,
+ ]);
+ }
+}
+
+mixin EnumDeclarationTestCases on AbstractCompletionDriverTest {
+ Future<void> test_afterConstants_noSemicolon() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v ^
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_afterImplements() async {
+ var response = await getTestCodeSuggestions('''
+enum E implements ^ {
+ v
+}
+''');
+
+ check(response).suggestions
+ ..withKindKeyword.isEmpty
+ ..includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('Object')
+ ..isClass,
+ ]);
+ }
+
+ Future<void> test_afterImplementsClause() async {
+ var response = await getTestCodeSuggestions('''
+enum E implements A ^ {
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.WITH,
+ }.asKeywordChecks,
+ ]);
+ }
+
+ Future<void> test_afterName() async {
+ var response = await getTestCodeSuggestions('''
+enum E ^ {
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.IMPLEMENTS,
+ Keyword.WITH,
+ }.asKeywordChecks,
+ ]);
+ }
+
+ Future<void> test_afterName_atEnd() async {
+ var response = await getTestCodeSuggestions('''
+enum E^ {
+ v
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_afterName_atLeftCurlyBracket() async {
+ var response = await getTestCodeSuggestions('''
+enum E ^{
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.IMPLEMENTS,
+ Keyword.WITH,
+ }.asKeywordChecks,
+ ]);
+ }
+
+ Future<void> test_afterName_beforeImplements() async {
+ var response = await getTestCodeSuggestions('''
+enum E ^ implements A {
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.WITH,
+ }.asKeywordChecks,
+ ]);
+ }
+
+ Future<void> test_afterName_hasWith_hasImplements() async {
+ var response = await getTestCodeSuggestions('''
+enum E ^ with M implements A {
+ v
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_afterName_language216() async {
+ var response = await getTestCodeSuggestions('''
+// @dart = 2.16
+enum E ^ {
+ v
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_afterWith() async {
+ var response = await getTestCodeSuggestions('''
+enum E with ^ {
+ v
+}
+''');
+
+ check(response).suggestions
+ ..withKindKeyword.isEmpty
+ ..includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('Object')
+ ..isClass,
+ ]);
+ }
+
+ Future<void> test_afterWithClause() async {
+ var response = await getTestCodeSuggestions('''
+enum E with M ^ {
+ v
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ ...{
+ Keyword.IMPLEMENTS,
+ }.asKeywordChecks,
+ ]);
+ }
+
+ Future<void> test_beforeConstants_hasSemicolon() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ ^ v;
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_beforeConstants_noSemicolon() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ ^ v
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_constantName_dot_name_x_argumentList_named() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.foo0^();
+ const E.foo01();
+ const E.foo02();
+ const E.bar01();
+}
+''');
+
+ if (isProtocolVersion2) {
+ check(response)
+ ..hasReplacement(left: 4)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..isConstructorInvocation,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..isConstructorInvocation,
+ ]);
+ }
+ }
+
+ Future<void> test_constantName_dot_name_x_semicolon_named() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.foo0^;
+ const E.foo01();
+ const E.foo02();
+ const E.bar01();
+}
+''');
+
+ if (isProtocolVersion2) {
+ check(response)
+ ..hasReplacement(left: 4)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..isConstructorInvocation,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..isConstructorInvocation,
+ ]);
+ }
+ }
+
+ Future<void> test_constantName_dot_x_argumentList_named() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.^();
+ const E.foo01();
+ const E.foo02();
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..isConstructorInvocation,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..isConstructorInvocation,
+ ]);
+ }
+
+ Future<void> test_constantName_dot_x_semicolon_named() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.^;
+ const E.foo01();
+ const E.foo02();
+}
+''');
+
+ check(response).suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..isConstructorInvocation,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..isConstructorInvocation,
+ ]);
+ }
+
+ Future<void> test_constantName_dot_x_semicolon_unnamed_declared() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.^;
+ const E();
+}
+''');
+
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('new')
+ ..isConstructorInvocation,
+ ]);
+ }
+
+ Future<void> test_constantName_dot_x_unnamed_implicit() async {
+ var response = await getTestCodeSuggestions('''
+enum E {
+ v.^
+}
+''');
+
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('new')
+ ..isConstructorInvocation,
+ ]);
+ }
+
+ Future<void> test_constantName_dot_x_unnamed_language216() async {
+ var response = await getTestCodeSuggestions('''
+// @dart = 2.16
+enum E {
+ v.^
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/field_formal_parameter_test.dart b/pkg/analysis_server/test/services/completion/dart/location/field_formal_parameter_test.dart
new file mode 100644
index 0000000..41f4004
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/field_formal_parameter_test.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FieldFormalParameterTest1);
+ defineReflectiveTests(FieldFormalParameterTest2);
+ });
+}
+
+@reflectiveTest
+class FieldFormalParameterTest1 extends AbstractCompletionDriverTest
+ with SuperFormalParameterTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class FieldFormalParameterTest2 extends AbstractCompletionDriverTest
+ with SuperFormalParameterTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin SuperFormalParameterTestCases on AbstractCompletionDriverTest {
+ /// https://github.com/dart-lang/sdk/issues/39028
+ Future<void> test_mixin_constructor() async {
+ var response = await getTestCodeSuggestions('''
+mixin M {
+ var field = 0;
+ M(this.^);
+}
+''');
+
+ check(response).suggestions.isEmpty;
+ }
+
+ Future<void> test_replacement_left() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ var field = 0;
+ A(this.f^);
+}
+''');
+
+ check(response)
+ ..hasReplacement(left: 1)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('field')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_replacement_right() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ var field = 0;
+ A(this.^f);
+}
+''');
+
+ check(response)
+ ..hasReplacement(right: 1)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('field')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_suggestions_onlyLocal() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ var inherited = 0;
+}
+
+class B extends A {
+ var first = 0;
+ var second = 1.2;
+ B(this.^);
+ B.constructor() {}
+ void method() {}
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isField
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_suggestions_onlyNotSpecified_optionalNamed() async {
+ var response = await getTestCodeSuggestions('''
+class Point {
+ final int x;
+ final int y;
+ Point({this.x, this.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('y')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_suggestions_onlyNotSpecified_requiredPositional() async {
+ var response = await getTestCodeSuggestions('''
+class Point {
+ final int x;
+ final int y;
+ Point(this.x, this.^);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('y')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/named_expression_test.dart b/pkg/analysis_server/test/services/completion/dart/location/named_expression_test.dart
new file mode 100644
index 0000000..c6355ea
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/named_expression_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NamedExpressionExpressionTest1);
+ defineReflectiveTests(NamedExpressionExpressionTest2);
+ });
+}
+
+@reflectiveTest
+class NamedExpressionExpressionTest1 extends AbstractCompletionDriverTest
+ with NamedExpressionExpressionTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class NamedExpressionExpressionTest2 extends AbstractCompletionDriverTest
+ with NamedExpressionExpressionTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin NamedExpressionExpressionTestCases on AbstractCompletionDriverTest {
+ Future<void> test_beforePositional() async {
+ var response = await getTestCodeSuggestions('''
+void f(int x) {
+ g(b: ^, 0);
+}
+
+void g(int a, {required int b}) {}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('x')
+ ..isParameter,
+ ]);
+ }
+
+ Future<void> test_lastArgument() async {
+ var response = await getTestCodeSuggestions('''
+void f(int x) {
+ g(0, b: ^);
+}
+
+void g(int a, {required int b}) {}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('x')
+ ..isParameter,
+ ]);
+ }
+
+ Future<void> test_onlyArgument() async {
+ var response = await getTestCodeSuggestions('''
+void f(int x) {
+ g(a: ^);
+}
+
+void g({required int a}) {}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('x')
+ ..isParameter,
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/super_formal_parameter_test.dart b/pkg/analysis_server/test/services/completion/dart/location/super_formal_parameter_test.dart
new file mode 100644
index 0000000..2d4144a
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/super_formal_parameter_test.dart
@@ -0,0 +1,454 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SuperFormalParameterTest1);
+ defineReflectiveTests(SuperFormalParameterTest2);
+ });
+}
+
+@reflectiveTest
+class SuperFormalParameterTest1 extends AbstractCompletionDriverTest
+ with SuperFormalParameterTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class SuperFormalParameterTest2 extends AbstractCompletionDriverTest
+ with SuperFormalParameterTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin SuperFormalParameterTestCases on AbstractCompletionDriverTest {
+ Future<void> test_explicit_optionalNamed_hasArgument_named() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.^}) : super(first: 0);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_explicit_optionalNamed_hasArgument_positional() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.^}) : super(0);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ /// It is an error, but the user already typed `super.`, so maybe do it.
+ Future<void> test_explicit_requiredPositional_hasArgument_positional() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(int first, double second);
+}
+
+class B extends A {
+ B(super.^) : super(0);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_explicitNamed_noOther() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A.named(int first, double second);
+ A(int third)
+}
+
+class B extends A {
+ B(super.^) : super.named();
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_notSuper() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({int a, super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_notSuper2() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({int first, super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_super() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.first, super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_super2() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.second, super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasPositional_notSuper() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B(int a, {super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasPositional_super() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B(super.first, {super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_noOther() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(bool first, {int second, double third});
+}
+
+class B extends A {
+ B({super.^});
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('third')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_notSuper() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A([int first, double second]);
+}
+
+class B extends A {
+ B([int one, super.^]);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_super() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A([int first, double second, bool third]);
+}
+
+class B extends A {
+ B([super.one, super.^]);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_super2() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A([int first, double second, bool third]);
+}
+
+class B extends A {
+ B([super.second, super.^]);
+}
+''');
+
+ // It does not matter what is the name of the positional parameter.
+ // Here `super.second` consumes `int first`.
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_noOther() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A([int first, double second]);
+}
+
+class B extends A {
+ B(super.^);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_notSuper() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(int first, double second);
+}
+
+class B extends A {
+ B(int one, super.^);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_super() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(int first, double second, bool third);
+}
+
+class B extends A {
+ B(super.one, super.^);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_super2() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(int first, double second, bool third);
+}
+
+class B extends A {
+ B(super.second, super.^);
+}
+''');
+
+ // It does not matter what is the name of the positional parameter.
+ // Here `super.second` consumes `int first`.
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_noOther() async {
+ var response = await getTestCodeSuggestions('''
+class A {
+ A(int first, double second);
+ A.named(int third);
+}
+
+class B extends A {
+ B(super.^);
+}
+''');
+
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/test_all.dart b/pkg/analysis_server/test/services/completion/dart/location/test_all.dart
new file mode 100644
index 0000000..5fc5401
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/test_all.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'class_body_test.dart' as class_body;
+import 'enum_constant_test.dart' as enum_constant;
+import 'enum_test.dart' as enum_;
+import 'field_formal_parameter_test.dart' as field_formal_parameter;
+import 'named_expression_test.dart' as named_expression;
+import 'super_formal_parameter_test.dart' as super_formal_parameter;
+
+/// Tests suggestions produced at specific locations.
+void main() {
+ defineReflectiveSuite(() {
+ class_body.main();
+ enum_constant.main();
+ enum_.main();
+ field_formal_parameter.main();
+ named_expression.main();
+ super_formal_parameter.main();
+ });
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
index f353b8d..018c26d 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
@@ -8,9 +8,6 @@
import '../../../../client/completion_driver_test.dart';
abstract class CompletionRelevanceTest extends AbstractCompletionDriverTest {
- @override
- bool get supportsAvailableSuggestions => true;
-
/// Assert that all of the given completions were produced and that the
/// suggestions are ordered in decreasing order based on relevance scores.
void assertOrder(List<CompletionSuggestion> suggestions) {
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
index b6ad9fc..73fa3be 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
@@ -29,9 +29,6 @@
}
mixin InstanceMemberTestCases on CompletionRelevanceTest {
- @override
- bool get supportsAvailableSuggestions => true;
-
Future<void> test_contextType() async {
await addTestFile(r'''
class A {}
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
index 018a020..ea4ec7e 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
@@ -32,14 +32,15 @@
mixin NamedArgumentTestCases on CompletionRelevanceTest {
@override
Future<void> setUp() async {
- await super.setUp();
-
var metaLibFolder = MockPackages.instance.addMeta(resourceProvider);
- newDotPackagesFile(projectPath, content: '''
+ // TODO(scheglov) Use `writeTestPackageConfig` instead
+ newDotPackagesFile(testPackageRootPath, content: '''
meta:${metaLibFolder.toUri()}
-project:${toUri('$projectPath/lib')}
+project:${toUri(testPackageLibPath)}
''');
+
+ await super.setUp();
}
Future<void> test_required() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
deleted file mode 100644
index 88d16b9..0000000
--- a/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
+++ /dev/null
@@ -1,471 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
-import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/dart/super_formal_contributor.dart';
-import 'package:analyzer_utilities/check/check.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'completion_check.dart';
-import 'completion_contributor_util.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(SuperFormalContributorTest);
- });
-}
-
-@reflectiveTest
-class SuperFormalContributorTest extends DartCompletionContributorTest {
- @override
- DartCompletionContributor createContributor(
- DartCompletionRequest request,
- SuggestionBuilder builder,
- ) {
- return SuperFormalContributor(request, builder);
- }
-
- Future<void> test_explicit_optionalNamed_hasArgument_named() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({super.^}) : super(first: 0);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_explicit_optionalNamed_hasArgument_positional() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({super.^}) : super(0);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- /// It is an error, but the user already typed `super.`, so maybe do it.
- Future<void> test_explicit_requiredPositional_hasArgument_positional() async {
- addTestSource('''
-class A {
- A(int first, double second);
-}
-
-class B extends A {
- B(super.^) : super(0);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_explicitNamed_noOther() async {
- addTestSource('''
-class A {
- A.named(int first, double second);
- A(int third)
-}
-
-class B extends A {
- B(super.^) : super.named();
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasNamed_notSuper() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({int a, super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasNamed_notSuper2() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({int first, super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasNamed_super() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({super.first, super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasNamed_super2() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B({super.second, super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasPositional_notSuper() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B(int a, {super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_hasPositional_super() async {
- addTestSource('''
-class A {
- A({int first, double second});
-}
-
-class B extends A {
- B(super.first, {super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalNamed_noOther() async {
- addTestSource('''
-class A {
- A(bool first, {int second, double third});
-}
-
-class B extends A {
- B({super.^});
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('int'),
- (suggestion) => suggestion
- ..completion.isEqualTo('third')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalPositional_hasPositional_notSuper() async {
- addTestSource('''
-class A {
- A([int first, double second]);
-}
-
-class B extends A {
- B([int one, super.^]);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_implicit_optionalPositional_hasPositional_super() async {
- addTestSource('''
-class A {
- A([int first, double second, bool third]);
-}
-
-class B extends A {
- B([super.one, super.^]);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalPositional_hasPositional_super2() async {
- addTestSource('''
-class A {
- A([int first, double second, bool third]);
-}
-
-class B extends A {
- B([super.second, super.^]);
-}
-''');
-
- // It does not matter what is the name of the positional parameter.
- // Here `super.second` consumes `int first`.
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_optionalPositional_noOther() async {
- addTestSource('''
-class A {
- A([int first, double second]);
-}
-
-class B extends A {
- B(super.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_implicit_requiredPositional_hasPositional_notSuper() async {
- addTestSource('''
-class A {
- A(int first, double second);
-}
-
-class B extends A {
- B(int one, super.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-
- Future<void> test_implicit_requiredPositional_hasPositional_super() async {
- addTestSource('''
-class A {
- A(int first, double second, bool third);
-}
-
-class B extends A {
- B(super.one, super.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_requiredPositional_hasPositional_super2() async {
- addTestSource('''
-class A {
- A(int first, double second, bool third);
-}
-
-class B extends A {
- B(super.second, super.^);
-}
-''');
-
- // It does not matter what is the name of the positional parameter.
- // Here `super.second` consumes `int first`.
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('second')
- ..isParameter
- ..returnType.isEqualTo('double'),
- ]);
- }
-
- Future<void> test_implicit_requiredPositional_noOther() async {
- addTestSource('''
-class A {
- A(int first, double second);
- A.named(int third);
-}
-
-class B extends A {
- B(super.^);
-}
-''');
-
- var response = await computeSuggestions2();
- check(response)
- ..hasEmptyReplacement()
- ..suggestions.matchesInAnyOrder([
- (suggestion) => suggestion
- ..completion.isEqualTo('first')
- ..isParameter
- ..returnType.isEqualTo('int'),
- ]);
- }
-}
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 0ed0678..29e4a22 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -10,7 +10,6 @@
import 'completion_manager_test.dart' as completion_manager;
import 'declaration/test_all.dart' as declaration;
import 'extension_member_contributor_test.dart' as extension_member_contributor;
-import 'field_formal_contributor_test.dart' as field_formal_contributor_test;
import 'imported_reference_contributor_test.dart' as imported_ref_test;
import 'keyword_contributor_test.dart' as keyword_test;
import 'label_contributor_test.dart' as label_contributor_test;
@@ -18,11 +17,11 @@
import 'library_prefix_contributor_test.dart' as library_prefix_test;
import 'local_library_contributor_test.dart' as local_lib_test;
import 'local_reference_contributor_test.dart' as local_ref_test;
+import 'location/test_all.dart' as location;
import 'named_constructor_contributor_test.dart' as named_contributor_test;
import 'override_contributor_test.dart' as override_contributor_test;
import 'relevance/test_all.dart' as relevance_tests;
import 'static_member_contributor_test.dart' as static_contributor_test;
-import 'super_formal_contributor_test.dart' as super_formal_contributor;
import 'type_member_contributor_test.dart' as type_member_contributor_test;
import 'uri_contributor_test.dart' as uri_contributor_test;
import 'variable_name_contributor_test.dart' as variable_name_contributor_test;
@@ -35,7 +34,6 @@
completion_manager.main();
declaration.main();
extension_member_contributor.main();
- field_formal_contributor_test.main();
imported_ref_test.main();
keyword_test.main();
label_contributor_test.main();
@@ -43,11 +41,11 @@
library_prefix_test.main();
local_lib_test.main();
local_ref_test.main();
+ location.main();
named_contributor_test.main();
override_contributor_test.main();
relevance_tests.main();
static_contributor_test.main();
- super_formal_contributor.main();
type_member_contributor_test.main();
uri_contributor_test.main();
variable_name_contributor_test.main();
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index 47000b2..a5d53f4 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -1674,6 +1674,8 @@
assertNotSuggested('values');
}
+ /// TODO(scheglov) move this test into contributor independent suite
+ @FailingTest(reason: 'No index, not local anymore')
Future<void> test_enumConst_index() async {
addTestSource('enum E { one, two } void f() {E.one.^}');
await computeSuggestions();
@@ -1684,6 +1686,8 @@
assertNotSuggested('values');
}
+ /// TODO(scheglov) move this test into contributor independent suite
+ @FailingTest(reason: 'No index, not local anymore')
Future<void> test_enumConst_index2() async {
addTestSource('enum E { one, two } void f() {E.one.i^}');
await computeSuggestions();
@@ -1694,6 +1698,8 @@
assertNotSuggested('values');
}
+ /// TODO(scheglov) move this test into contributor independent suite
+ @FailingTest(reason: 'No index, not local anymore')
Future<void> test_enumConst_index3() async {
addTestSource('enum E { one, two } void f() {E.one.^ int g;}');
await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index 87042b0..5e7fb27 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -585,6 +585,156 @@
''');
}
+ Future<void> test_enum_accessor() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ set c(x) {}
+ set a(x) {}
+ get a => null;
+ get b => null;
+ set b(x) {}
+ get c => null;
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ get a => null;
+ set a(x) {}
+ get b => null;
+ set b(x) {}
+ get c => null;
+ set c(x) {}
+}
+''');
+ }
+
+ Future<void> test_enum_accessor_static() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ get a => null;
+ set a(x) {}
+ static get b => null;
+ static set b(x) {}
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ static get b => null;
+ static set b(x) {}
+ get a => null;
+ set a(x) {}
+}
+''');
+ }
+
+ Future<void> test_enum_field_static() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ int b;
+ int a;
+ static int d;
+ static int c;
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ static int d;
+ static int c;
+ int b;
+ int a;
+}
+''');
+ }
+
+ Future<void> test_enum_method() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ c() {}
+ a() {}
+ b() {}
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ a() {}
+ b() {}
+ c() {}
+}
+''');
+ }
+
+ Future<void> test_enum_method_emptyLine() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+
+ b() {}
+
+ a() {}
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+
+ a() {}
+
+ b() {}
+}
+''');
+ }
+
+ Future<void> test_enum_method_ignoreCase() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ m_C() {}
+ m_a() {}
+ m_B() {}
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ m_a() {}
+ m_B() {}
+ m_C() {}
+}
+''');
+ }
+
+ Future<void> test_enum_method_static() async {
+ await _parseTestUnit(r'''
+enum E {
+ v;
+ static a() {}
+ b() {}
+}
+''');
+ // validate change
+ _assertSort(r'''
+enum E {
+ v;
+ b() {}
+ static a() {}
+}
+''');
+ }
+
Future<void> test_extension_accessor() async {
await _parseTestUnit(r'''
extension E on int {
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index 8b090db..ee79e97 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -20,6 +20,28 @@
@override
late ConvertGetterToMethodRefactoring refactoring;
+ Future<void> test_change_extensionMethod() async {
+ await indexTestUnit('''
+extension A on String {
+ int get test => 1;
+}
+void f(String a) {
+ var va = a.test;
+}
+''');
+ var element = findElement.getter('test', of: 'A');
+ _createRefactoringForElement(element);
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+extension A on String {
+ int test() => 1;
+}
+void f(String a) {
+ var va = a.test();
+}
+''');
+ }
+
Future<void> test_change_function() async {
await indexTestUnit('''
int get test => 42;
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index 98584b89..865fbcb 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -11,15 +11,129 @@
void main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(ExtractMethodEnumTest);
defineReflectiveTests(ExtractMethodTest);
});
}
@reflectiveTest
-class ExtractMethodTest extends RefactoringTest {
- @override
- late ExtractMethodRefactoringImpl refactoring;
+class ExtractMethodEnumTest extends _ExtractMethodTest {
+ Future<void> test_bad_conflict_method_alreadyDeclaresMethod() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void res() {}
+ void foo() {
+// start
+ print(0);
+// end
+ }
+}
+''');
+ _createRefactoringForStartEndComments();
+ return _assertConditionsError(
+ "Enum 'E' already declares method with name 'res'.");
+ }
+ Future<void> test_bad_conflict_method_shadowsSuperDeclaration() async {
+ await indexTestUnit('''
+mixin M {
+ void res() {}
+}
+
+enum E with M {
+ v;
+ void foo() {
+ res();
+// start
+ print(0);
+// end
+ }
+}
+''');
+ _createRefactoringForStartEndComments();
+ return _assertConditionsError("Created method will shadow method 'M.res'.");
+ }
+
+ Future<void> test_bad_conflict_topLevel_willHideInheritedMemberUsage() async {
+ await indexTestUnit('''
+mixin M {
+ void res() {}
+}
+
+enum E with M {
+ v;
+ void foo() {
+ res();
+ }
+}
+
+void f() {
+// start
+ print(0);
+// end
+}
+''');
+ _createRefactoringForStartEndComments();
+ return _assertConditionsError(
+ "Created function will shadow method 'M.res'.");
+ }
+
+ Future<void> test_singleExpression_method() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void foo() {
+ int a = 1 + 2;
+ }
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+enum E {
+ v;
+ void foo() {
+ int a = res();
+ }
+
+ int res() => 1 + 2;
+}
+''');
+ }
+
+ Future<void> test_statements_method() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void foo() {
+// start
+ print(0);
+// end
+ }
+}
+''');
+ _createRefactoringForStartEndComments();
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+enum E {
+ v;
+ void foo() {
+// start
+ res();
+// end
+ }
+
+ void res() {
+ print(0);
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class ExtractMethodTest extends _ExtractMethodTest {
Future<void> test_bad_assignmentLeftHandSide() async {
await indexTestUnit('''
void f() {
@@ -2877,6 +2991,11 @@
Completer<int> newCompleter() => null;
''');
}
+}
+
+class _ExtractMethodTest extends RefactoringTest {
+ @override
+ late ExtractMethodRefactoringImpl refactoring;
Future _assertConditionsError(String message) async {
var status = await refactoring.checkAllConditions();
diff --git a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
index 35d678c..e775831 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
@@ -12,17 +12,86 @@
void main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(InlineMethodEnumTest);
defineReflectiveTests(InlineMethodTest);
});
}
@reflectiveTest
-class InlineMethodTest extends RefactoringTest {
- @override
- late InlineMethodRefactoringImpl refactoring;
- bool? deleteSource;
- bool? inlineAll;
+class InlineMethodEnumTest extends _InlineMethodTest {
+ Future<void> test_getter_classMember_instance() async {
+ await indexTestUnit(r'''
+enum E {
+ v;
+ final int f = 0;
+ int get result => f + 1;
+}
+void f(E e) {
+ print(e.result);
+}
+''');
+ _createRefactoring('result =>');
+ // validate change
+ return _assertSuccessfulRefactoring(r'''
+enum E {
+ v;
+ final int f = 0;
+}
+void f(E e) {
+ print(e.f + 1);
+}
+''');
+ }
+ Future<void> test_getter_classMember_static() async {
+ await indexTestUnit(r'''
+enum E {
+ v;
+ static int get result => 1 + 2;
+}
+void f() {
+ print(E.result);
+}
+''');
+ _createRefactoring('result =>');
+ // validate change
+ return _assertSuccessfulRefactoring(r'''
+enum E {
+ v;
+}
+void f() {
+ print(1 + 2);
+}
+''');
+ }
+
+ Future<void> test_method_singleStatement() async {
+ await indexTestUnit(r'''
+enum E {
+ v;
+ void test() {
+ print(0);
+ }
+ void foo() {
+ test();
+ }
+}
+''');
+ _createRefactoring('test() {');
+ // validate change
+ return _assertSuccessfulRefactoring(r'''
+enum E {
+ v;
+ void foo() {
+ print(0);
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class InlineMethodTest extends _InlineMethodTest {
Future<void> test_access_FunctionElement() async {
await indexTestUnit(r'''
test(a, b) {
@@ -1749,6 +1818,13 @@
var a = 42;
''');
}
+}
+
+class _InlineMethodTest extends RefactoringTest {
+ @override
+ late InlineMethodRefactoringImpl refactoring;
+ bool? deleteSource;
+ bool? inlineAll;
Future _assertConditionsError(String message) async {
var status = await refactoring.checkAllConditions();
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index 52fe0df..983df07 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -22,14 +22,12 @@
late MoveFileRefactoring refactoring;
Future<void> test_file_containing_imports_exports_parts() async {
- var pathA = convertPath('/home/test/000/1111/a.dart');
- var pathB = convertPath('/home/test/000/1111/b.dart');
- var pathC = convertPath('/home/test/000/1111/22/c.dart');
- testFile = convertPath('/home/test/000/1111/test.dart');
- addSource('/absolute/uri.dart', '');
- addSource(pathA, 'part of lib;');
- addSource(pathB, "import 'test.dart';");
- addSource(pathC, '');
+ final root = '/home/test/000/1111';
+ testFile = convertPath('$root/test.dart');
+ newFile('/absolute/uri.dart', content: '');
+ final fileA = newFile('$root/a.dart', content: 'part of lib;');
+ final fileB = newFile('$root/b.dart', content: "import 'test.dart';");
+ final fileC = newFile('$root/22/c.dart', content: '');
verifyNoTestUnitErrors = false;
await resolveTestCode('''
library lib;
@@ -43,9 +41,9 @@
// perform refactoring
_createRefactoring('/home/test/000/1111/22/new_name.dart');
await _assertSuccessfulRefactoring();
- assertNoFileChange(pathA);
- assertFileChangeResult(pathB, "import '22/new_name.dart';");
- assertNoFileChange(pathC);
+ assertNoFileChange(fileA.path);
+ assertFileChangeResult(fileB.path, "import '22/new_name.dart';");
+ assertNoFileChange(fileC.path);
assertFileChangeResult(testFile, '''
library lib;
import 'dart:math';
@@ -340,9 +338,34 @@
assertNoFileChange(testFile);
}
- @failingTest
Future<void> test_folder_inside_project() async {
- fail('Not yet implemented/tested');
+ final pathA = convertPath('/home/test/lib/old/a.dart');
+ final pathB = convertPath('/home/test/lib/old/b.dart');
+ final pathC = convertPath('/home/test/lib/old/nested/c.dart');
+ final pathD = convertPath('/home/test/lib/old/nested/d.dart');
+ testFile = convertPath('/home/test/lib/test.dart');
+ addSource(pathA, '');
+ addSource(pathB, '');
+ addSource(pathC, '');
+ addSource(pathD, '');
+ verifyNoTestUnitErrors = false;
+ await resolveTestCode('''
+import 'old/a.dart';
+import 'package:test/old/b.dart';
+import 'old/nested/c.dart';
+import 'package:test/old/nested/d.dart';
+''');
+ // Rename the whole 'old' folder to 'new''.
+ _createRefactoring('/home/test/lib/new', oldFile: '/home/test/lib/old');
+ await _assertSuccessfulRefactoring();
+ assertNoFileChange(pathA);
+ assertNoFileChange(pathB);
+ assertFileChangeResult(testFile, '''
+import 'new/a.dart';
+import 'package:test/new/b.dart';
+import 'new/nested/c.dart';
+import 'package:test/new/nested/d.dart';
+''');
}
Future<void> test_folder_outside_workspace_returns_failure() async {
@@ -517,8 +540,8 @@
// Allow passing an oldName for when we don't want to rename testSource,
// but otherwise fall back to testSource.fullname
oldFile = convertPath(oldFile ?? testFile);
- refactoring = MoveFileRefactoring(
- resourceProvider, refactoringWorkspace, testAnalysisResult, oldFile);
+ refactoring =
+ MoveFileRefactoring(resourceProvider, refactoringWorkspace, oldFile);
refactoring.newFile = convertPath(newFile);
}
}
diff --git a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
index 27a8207..524da05 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
@@ -11,12 +11,13 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(RenameClassMemberTest);
+ defineReflectiveTests(RenameClassMemberClassTest);
+ defineReflectiveTests(RenameClassMemberEnumTest);
});
}
@reflectiveTest
-class RenameClassMemberTest extends RenameRefactoringTest {
+class RenameClassMemberClassTest extends RenameRefactoringTest {
Future<void> test_checkFinalConditions_classNameConflict_sameClass() async {
await indexTestUnit('''
class NewName {
@@ -1047,3 +1048,573 @@
''');
}
}
+
+@reflectiveTest
+class RenameClassMemberEnumTest extends RenameRefactoringTest {
+ Future<void> test_checkFinalConditions_classNameConflict_sameClass() async {
+ await indexTestUnit('''
+enum NewName {
+ v;
+ void test() {}
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'NewName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Renamed method has the same name as the declaring enum 'NewName'.",
+ expectedContextSearch: 'test() {}');
+ }
+
+ Future<void> test_checkFinalConditions_classNameConflict_superClass() async {
+ await indexTestUnit('''
+class NewName {
+ void test() {} // 1
+}
+enum E implements NewName {
+ v;
+ void test() {} // 2
+}
+''');
+ createRenameRefactoringAtString('test() {} // 2');
+ // check status
+ refactoring.newName = 'NewName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Renamed method has the same name as the declaring class 'NewName'.",
+ expectedContextSearch: 'test() {} // 1');
+ }
+
+ Future<void> test_checkFinalConditions_hasMember_MethodElement() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ test() {}
+ newName() {} // existing
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Enum 'E' already declares method with name 'newName'.",
+ expectedContextSearch: 'newName() {} // existing');
+ }
+
+ Future<void> test_checkFinalConditions_OK_dropSuffix() async {
+ await indexTestUnit(r'''
+abstract class A {
+ void testOld();
+}
+enum E implements A {
+ v;
+ void testOld() {}
+}
+''');
+ createRenameRefactoringAtString('testOld() {}');
+ // check status
+ refactoring.newName = 'test';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatusOK(status);
+ }
+
+ Future<void> test_checkFinalConditions_publicToPrivate_used() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+}
+''');
+ await indexUnit('$testPackageLibPath/lib.dart', '''
+import 'test.dart';
+
+void f(E e) {
+ e.test();
+}
+''');
+ createRenameRefactoringAtString('test()');
+ // check status
+ refactoring.newName = '_newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Renamed method will be invisible in '${convertPath("lib/lib.dart")}'.");
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowed_byLocalFunction_inSameClass() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void f() {
+ newName() {}
+ test(); // marker
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Usage of renamed method will be shadowed by function 'newName'.",
+ expectedContextSearch: 'test(); // marker');
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowed_byLocalVariable_inSameClass() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void f() {
+ var newName;
+ test(); // marker
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Usage of renamed method will be shadowed by local variable 'newName'.",
+ expectedContextSearch: 'test(); // marker');
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowed_byLocalVariable_OK_qualifiedReference() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void f() {
+ var newName;
+ this.test(); // marker
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatusOK(status);
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowed_byLocalVariable_OK_renamedNotUsed() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void f() {
+ var newName;
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatusOK(status);
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowed_byParameter_inSameClass() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void f(newName) {
+ test(); // marker
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Usage of renamed method will be shadowed by parameter 'newName'.",
+ expectedContextSearch: 'test(); // marker');
+ }
+
+ Future<void> test_checkFinalConditions_shadowsSuper_MethodElement() async {
+ await indexTestUnit('''
+mixin M {
+ void newName() {}
+}
+enum E with M {
+ v;
+ void test() {}
+ void f() {
+ newName();
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage: "Renamed method will shadow method 'M.newName'.",
+ expectedContextSearch: 'newName() {}');
+ }
+
+ Future<void>
+ test_checkFinalConditions_shadowsSuper_MethodElement_otherLib() async {
+ var libCode = r'''
+mixin M {
+ void newName() {}
+}
+''';
+ await indexUnit('$testPackageLibPath/lib.dart', libCode);
+ await indexTestUnit('''
+import 'lib.dart';
+enum E with M {
+ v;
+ void test() {}
+ void f() {
+ newName();
+ }
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkFinalConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage: "Renamed method will shadow method 'M.newName'.",
+ expectedContextRange:
+ SourceRange(libCode.indexOf('newName() {}'), 'newName'.length));
+ }
+
+ Future<void> test_checkInitialConditions_operator() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ operator -() => this;
+}
+''');
+ createRenameRefactoringAtString('-()');
+ // check status
+ refactoring.newName = 'newName';
+ var status = await refactoring.checkInitialConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.FATAL);
+ }
+
+ Future<void> test_checkNewName_FieldElement() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ final int test = 0;
+}
+''');
+ createRenameRefactoringAtString('test = 0;');
+ // OK
+ refactoring.newName = 'newName';
+ assertRefactoringStatusOK(refactoring.checkNewName());
+ }
+
+ Future<void> test_checkNewName_MethodElement() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+}
+''');
+ createRenameRefactoringAtString('test() {}');
+ // empty
+ refactoring.newName = '';
+ assertRefactoringStatus(
+ refactoring.checkNewName(), RefactoringProblemSeverity.FATAL,
+ expectedMessage: 'Method name must not be empty.');
+ // same
+ refactoring.newName = 'test';
+ assertRefactoringStatus(
+ refactoring.checkNewName(), RefactoringProblemSeverity.FATAL,
+ expectedMessage:
+ 'The new name must be different than the current name.');
+ // OK
+ refactoring.newName = 'newName';
+ assertRefactoringStatusOK(refactoring.checkNewName());
+ }
+
+ Future<void> test_createChange_FieldElement() async {
+ verifyNoTestUnitErrors = false;
+ await indexTestUnit('''
+enum E {
+ v;
+ final int test = 0;
+ void f() {
+ test;
+ test = 1;
+ test += 2;
+ }
+}
+void f(E e) {
+ e.test;
+ e.test = 1;
+ e.test += 2;
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test = 0;');
+ expect(refactoring.refactoringName, 'Rename Field');
+ expect(refactoring.elementKindName, 'field');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E {
+ v;
+ final int newName = 0;
+ void f() {
+ newName;
+ newName = 1;
+ newName += 2;
+ }
+}
+void f(E e) {
+ e.newName;
+ e.newName = 1;
+ e.newName += 2;
+}
+''');
+ }
+
+ Future<void>
+ test_createChange_FieldElement_constructorFieldInitializer() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ final int test;
+ const E() : test = 5;
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test;');
+ expect(refactoring.refactoringName, 'Rename Field');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E {
+ v;
+ final int newName;
+ const E() : newName = 5;
+}
+''');
+ }
+
+ Future<void> test_createChange_FieldElement_fieldFormalParameter() async {
+ await indexTestUnit('''
+enum E {
+ v(0);
+ final int test;
+ const E(this.test);
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test;');
+ expect(refactoring.refactoringName, 'Rename Field');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E {
+ v(0);
+ final int newName;
+ const E(this.newName);
+}
+''');
+ }
+
+ Future<void> test_createChange_MethodElement() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ void test() {}
+ void foo() {
+ test();
+ test;
+ }
+}
+
+void f(E e) {
+ e.test();
+ e.test;
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test() {}');
+ expect(refactoring.refactoringName, 'Rename Method');
+ expect(refactoring.elementKindName, 'method');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E {
+ v;
+ void newName() {}
+ void foo() {
+ newName();
+ newName;
+ }
+}
+
+void f(E e) {
+ e.newName();
+ e.newName;
+}
+''');
+ }
+
+ Future<void> test_createChange_MethodElement_fromInterface() async {
+ await indexTestUnit('''
+class A {
+ void test() {} // A
+}
+
+enum E implements A {
+ v;
+ void test() {}
+ void foo() {
+ test();
+ }
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test() {} // A');
+ expect(refactoring.refactoringName, 'Rename Method');
+ expect(refactoring.elementKindName, 'method');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+class A {
+ void newName() {} // A
+}
+
+enum E implements A {
+ v;
+ void newName() {}
+ void foo() {
+ newName();
+ }
+}
+''');
+ }
+
+ Future<void> test_createChange_MethodElement_fromMixin() async {
+ await indexTestUnit('''
+mixin M {
+ void test() {} // M
+}
+
+enum E with M {
+ v;
+ void test() {}
+ void foo() {
+ test();
+ }
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test() {} // M');
+ expect(refactoring.refactoringName, 'Rename Method');
+ expect(refactoring.elementKindName, 'method');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+mixin M {
+ void newName() {} // M
+}
+
+enum E with M {
+ v;
+ void newName() {}
+ void foo() {
+ newName();
+ }
+}
+''');
+ }
+
+ Future<void> test_createChange_PropertyAccessorElement() async {
+ await indexTestUnit('''
+enum E {
+ v;
+ int get test => 0;
+ set test(int _) {}
+ void f() {
+ test;
+ test = 0;
+ }
+}
+void f(E e) {
+ e.test;
+ e.test = 1;
+ e.test += 2;
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test => 0;');
+ expect(refactoring.refactoringName, 'Rename Field');
+ expect(refactoring.oldName, 'test');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E {
+ v;
+ int get newName => 0;
+ set newName(int _) {}
+ void f() {
+ newName;
+ newName = 0;
+ }
+}
+void f(E e) {
+ e.newName;
+ e.newName = 1;
+ e.newName += 2;
+}
+''');
+ }
+
+ Future<void> test_createChange_TypeParameterElement() async {
+ await indexTestUnit('''
+enum E<Test> {
+ v;
+ final Test? field = null;
+ final List<Test> items = const [];
+ Test method(Test a) => a;
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('Test> {');
+ expect(refactoring.refactoringName, 'Rename Type Parameter');
+ expect(refactoring.elementKindName, 'type parameter');
+ expect(refactoring.oldName, 'Test');
+ refactoring.newName = 'NewName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+enum E<NewName> {
+ v;
+ final NewName? field = null;
+ final List<NewName> items = const [];
+ NewName method(NewName a) => a;
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
index 79d6fe7..9a40d78 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
@@ -12,12 +12,13 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(RenameConstructorTest);
+ defineReflectiveTests(RenameConstructorClassTest);
+ defineReflectiveTests(RenameConstructorEnumTest);
});
}
@reflectiveTest
-class RenameConstructorTest extends RenameRefactoringTest {
+class RenameConstructorClassTest extends _RenameConstructorTest {
Future<void> test_checkInitialConditions_inSDK() async {
await indexTestUnit('''
main() {
@@ -285,7 +286,287 @@
RenameRefactoring.create(workspace, testAnalysisResult, null);
expect(refactoring, isNull);
}
+}
+@reflectiveTest
+class RenameConstructorEnumTest extends _RenameConstructorTest {
+ Future<void> test_checkNewName() async {
+ await indexTestUnit('''
+enum E {
+ v.test();
+ const E.test(); // 0
+}
+''');
+ createRenameRefactoringAtString('test(); // 0');
+ expect(refactoring.oldName, 'test');
+ // same
+ refactoring.newName = 'test';
+ assertRefactoringStatus(
+ refactoring.checkNewName(), RefactoringProblemSeverity.FATAL,
+ expectedMessage:
+ 'The new name must be different than the current name.');
+ // empty
+ refactoring.newName = '';
+ assertRefactoringStatusOK(refactoring.checkNewName());
+ // OK
+ refactoring.newName = 'newName';
+ assertRefactoringStatusOK(refactoring.checkNewName());
+ }
+
+ Future<void> test_checkNewName_hasMember_constructor() async {
+ await indexTestUnit('''
+enum E {
+ v.test();
+ const E.test(); // 0
+ const E.newName(); // existing
+}
+''');
+ _createConstructorDeclarationRefactoring('test(); // 0');
+ // check status
+ refactoring.newName = 'newName';
+ var status = refactoring.checkNewName();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Class 'E' already declares constructor with name 'newName'.",
+ expectedContextSearch: 'newName(); // existing');
+ }
+
+ Future<void> test_checkNewName_hasMember_method() async {
+ await indexTestUnit('''
+enum E {
+ v.test();
+ const E.test(); // 0
+ void newName() {} // existing
+}
+''');
+ _createConstructorDeclarationRefactoring('test(); // 0');
+ // check status
+ refactoring.newName = 'newName';
+ var status = refactoring.checkNewName();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+ expectedMessage:
+ "Class 'E' already declares method with name 'newName'.",
+ expectedContextSearch: 'newName() {} // existing');
+ }
+
+ Future<void> test_createChange_add() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3, v4.other();
+ const E(); // 0
+ const E.other() : this();
+}
+''');
+ // configure refactoring
+ _createConstructorDeclarationRefactoring('(); // 0');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName(), v4.other();
+ const E.newName(); // 0
+ const E.other() : this.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_add_toSynthetic_hasConstructor() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3;
+
+ factory E.other() => throw 0;
+}
+''');
+ // configure refactoring
+ _createEnumConstantRefactoring('v1()');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName();
+
+ factory E.other() => throw 0;
+
+ const E.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_add_toSynthetic_hasField() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3;
+
+ final int foo = 0;
+}
+''');
+ // configure refactoring
+ _createEnumConstantRefactoring('v1()');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName();
+
+ final int foo = 0;
+
+ const E.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_add_toSynthetic_hasMethod() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3;
+
+ void foo() {}
+}
+''');
+ // configure refactoring
+ _createEnumConstantRefactoring('v1()');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName();
+
+ const E.newName();
+
+ void foo() {}
+}
+''');
+ }
+
+ Future<void> test_createChange_add_toSynthetic_hasSemicolon() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3;
+}
+''');
+ // configure refactoring
+ _createEnumConstantRefactoring('v1()');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName();
+
+ const E.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_add_toSynthetic_noSemicolon() async {
+ await indexTestUnit('''
+/// [E.new]
+enum E {
+ v1(), v2.new(), v3
+}
+''');
+ // configure refactoring
+ _createEnumConstantRefactoring('v1()');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, '');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.newName(), v3.newName();
+
+ const E.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_change() async {
+ await indexTestUnit('''
+/// [E.test]
+enum E {
+ v1.test(), v2.other();
+ const E.test(); // 0
+ const E.other() : this.test();
+}
+''');
+ // configure refactoring
+ _createConstructorDeclarationRefactoring('test(); // 0');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, 'test');
+ // validate change
+ refactoring.newName = 'newName';
+ return assertSuccessfulRefactoring('''
+/// [E.newName]
+enum E {
+ v1.newName(), v2.other();
+ const E.newName(); // 0
+ const E.other() : this.newName();
+}
+''');
+ }
+
+ Future<void> test_createChange_remove() async {
+ await indexTestUnit('''
+/// [E]
+enum E {
+ v1.test(), v2.other();
+ const E.test(); // 0
+ const E.other() : this.test();
+}
+''');
+ // configure refactoring
+ _createConstructorDeclarationRefactoring('test(); // 0');
+ expect(refactoring.refactoringName, 'Rename Constructor');
+ expect(refactoring.elementKindName, 'constructor');
+ expect(refactoring.oldName, 'test');
+ // validate change
+ refactoring.newName = '';
+ return assertSuccessfulRefactoring('''
+/// [E]
+enum E {
+ v1(), v2.other();
+ const E(); // 0
+ const E.other() : this();
+}
+''');
+ }
+
+ void _createEnumConstantRefactoring(String search) {
+ var enumConstant = findNode.enumConstantDeclaration(search);
+ var element = enumConstant.constructorElement;
+ createRenameRefactoringForElement(element);
+ }
+}
+
+class _RenameConstructorTest extends RenameRefactoringTest {
void _createConstructorDeclarationRefactoring(String search) {
var element = findNode.constructor(search).declaredElement;
createRenameRefactoringForElement(element);
diff --git a/pkg/analysis_server/test/services/search/hierarchy_test.dart b/pkg/analysis_server/test/services/search/hierarchy_test.dart
index 9ac31f4..17454ea 100644
--- a/pkg/analysis_server/test/services/search/hierarchy_test.dart
+++ b/pkg/analysis_server/test/services/search/hierarchy_test.dart
@@ -391,99 +391,6 @@
}
}
- Future<void> test_getSuperClasses() async {
- await _indexTestUnit('''
-class A {}
-class B extends A {}
-class C extends B {}
-class D extends B implements A {}
-class M {}
-class E extends A with M {}
-class F implements A {}
-''');
- var classA = findElement.class_('A');
- var classB = findElement.class_('B');
- var classC = findElement.class_('C');
- var classD = findElement.class_('D');
- var classE = findElement.class_('E');
- var classF = findElement.class_('F');
- var objectElement = classA.supertype!.element;
- // Object
- {
- var supers = getSuperClasses(objectElement);
- expect(supers, isEmpty);
- }
- // A
- {
- var supers = getSuperClasses(classA);
- expect(supers, unorderedEquals([objectElement]));
- }
- // B
- {
- var supers = getSuperClasses(classB);
- expect(supers, unorderedEquals([objectElement, classA]));
- }
- // C
- {
- var supers = getSuperClasses(classC);
- expect(supers, unorderedEquals([objectElement, classA, classB]));
- }
- // D
- {
- var supers = getSuperClasses(classD);
- expect(supers, unorderedEquals([objectElement, classA, classB]));
- }
- // E
- {
- var supers = getSuperClasses(classE);
- expect(supers, unorderedEquals([objectElement, classA]));
- }
- // F
- {
- var supers = getSuperClasses(classF);
- expect(supers, unorderedEquals([objectElement, classA]));
- }
- }
-
- Future<void> test_getSuperClasses_superclassConstraints() async {
- await _indexTestUnit('''
-class A {}
-class B extends A {}
-class C {}
-
-mixin M1 on A {}
-mixin M2 on B {}
-mixin M3 on M1 {}
-mixin M4 on M2 {}
-mixin M5 on A, C {}
-''');
- var a = findElement.class_('A');
- var b = findElement.class_('B');
- var c = findElement.class_('C');
- var m1 = findElement.mixin('M1');
- var m2 = findElement.mixin('M2');
- var m3 = findElement.mixin('M3');
- var m4 = findElement.mixin('M4');
- var m5 = findElement.mixin('M5');
- var object = a.supertype!.element;
-
- _assertSuperClasses(object, []);
- _assertSuperClasses(a, [object]);
- _assertSuperClasses(b, [object, a]);
- _assertSuperClasses(c, [object]);
-
- _assertSuperClasses(m1, [object, a]);
- _assertSuperClasses(m2, [object, a, b]);
- _assertSuperClasses(m3, [object, a, m1]);
- _assertSuperClasses(m4, [object, a, b, m2]);
- _assertSuperClasses(m5, [object, a, c]);
- }
-
- void _assertSuperClasses(ClassElement element, List<ClassElement> expected) {
- var supers = getSuperClasses(element);
- expect(supers, unorderedEquals(expected));
- }
-
Future<void> _indexTestUnit(String code) async {
await resolveTestCode(code);
}
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 43637ae..0097edb 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -61,7 +61,7 @@
return SearchEngineImpl(allDrivers);
}
- Future<void> test_membersOfSubtypes_hasMembers() async {
+ Future<void> test_membersOfSubtypes_classByClass_hasMembers() async {
newFile('$testPackageLibPath/a.dart', content: '''
class A {
void a() {}
@@ -91,6 +91,40 @@
expect(members, unorderedEquals(['a', 'b']));
}
+ Future<void> test_membersOfSubtypes_enum_implements_hasMembers() async {
+ await resolveTestCode('''
+class A {
+ void foo() {}
+}
+
+enum E implements A {
+ v;
+ void foo() {}
+}
+''');
+
+ var A = findElement.class_('A');
+ var members = await searchEngine.membersOfSubtypes(A);
+ expect(members, unorderedEquals(['foo']));
+ }
+
+ Future<void> test_membersOfSubtypes_enum_with_hasMembers() async {
+ await resolveTestCode('''
+mixin M {
+ void foo() {}
+}
+
+enum E with M {
+ v;
+ void foo() {}
+}
+''');
+
+ var M = findElement.mixin('M');
+ var members = await searchEngine.membersOfSubtypes(M);
+ expect(members, unorderedEquals(['foo']));
+ }
+
Future<void> test_membersOfSubtypes_noMembers() async {
newFile('$testPackageLibPath/a.dart', content: '''
class A {
@@ -344,6 +378,68 @@
assertHasOne(a, 'a');
}
+ Future<void> test_searchReferences_enum_constructor_named() async {
+ var code = '''
+enum E {
+ v.named(); // 1
+ const E.named();
+}
+''';
+ await resolveTestCode(code);
+
+ var element = findElement.constructor('named');
+ var matches = await searchEngine.searchReferences(element);
+ expect(
+ matches,
+ unorderedEquals([
+ predicate((SearchMatch m) {
+ return m.kind == MatchKind.INVOCATION &&
+ identical(m.element, findElement.field('v')) &&
+ m.sourceRange.offset == code.indexOf('.named(); // 1') &&
+ m.sourceRange.length == '.named'.length;
+ }),
+ ]),
+ );
+ }
+
+ Future<void> test_searchReferences_enum_constructor_unnamed() async {
+ var code = '''
+enum E {
+ v1, // 1
+ v2(), // 2
+ v3.new(), // 3
+}
+''';
+ await resolveTestCode(code);
+
+ var element = findElement.unnamedConstructor('E');
+ var matches = await searchEngine.searchReferences(element);
+ expect(
+ matches,
+ unorderedEquals([
+ predicate((SearchMatch m) {
+ return m.kind ==
+ MatchKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS &&
+ identical(m.element, findElement.field('v1')) &&
+ m.sourceRange.offset == code.indexOf(', // 1') &&
+ m.sourceRange.length == 0;
+ }),
+ predicate((SearchMatch m) {
+ return m.kind == MatchKind.INVOCATION &&
+ identical(m.element, findElement.field('v2')) &&
+ m.sourceRange.offset == code.indexOf('(), // 2') &&
+ m.sourceRange.length == 0;
+ }),
+ predicate((SearchMatch m) {
+ return m.kind == MatchKind.INVOCATION &&
+ identical(m.element, findElement.field('v3')) &&
+ m.sourceRange.offset == code.indexOf('.new(), // 3') &&
+ m.sourceRange.length == '.new'.length;
+ }),
+ ]),
+ );
+ }
+
Future<void>
test_searchReferences_parameter_ofConstructor_super_named() async {
var code = '''
@@ -374,6 +470,32 @@
);
}
+ Future<void>
+ test_searchReferences_topFunction_parameter_optionalNamed_anywhere() async {
+ var code = '''
+void foo(int a, int b, {int? test}) {}
+
+void g() {
+ foo(1, test: 0, 2);
+}
+''';
+ await resolveTestCode(code);
+
+ var element = findElement.parameter('test');
+ var matches = await searchEngine.searchReferences(element);
+ expect(
+ matches,
+ unorderedEquals([
+ predicate((SearchMatch m) {
+ return m.kind == MatchKind.REFERENCE &&
+ identical(m.element, findElement.topFunction('g')) &&
+ m.sourceRange.offset == code.indexOf('test: 0') &&
+ m.sourceRange.length == 'test'.length;
+ }),
+ ]),
+ );
+ }
+
Future<void> test_searchTopLevelDeclarations() async {
newFile('$testPackageLibPath/a.dart', content: '''
class A {}
diff --git a/pkg/analysis_server/test/services/snippets/dart/flutter_snippet_producers_test.dart b/pkg/analysis_server/test/services/snippets/dart/flutter_snippet_producers_test.dart
new file mode 100644
index 0000000..6edf13b
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/dart/flutter_snippet_producers_test.dart
@@ -0,0 +1,302 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/snippets/dart/flutter_snippet_producers.dart';
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../abstract_single_unit.dart';
+import 'test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FlutterStatefulWidgetSnippetProducerTest);
+ defineReflectiveTests(
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducerTest);
+ defineReflectiveTests(FlutterStatelessWidgetSnippetProducerTest);
+ });
+}
+
+abstract class FlutterSnippetProducerTest extends AbstractSingleUnitTest {
+ SnippetProducerGenerator get generator;
+ String get label;
+ String get prefix;
+
+ @override
+ bool get verifyNoTestUnitErrors => false;
+
+ Future<void> expectNotValidSnippet(
+ String code,
+ ) async {
+ await resolveTestCode(withoutMarkers(code));
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: offsetFromMarker(code),
+ );
+
+ final producer = generator(request);
+ expect(await producer.isValid(), isFalse);
+ }
+
+ Future<Snippet> expectValidSnippet(String code) async {
+ await resolveTestCode(withoutMarkers(code));
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: offsetFromMarker(code),
+ );
+
+ final producer = generator(request);
+ expect(await producer.isValid(), isTrue);
+ return producer.compute();
+ }
+
+ /// Checks snippets can produce edits where the imports and snippet will be
+ /// inserted at the same location.
+ ///
+ /// For example, when a document is completely empty besides the snippet
+ /// prefix, the imports will be inserted at offset 0 and the snippet will
+ /// replace from 0 to the end of the typed prefix.
+ Future<void> test_valid_importsAndEditsOverlap() async {
+ writeTestPackageConfig(flutter: true);
+
+ final snippet = await expectValidSnippet('$prefix^');
+ expect(snippet.prefix, prefix);
+
+ // Main edits replace $prefix.length characters starting at $prefix
+ final mainEdit = snippet.change.edits[0].edits[0];
+ expect(mainEdit.offset, testCode.indexOf(prefix));
+ expect(mainEdit.length, prefix.length);
+
+ // Imports inserted at start of doc (0)
+ final importEdit = snippet.change.edits[0].edits[1];
+ expect(importEdit.offset, 0);
+ expect(importEdit.length, 0);
+ }
+
+ Future<void> test_valid_suffixReplacement() async {
+ writeTestPackageConfig(flutter: true);
+
+ final snippet = await expectValidSnippet('''
+class A {}
+
+$prefix^
+''');
+ expect(snippet.prefix, prefix);
+
+ // Main edits replace $prefix.length characters starting at $prefix
+ final mainEdit = snippet.change.edits[0].edits[0];
+ expect(mainEdit.offset, testCode.indexOf(prefix));
+ expect(mainEdit.length, prefix.length);
+
+ // Imports inserted at start of doc (0)
+ final importEdit = snippet.change.edits[0].edits[1];
+ expect(importEdit.offset, 0);
+ expect(importEdit.length, 0);
+ }
+}
+
+@reflectiveTest
+class FlutterStatefulWidgetSnippetProducerTest
+ extends FlutterSnippetProducerTest {
+ @override
+ final generator = FlutterStatefulWidgetSnippetProducer.newInstance;
+
+ @override
+ String get label => FlutterStatefulWidgetSnippetProducer.label;
+
+ @override
+ String get prefix => FlutterStatefulWidgetSnippetProducer.prefix;
+
+ Future<void> test_notValid_notFlutterProject() async {
+ writeTestPackageConfig();
+
+ await expectNotValidSnippet('^');
+ }
+
+ Future<void> test_valid() async {
+ writeTestPackageConfig(flutter: true);
+
+ final snippet = await expectValidSnippet('^');
+ expect(snippet.prefix, 'stful');
+ expect(snippet.label, 'Flutter Stateful Widget');
+ var code = '';
+ expect(snippet.change.edits, hasLength(1));
+ snippet.change.edits
+ .forEach((edit) => code = SourceEdit.applySequence(code, edit.edits));
+ expect(code, '''
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+
+class MyWidget extends StatefulWidget {
+ const MyWidget({Key? key}) : super(key: key);
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+
+ }
+}''');
+ expect(snippet.change.selection!.file, testFile);
+ expect(snippet.change.selection!.offset, 363);
+ expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
+ {
+ 'positions': [
+ {'file': testFile, 'offset': 110},
+ {'file': testFile, 'offset': 152},
+ {'file': testFile, 'offset': 213},
+ {'file': testFile, 'offset': 241},
+ {'file': testFile, 'offset': 268},
+ {'file': testFile, 'offset': 296},
+ ],
+ 'length': 8,
+ 'suggestions': []
+ }
+ ]);
+ }
+}
+
+@reflectiveTest
+class FlutterStatefulWidgetWithAnimationControllerSnippetProducerTest
+ extends FlutterSnippetProducerTest {
+ @override
+ final generator =
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer.newInstance;
+
+ @override
+ String get label =>
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer.label;
+
+ @override
+ String get prefix =>
+ FlutterStatefulWidgetWithAnimationControllerSnippetProducer.prefix;
+
+ Future<void> test_notValid_notFlutterProject() async {
+ writeTestPackageConfig();
+
+ await expectNotValidSnippet('^');
+ }
+
+ Future<void> test_valid() async {
+ writeTestPackageConfig(flutter: true);
+
+ final snippet = await expectValidSnippet('^');
+ expect(snippet.prefix, 'stanim');
+ expect(snippet.label, 'Flutter Widget with AnimationController');
+ var code = '';
+ expect(snippet.change.edits, hasLength(1));
+ snippet.change.edits
+ .forEach((edit) => code = SourceEdit.applySequence(code, edit.edits));
+ expect(code, '''
+import 'package:flutter/src/animation/animation_controller.dart';
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+import 'package:flutter/src/widgets/ticker_provider.dart';
+
+class MyWidget extends StatefulWidget {
+ const MyWidget({Key? key}) : super(key: key);
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget>
+ with SingleTickerProviderStateMixin {
+ late AnimationController _controller;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = AnimationController(vsync: this);
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _controller.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+
+ }
+}''');
+ expect(snippet.change.selection!.file, testFile);
+ expect(snippet.change.selection!.offset, 766);
+ expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
+ {
+ 'positions': [
+ {'file': testFile, 'offset': 235},
+ {'file': testFile, 'offset': 277},
+ {'file': testFile, 'offset': 338},
+ {'file': testFile, 'offset': 366},
+ {'file': testFile, 'offset': 393},
+ {'file': testFile, 'offset': 421},
+ ],
+ 'length': 8,
+ 'suggestions': []
+ }
+ ]);
+ }
+}
+
+@reflectiveTest
+class FlutterStatelessWidgetSnippetProducerTest
+ extends FlutterSnippetProducerTest {
+ @override
+ final generator = FlutterStatelessWidgetSnippetProducer.newInstance;
+
+ @override
+ String get label => FlutterStatelessWidgetSnippetProducer.label;
+
+ @override
+ String get prefix => FlutterStatelessWidgetSnippetProducer.prefix;
+
+ Future<void> test_notValid_notFlutterProject() async {
+ writeTestPackageConfig();
+
+ await expectNotValidSnippet('^');
+ }
+
+ Future<void> test_valid() async {
+ writeTestPackageConfig(flutter: true);
+
+ final snippet = await expectValidSnippet('^');
+ expect(snippet.prefix, 'stless');
+ expect(snippet.label, 'Flutter Stateless Widget');
+ var code = '';
+ expect(snippet.change.edits, hasLength(1));
+ snippet.change.edits
+ .forEach((edit) => code = SourceEdit.applySequence(code, edit.edits));
+ expect(code, '''
+import 'package:flutter/src/foundation/key.dart';
+import 'package:flutter/src/widgets/framework.dart';
+
+class MyWidget extends StatelessWidget {
+ const MyWidget({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+
+ }
+}''');
+ expect(snippet.change.selection!.file, testFile);
+ expect(snippet.change.selection!.offset, 249);
+ expect(snippet.change.linkedEditGroups.map((group) => group.toJson()), [
+ {
+ 'positions': [
+ {'file': testFile, 'offset': 110},
+ {'file': testFile, 'offset': 153},
+ ],
+ 'length': 8,
+ 'suggestions': []
+ }
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/snippets/dart/snippet_manager_test.dart b/pkg/analysis_server/test/services/snippets/dart/snippet_manager_test.dart
new file mode 100644
index 0000000..622d84f
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/dart/snippet_manager_test.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../abstract_single_unit.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SnippetManagerTest);
+ });
+}
+
+@reflectiveTest
+class SnippetManagerTest extends AbstractSingleUnitTest {
+ Future<void> test_notValidProducers() async {
+ await resolveTestCode('');
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: 0,
+ );
+
+ final manager = _TestDartSnippetManager({
+ SnippetContext.atTopLevel: [_NotValidSnippetProducer.newInstance],
+ });
+ final results = await manager.computeSnippets(request);
+ expect(results, isEmpty);
+ }
+
+ Future<void> test_onlyCreatesForContext() async {
+ await resolveTestCode('');
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: 0,
+ );
+
+ final manager = _TestDartSnippetManager({
+ SnippetContext.atTopLevel: [_ValidSnippetProducer.newInstance],
+ SnippetContext.inClass: [
+ (context) => throw 'Tried to create producer for wrong context',
+ ]
+ });
+ final results = await manager.computeSnippets(request);
+ expect(results, hasLength(1));
+ }
+
+ Future<void> test_validProducers() async {
+ await resolveTestCode('');
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: 0,
+ );
+
+ final manager = _TestDartSnippetManager({
+ SnippetContext.atTopLevel: [_ValidSnippetProducer.newInstance],
+ });
+ final results = await manager.computeSnippets(request);
+ expect(results, hasLength(1));
+ final snippet = results.single;
+ expect(snippet.prefix, 'mysnip');
+ expect(snippet.label, 'My Test Snippet');
+ }
+}
+
+/// A snippet producer that always returns `false` from [isValid] and throws
+/// if [compute] is called.
+class _NotValidSnippetProducer extends SnippetProducer {
+ _NotValidSnippetProducer(DartSnippetRequest request) : super(request);
+
+ @override
+ Future<Snippet> compute() {
+ throw UnsupportedError(
+ 'compute should not be called for a producer '
+ 'that returned false from isValid',
+ );
+ }
+
+ @override
+ Future<bool> isValid() async => false;
+
+ static _NotValidSnippetProducer newInstance(DartSnippetRequest request) =>
+ _NotValidSnippetProducer(request);
+}
+
+class _TestDartSnippetManager extends DartSnippetManager {
+ @override
+ final Map<SnippetContext, List<SnippetProducerGenerator>> producerGenerators;
+
+ _TestDartSnippetManager(this.producerGenerators);
+}
+
+/// A snippet producer that always returns `true` from [isValid] and a simple
+/// snippet from [compute].
+class _ValidSnippetProducer extends SnippetProducer {
+ _ValidSnippetProducer(DartSnippetRequest request) : super(request);
+
+ @override
+ Future<Snippet> compute() async {
+ return Snippet(
+ 'mysnip',
+ 'My Test Snippet',
+ 'This is a test snippet',
+ SourceChange('message'),
+ );
+ }
+
+ @override
+ Future<bool> isValid() async => true;
+
+ static _ValidSnippetProducer newInstance(DartSnippetRequest request) =>
+ _ValidSnippetProducer(request);
+}
diff --git a/pkg/analysis_server/test/services/snippets/dart/snippet_request_test.dart b/pkg/analysis_server/test/services/snippets/dart/snippet_request_test.dart
new file mode 100644
index 0000000..fd6a240
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/dart/snippet_request_test.dart
@@ -0,0 +1,495 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
+import 'package:analyzer/src/test_utilities/platform.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../abstract_single_unit.dart';
+import 'test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SnippetRequestTest);
+ });
+}
+
+@reflectiveTest
+class SnippetRequestTest extends AbstractSingleUnitTest {
+ SnippetRequestTest() {
+ verifyNoTestUnitErrors = false;
+ }
+
+ Future<void> test_expression_constructor() async {
+ await testRequest(r'''
+final a = new [[^]]
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_expression_constructorName() async {
+ await testRequest(r'''
+class A {
+ A.foo();
+}
+final a = new A.[[fo^]]
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_inAnnotation() async {
+ await testRequest(r'''
+@[[depre^]]
+class A {}
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_inBlock_forBody() async {
+ await testRequest(r'''
+foo() {
+ for (var i = 0; i < 10; i++) {
+ [[^]]
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inClass_atEnd() async {
+ await testRequest(r'''
+class A {
+ foo() {}
+
+ [[^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_atEnd_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {}
+
+ [[mysnip^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_atStart() async {
+ await testRequest(r'''
+class A {
+ [[^]]
+
+ foo() {}
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_atStart_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ [[mysnip^]]
+
+ foo() {}
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_betweenMembers() async {
+ await testRequest(r'''
+class A {
+ foo() {}
+
+ [[^]]
+
+ bar() {}
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_betweenMembers_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {}
+
+ [[mysnip^]]
+
+ bar() {}
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_empty() async {
+ await testRequest(r'''
+class A {
+ [[^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inClass_empty_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ [[mysnip^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inComment_dartDoc() async {
+ await testRequest(r'''
+/// [[^]]
+class A {}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_dartDoc_reference_member() async {
+ await testRequest(r'''
+class A {
+ /// [ [[A^]] ]
+ foo() {}
+}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_dartDoc_reference_topLevel() async {
+ await testRequest(r'''
+/// [ [[A^]] ]
+class A {}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_multiline_member() async {
+ await testRequest(r'''
+class A {
+ /*
+ * [[^]]
+ */
+ foo() {}
+}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_multiline_topLevel() async {
+ await testRequest(r'''
+/*
+ * [[^]]
+ */
+class A {}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_singleLine_member() async {
+ await testRequest(r'''
+class A {
+ // [[^]]
+ foo () {}
+}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inComment_singleLine_topLevel() async {
+ await testRequest(r'''
+// [[^]]
+class A {}
+''', SnippetContext.inComment);
+ }
+
+ Future<void> test_inExpression_functionCall() async {
+ await testRequest(r'''
+foo() {
+ print([[^]]
+}
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_inExtension() async {
+ await testRequest(r'''
+extension on Object {
+ [[^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inFunction_atEnd() async {
+ await testRequest(r'''
+foo() {
+ var a = 1;
+ [[^]]
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_atEnd_partialIdentifier() async {
+ await testRequest(r'''
+foo() {
+ var a = 1;
+ [[mysnip^]]
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_atStart() async {
+ await testRequest(r'''
+foo() {
+ [[^]]
+ var a = 1;
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_atStart_partialIdentifier() async {
+ await testRequest(r'''
+foo() {
+ [[mysnip^]]
+ var a = 1;
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_betweenStatements() async {
+ await testRequest(r'''
+foo() {
+ var a = 1;
+ [[^]]
+ var b = 1;
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_betweenStatements_partialIdentifier() async {
+ await testRequest(r'''
+foo() {
+ var a = 1;
+ [[mysnip^]]
+ var b = 1;
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_empty() async {
+ await testRequest(r'''
+foo() {
+ [[^]]
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inFunction_empty_partialIdentifier() async {
+ await testRequest(r'''
+foo() {
+ [[mysnip^]]
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_atEnd() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ var a = 1;
+ [[^]]
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_atEnd_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ var a = 1;
+ [[mysnip^]]
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_atStart() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ [[^]]
+ var a = 1;
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_atStart_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ [[mysnip^]]
+ var a = 1;
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_betweenStatements() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ var a = 1;
+ [[^]]
+ var b = 1;
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_betweenStatements_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ var a = 1;
+ [[mysnip^]]
+ var b = 1;
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_empty() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ [[^]]
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMethod_empty_partialIdentifier() async {
+ await testRequest(r'''
+class A {
+ foo() {
+ [[mysnip^]]
+ }
+}
+''', SnippetContext.inBlock);
+ }
+
+ Future<void> test_inMixin() async {
+ await testRequest(r'''
+mixin A {
+ [[^]]
+}
+''', SnippetContext.inClass);
+ }
+
+ Future<void> test_inStatement_forCondition() async {
+ await testRequest(r'''
+foo() {
+ for (var i = [[^]]
+}
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_inStatement_variableDeclaration() async {
+ await testRequest(r'''
+foo() {
+ var a = [[^]]
+}
+''', SnippetContext.inExpressionOrStatement);
+ }
+
+ Future<void> test_inString() async {
+ await testRequest(r'''
+const a = '[[^]]';
+''', SnippetContext.inString);
+ }
+
+ Future<void> test_inString_raw() async {
+ await testRequest(r'''
+const a = r'[[^]]';
+''', SnippetContext.inString);
+ }
+
+ Future<void> test_inString_unterminated() async {
+ await testRequest(r'''
+const a = r'[[^]]
+''', SnippetContext.inString);
+ }
+
+ Future<void> test_topLevel_atEnd() async {
+ await testRequest(r'''
+class A {}
+
+[[^]]
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_atEnd_partialIdentifier() async {
+ await testRequest(r'''
+class A {}
+
+[[mysnip^]]
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_atStart() async {
+ await testRequest(r'''
+[[^]]
+
+class A {}
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_atStart_partialIdentifier() async {
+ await testRequest(r'''
+[[mysnip^]]
+
+class A {}
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_betweenClasses() async {
+ await testRequest(r'''
+class A {}
+
+[[^]]
+
+class B {}
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_betweenClasses_partialIdentifier() async {
+ await testRequest(r'''
+class A {}
+
+[[mysnip^]]
+
+class B {}
+''', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_empty() async {
+ await testRequest('[[^]]', SnippetContext.atTopLevel);
+ }
+
+ Future<void> test_topLevel_empty_partialIdentifier() async {
+ await testRequest('[[mysnip^]]', SnippetContext.atTopLevel);
+ }
+
+ /// Checks that [code] produces a context of [expectedContext] where the
+ /// character '^' in [code] represents the supplied offset and the range
+ /// surrounded `[[` by brackets `]]` is the expected replacement range.
+ ///
+ /// `^`, `[[` and `]]` will be removed from the code before resolving.
+ Future<void> testRequest(String code, SnippetContext expectedContext) async {
+ code = normalizeNewlinesForPlatform(code);
+ final offset = offsetFromMarker(code);
+ final expectedReplacementRange = rangeFromMarkers(code);
+ await resolveTestCode(withoutMarkers(code));
+
+ final request = DartSnippetRequest(
+ unit: testAnalysisResult,
+ offset: offset,
+ );
+
+ expect(request.filePath, testFile);
+ expect(request.offset, offset);
+ expect(request.context, expectedContext);
+ expect(request.replacementRange, expectedReplacementRange);
+ }
+}
diff --git a/pkg/analysis_server/test/services/snippets/dart/test_all.dart b/pkg/analysis_server/test/services/snippets/dart/test_all.dart
new file mode 100644
index 0000000..907e05a
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/dart/test_all.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'flutter_snippet_producers_test.dart' as flutter_snippet_producers;
+import 'snippet_manager_test.dart' as snippet_manager;
+import 'snippet_request_test.dart' as snippet_request;
+
+void main() {
+ defineReflectiveSuite(() {
+ flutter_snippet_producers.main();
+ snippet_manager.main();
+ snippet_request.main();
+ }, name: 'dart');
+}
diff --git a/pkg/analysis_server/test/services/snippets/dart/test_support.dart b/pkg/analysis_server/test/services/snippets/dart/test_support.dart
new file mode 100644
index 0000000..9f2d740
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/dart/test_support.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/source/source_range.dart';
+import 'package:test/test.dart';
+
+int offsetFromMarker(String code) {
+ final offset = withoutRangeMarkers(code).indexOf('^');
+ expect(offset, isNot(-1));
+ return offset;
+}
+
+SourceRange rangeFromMarkers(String code) {
+ code = _withoutPositionMarker(code);
+ final start = code.indexOf('[[');
+ final end = code.indexOf(']]');
+ expect(start, isNot(-1));
+ expect(end, isNot(-1));
+ final endAdjusted = end - 2; // Account for the [[ before this marker
+ return SourceRange(start, endAdjusted - start);
+}
+
+String withoutMarkers(String code) =>
+ withoutRangeMarkers(_withoutPositionMarker(code));
+
+String withoutRangeMarkers(String code) =>
+ code.replaceAll('[[', '').replaceAll(']]', '');
+
+String _withoutPositionMarker(String code) => code.replaceAll('^', '');
diff --git a/pkg/analysis_server/test/services/snippets/test_all.dart b/pkg/analysis_server/test/services/snippets/test_all.dart
new file mode 100644
index 0000000..899f5ae
--- /dev/null
+++ b/pkg/analysis_server/test/services/snippets/test_all.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'dart/test_all.dart' as dart_all;
+
+void main() {
+ defineReflectiveSuite(() {
+ dart_all.main();
+ }, name: 'snippets');
+}
diff --git a/pkg/analysis_server/test/services/test_all.dart b/pkg/analysis_server/test/services/test_all.dart
index 954023d..a6feeba 100644
--- a/pkg/analysis_server/test/services/test_all.dart
+++ b/pkg/analysis_server/test/services/test_all.dart
@@ -9,6 +9,7 @@
import 'linter/test_all.dart' as linter_all;
import 'refactoring/test_all.dart' as refactoring_all;
import 'search/test_all.dart' as search_all;
+import 'snippets/test_all.dart' as snippets_all;
void main() {
defineReflectiveSuite(() {
@@ -17,5 +18,6 @@
linter_all.main();
refactoring_all.main();
search_all.main();
+ snippets_all.main();
});
}
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 02368a6..59f686d 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -51,6 +51,18 @@
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
+ void test_canRename_field_static_private() {
+ var refactor = _compute(r'''
+class A{
+ static const ^_val = 1234;
+}
+''');
+
+ expect(refactor, isNotNull);
+ expect(refactor!.refactoringElement.element.name, '_val');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
+ }
+
void test_canRename_function() {
var refactor = _compute(r'''
void ^foo() {
@@ -256,6 +268,42 @@
]);
}
+ void test_rename_field() {
+ var result = _rename(r'''
+class A{
+ int get ^x => 5;
+}
+
+void foo() {
+ var m = A().x;
+}
+''', 'y');
+
+ expect(result, isNotNull);
+ expect(result!.matches, [
+ CiderSearchMatch(convertPath('/workspace/dart/test/lib/test.dart'),
+ [CharacterLocation(2, 11), CharacterLocation(6, 15)]),
+ ]);
+ }
+
+ void test_rename_field_static_private() {
+ var result = _rename(r'''
+class A{
+ static const ^_val = 1234;
+}
+
+void foo() {
+ print(A._val);
+}
+''', '_newVal');
+
+ expect(result, isNotNull);
+ expect(result!.matches, [
+ CiderSearchMatch(convertPath('/workspace/dart/test/lib/test.dart'),
+ [CharacterLocation(2, 16), CharacterLocation(6, 11)]),
+ ]);
+ }
+
void test_rename_function() {
var result = _rename(r'''
test() {}
@@ -341,7 +389,7 @@
]);
}
- void test_typeAlias_functionType() {
+ void test_rename_typeAlias_functionType() {
var result = _rename(r'''
typedef ^F = void Function();
void f(F a) {}
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index c215a6c..79818f0 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:convert';
+
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -137,6 +139,24 @@
@reflectiveTest
class OutlineComputerTest extends AbstractOutlineComputerTest {
+ String get testPathJson => jsonOfPath(testPath);
+
+ void assertJsonText(Object object, String expected) {
+ expected = expected.trimRight();
+ var actual = JsonEncoder.withIndent(' ').convert(object);
+ if (actual != expected) {
+ print('-----');
+ print(actual);
+ print('-----');
+ }
+ expect(actual, expected);
+ }
+
+ String jsonOfPath(String path) {
+ path = convertPath(path);
+ return json.encode(path);
+ }
+
Future<void> test_class() async {
var unitOutline = await _computeOutline('''
abstract class A<K, V> {
@@ -382,34 +402,270 @@
}
}
- Future<void> test_enum() async {
+ Future<void> test_enum_constants() async {
var unitOutline = await _computeOutline('''
-enum MyEnum {
- A, B, C
+enum E {
+ v1, v2
}
''');
+
var topOutlines = unitOutline.children!;
expect(topOutlines, hasLength(1));
- // MyEnum
+
+ assertJsonText(topOutlines[0], '''
+{
+ "element": {
+ "kind": "ENUM",
+ "name": "E",
+ "location": {
+ "file": $testPathJson,
+ "offset": 5,
+ "length": 1,
+ "startLine": 1,
+ "startColumn": 6,
+ "endLine": 1,
+ "endColumn": 7
+ },
+ "flags": 0
+ },
+ "offset": 0,
+ "length": 19,
+ "codeOffset": 0,
+ "codeLength": 19,
+ "children": [
{
- var outline_MyEnum = topOutlines[0];
- var element_MyEnum = outline_MyEnum.element;
- expect(element_MyEnum.kind, ElementKind.ENUM);
- expect(element_MyEnum.name, 'MyEnum');
- {
- var location = element_MyEnum.location!;
- expect(location.offset, testCode.indexOf('MyEnum {'));
- expect(location.length, 'MyEnum'.length);
- }
- expect(element_MyEnum.parameters, null);
- expect(element_MyEnum.returnType, null);
- // MyEnum children
- var outlines_MyEnum = outline_MyEnum.children!;
- expect(outlines_MyEnum, hasLength(3));
- _isEnumConstant(outlines_MyEnum[0], 'A');
- _isEnumConstant(outlines_MyEnum[1], 'B');
- _isEnumConstant(outlines_MyEnum[2], 'C');
+ "element": {
+ "kind": "ENUM_CONSTANT",
+ "name": "v1",
+ "location": {
+ "file": $testPathJson,
+ "offset": 11,
+ "length": 2,
+ "startLine": 2,
+ "startColumn": 3,
+ "endLine": 2,
+ "endColumn": 5
+ },
+ "flags": 0
+ },
+ "offset": 11,
+ "length": 2,
+ "codeOffset": 11,
+ "codeLength": 2
+ },
+ {
+ "element": {
+ "kind": "ENUM_CONSTANT",
+ "name": "v2",
+ "location": {
+ "file": $testPathJson,
+ "offset": 15,
+ "length": 2,
+ "startLine": 2,
+ "startColumn": 7,
+ "endLine": 2,
+ "endColumn": 9
+ },
+ "flags": 0
+ },
+ "offset": 15,
+ "length": 2,
+ "codeOffset": 15,
+ "codeLength": 2
}
+ ]
+}
+''');
+ }
+
+ Future<void> test_enum_members() async {
+ var unitOutline = await _computeOutline('''
+enum E {
+ v;
+ final int f = 0;
+ const E();
+ const E.named();
+ void aMethod() {}
+ int get aGetter => 0;
+ set aSetter(int value) {}
+}
+''');
+
+ var topOutlines = unitOutline.children!;
+ expect(topOutlines, hasLength(1));
+
+ assertJsonText(topOutlines[0], '''
+{
+ "element": {
+ "kind": "ENUM",
+ "name": "E",
+ "location": {
+ "file": $testPathJson,
+ "offset": 5,
+ "length": 1,
+ "startLine": 1,
+ "startColumn": 6,
+ "endLine": 1,
+ "endColumn": 7
+ },
+ "flags": 0
+ },
+ "offset": 0,
+ "length": 138,
+ "codeOffset": 0,
+ "codeLength": 138,
+ "children": [
+ {
+ "element": {
+ "kind": "ENUM_CONSTANT",
+ "name": "v",
+ "location": {
+ "file": $testPathJson,
+ "offset": 11,
+ "length": 1,
+ "startLine": 2,
+ "startColumn": 3,
+ "endLine": 2,
+ "endColumn": 4
+ },
+ "flags": 0
+ },
+ "offset": 11,
+ "length": 1,
+ "codeOffset": 11,
+ "codeLength": 1
+ },
+ {
+ "element": {
+ "kind": "FIELD",
+ "name": "f",
+ "location": {
+ "file": $testPathJson,
+ "offset": 26,
+ "length": 1,
+ "startLine": 3,
+ "startColumn": 13,
+ "endLine": 3,
+ "endColumn": 14
+ },
+ "flags": 4,
+ "returnType": "int"
+ },
+ "offset": 16,
+ "length": 16,
+ "codeOffset": 26,
+ "codeLength": 5
+ },
+ {
+ "element": {
+ "kind": "CONSTRUCTOR",
+ "name": "E",
+ "location": {
+ "file": $testPathJson,
+ "offset": 41,
+ "length": 1,
+ "startLine": 4,
+ "startColumn": 9,
+ "endLine": 4,
+ "endColumn": 10
+ },
+ "flags": 0,
+ "parameters": "()"
+ },
+ "offset": 35,
+ "length": 10,
+ "codeOffset": 35,
+ "codeLength": 10
+ },
+ {
+ "element": {
+ "kind": "CONSTRUCTOR",
+ "name": "E.named",
+ "location": {
+ "file": $testPathJson,
+ "offset": 56,
+ "length": 5,
+ "startLine": 5,
+ "startColumn": 11,
+ "endLine": 5,
+ "endColumn": 16
+ },
+ "flags": 0,
+ "parameters": "()"
+ },
+ "offset": 48,
+ "length": 16,
+ "codeOffset": 48,
+ "codeLength": 16
+ },
+ {
+ "element": {
+ "kind": "METHOD",
+ "name": "aMethod",
+ "location": {
+ "file": $testPathJson,
+ "offset": 72,
+ "length": 7,
+ "startLine": 6,
+ "startColumn": 8,
+ "endLine": 6,
+ "endColumn": 15
+ },
+ "flags": 0,
+ "parameters": "()",
+ "returnType": "void"
+ },
+ "offset": 67,
+ "length": 17,
+ "codeOffset": 67,
+ "codeLength": 17
+ },
+ {
+ "element": {
+ "kind": "GETTER",
+ "name": "aGetter",
+ "location": {
+ "file": $testPathJson,
+ "offset": 95,
+ "length": 7,
+ "startLine": 7,
+ "startColumn": 11,
+ "endLine": 7,
+ "endColumn": 18
+ },
+ "flags": 0,
+ "returnType": "int"
+ },
+ "offset": 87,
+ "length": 21,
+ "codeOffset": 87,
+ "codeLength": 21
+ },
+ {
+ "element": {
+ "kind": "SETTER",
+ "name": "aSetter",
+ "location": {
+ "file": $testPathJson,
+ "offset": 115,
+ "length": 7,
+ "startLine": 8,
+ "startColumn": 7,
+ "endLine": 8,
+ "endColumn": 14
+ },
+ "flags": 0,
+ "parameters": "(int value)",
+ "returnType": ""
+ },
+ "offset": 111,
+ "length": 25,
+ "codeOffset": 111,
+ "codeLength": 25
+ }
+ ]
+}
+''');
}
Future<void> test_extension_named() async {
@@ -1350,12 +1606,4 @@
expect(element.returnType, returnType);
}
}
-
- void _isEnumConstant(Outline outline, String name) {
- var element = outline.element;
- expect(element.kind, ElementKind.ENUM_CONSTANT);
- expect(element.name, name);
- expect(element.parameters, isNull);
- expect(element.returnType, isNull);
- }
}
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index e55c554..f59bb45 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -386,6 +386,35 @@
expect(container.codeLength, 15);
}
+ Future<void> test_enum() async {
+ var unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+
+enum E {
+ v;
+ Widget build(BuildContext context) {
+ return const Text('A');
+ }
+}
+''');
+
+ expect(_toText(unitOutline), r'''
+(D) E
+ (D) v
+ (D) build
+ Text
+''');
+ var E = unitOutline.children![0];
+ var build = E.children![1];
+ {
+ var textOutline = build.children![0];
+ var text = "const Text('A')";
+ var offset = testCode.indexOf(text);
+ expect(textOutline.offset, offset);
+ expect(textOutline.length, text.length);
+ }
+ }
+
Future<void> test_genericLabel_invocation() async {
var unitOutline = await _computeOutline(r'''
import 'package:flutter/widgets.dart';
@@ -442,6 +471,46 @@
}
}
+ Future<void> test_namedArgument_anywhere() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+ final Widget top;
+ final Widget bottom;
+ final Widget left;
+ final Widget right;
+
+ WidgetA(this.top, this.bottom, {this.left, this.right});
+}
+''');
+ var unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new WidgetA(
+ const Container(),
+ left: const Text('left'),
+ const Flex(),
+ right: const Text('right'),
+ );
+ }
+}
+''');
+ expect(_toText(unitOutline), r'''
+(D) MyWidget
+ (D) build
+ WidgetA
+ Container
+ left: Text
+ Flex
+ right: Text
+''');
+ }
+
Future<void> test_parentAssociationLabel() async {
newFile('$testPackageLibPath/a.dart', content: r'''
import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
index 9f66816..3ee46d5 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
@@ -33,7 +33,7 @@
);
var builder = SuggestionBuilder(request);
builder.suggestTopLevelFunction(findElement.topFunction('f'));
- var suggestions = builder.suggestions.toList();
+ var suggestions = builder.suggestions.map((e) => e.build()).toList();
expect(suggestions, hasLength(1));
return suggestions[0];
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_enum_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_enum_test.dart
new file mode 100644
index 0000000..fa8e2fe
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_class_to_enum_test.dart
@@ -0,0 +1,567 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertClassToEnumTest);
+ });
+}
+
+@reflectiveTest
+class ConvertClassToEnumTest extends AssistProcessorTest {
+ @override
+ AssistKind get kind => DartAssistKind.CONVERT_CLASS_TO_ENUM;
+
+ Future<void> test_extends_object_privateClass() async {
+ await resolveTestCode('''
+class _E extends Object {
+ static const _E c = _E();
+
+ const _E();
+}
+''');
+ await assertHasAssistAt('E extends', '''
+enum _E {
+ c
+}
+''');
+ }
+
+ Future<void> test_extends_object_publicClass() async {
+ await resolveTestCode('''
+class E extends Object {
+ static const E c = E._();
+
+ const E._();
+}
+''');
+ await assertHasAssistAt('E extends', '''
+enum E {
+ c._();
+
+ const E._();
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_first_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(0, 'a');
+ static const _E c1 = _E(1, 'b');
+
+ final int index;
+
+ final String code;
+
+ const _E(this.index, this.code);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0('a'),
+ c1('b');
+
+ final String code;
+
+ const _E(this.code);
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_last_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E('a', 0);
+ static const _E c1 = _E('b', 1);
+
+ final String code;
+
+ final int index;
+
+ const _E(this.code, this.index);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0('a'),
+ c1('b');
+
+ final String code;
+
+ const _E(this.code);
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_middle_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E('a', 0, 'b');
+ static const _E c1 = _E('c', 1, 'd');
+
+ final String first;
+
+ final int index;
+
+ final String last;
+
+ const _E(this.first, this.index, this.last);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0('a', 'b'),
+ c1('c', 'd');
+
+ final String first;
+
+ final String last;
+
+ const _E(this.first, this.last);
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_only_outOfOrder() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(1);
+ static const _E c1 = _E(0);
+
+ final int index;
+
+ const _E(this.index);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c1,
+ c0
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_only_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(0);
+ static const _E c1 = _E(1);
+
+ final int index;
+
+ const _E(this.index);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0,
+ c1
+}
+''');
+ }
+
+ Future<void> test_index_namedIndex_only_publicClass() async {
+ await resolveTestCode('''
+class E {
+ static const E c0 = E._(0);
+ static const E c1 = E._(1);
+
+ final int index;
+
+ const E._(this.index);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum E {
+ c0._(),
+ c1._();
+
+ const E._();
+}
+''');
+ }
+
+ Future<void> test_index_notNamedIndex_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(0);
+ static const _E c1 = _E(1);
+
+ final int value;
+
+ const _E(this.value);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0(0),
+ c1(1);
+
+ final int value;
+
+ const _E(this.value);
+}
+''');
+ }
+
+ Future<void> test_index_notNamedIndex_publicClass() async {
+ await resolveTestCode('''
+class E {
+ static const E c0 = E._(0);
+ static const E c1 = E._(1);
+
+ final int value;
+
+ const E._(this.value);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum E {
+ c0._(0),
+ c1._(1);
+
+ final int value;
+
+ const E._(this.value);
+}
+''');
+ }
+
+ Future<void> test_invalid_abstractClass() async {
+ await resolveTestCode('''
+abstract class E {}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_constructorUsedInConstructor() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ // ignore: unused_element
+ const _E({_E e = const _E()});
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_constructorUsedOutsideClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+}
+_E get e => _E();
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_extended() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+}
+class F extends _E {}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_extends_notObject() async {
+ await resolveTestCode('''
+class E extends C {
+ static const E c = E._();
+
+ const E._();
+}
+class C {
+ const C();
+}
+''');
+ await assertNoAssistAt('E extends');
+ }
+
+ Future<void> test_invalid_factoryConstructor_all() async {
+ await resolveTestCode('''
+class _E {
+ static _E c = _E();
+
+ factory _E() => c;
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_factoryConstructor_some() async {
+ // We could arguably support this case by only converting the static fields
+ // that are initialized by a generative constructor.
+ await resolveTestCode('''
+class _E {
+ static _E c0 = _E._();
+ static _E c1 = _E();
+
+ factory _E() => c0;
+ const _E._();
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_hasPart() async {
+ // Change this test if the assist becomes able to look for references to the
+ // class and its constructors in part files.
+ newFile('$testPackageLibPath/a.dart', content: '''
+part of 'test.dart';
+''');
+ await resolveTestCode('''
+part 'a.dart';
+
+class E {
+ static const E c = E._();
+
+ const E._();
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_implemented() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+}
+class F implements _E {}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_indexFieldNotSequential() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(0);
+ static const _E c1 = _E(3);
+
+ final int index;
+
+ const _E(this.index);
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_multipleConstantsInSameFieldDeclaration() async {
+ // Change this test if support is added to cover cases where multiple
+ // constants are defined in a single field declaration.
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E('a'), c1 = _E('b');
+
+ final String s;
+
+ const _E(this.s);
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_nonConstConstructor() async {
+ await resolveTestCode('''
+class _E {
+ static _E c = _E();
+
+ _E();
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_overrides_equal() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+
+ @override
+ int get hashCode => 0;
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_invalid_overrides_hashCode() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+
+ @override
+ bool operator ==(Object other) => true;
+}
+''');
+ await assertNoAssistAt('E {');
+ }
+
+ Future<void> test_minimal_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c
+}
+''');
+ }
+
+ Future<void> test_minimal_publicClass() async {
+ await resolveTestCode('''
+class E {
+ static const E c = E._();
+
+ const E._();
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum E {
+ c._();
+
+ const E._();
+}
+''');
+ }
+
+ Future<void> test_noIndex_int_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E(2);
+ static const _E c1 = _E(4);
+
+ final int count;
+
+ const _E(this.count);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0(2),
+ c1(4);
+
+ final int count;
+
+ const _E(this.count);
+}
+''');
+ }
+
+ Future<void> test_noIndex_int_publicClass() async {
+ await resolveTestCode('''
+class E {
+ static const E c0 = E._(2);
+ static const E c1 = E._(4);
+
+ final int count;
+
+ const E._(this.count);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum E {
+ c0._(2),
+ c1._(4);
+
+ final int count;
+
+ const E._(this.count);
+}
+''');
+ }
+
+ Future<void> test_noIndex_notInt_privateClass() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c0 = _E('c0');
+ static const _E c1 = _E('c1');
+
+ final String name;
+
+ const _E(this.name);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c0('c0'),
+ c1('c1');
+
+ final String name;
+
+ const _E(this.name);
+}
+''');
+ }
+
+ Future<void> test_noIndex_notInt_publicClass() async {
+ await resolveTestCode('''
+class E {
+ static const E c0 = E._('c0');
+ static const E c1 = E._('c1');
+
+ final String name;
+
+ const E._(this.name);
+}
+''');
+ await assertHasAssistAt('E {', '''
+enum E {
+ c0._('c0'),
+ c1._('c1');
+
+ final String name;
+
+ const E._(this.name);
+}
+''');
+ }
+
+ Future<void> test_withReferencedFactoryConstructor() async {
+ await resolveTestCode('''
+class _E {
+ static const _E c = _E();
+
+ const _E();
+
+ factory _E.withValue(int x) => c;
+}
+
+_E e = _E.withValue(0);
+''');
+ await assertHasAssistAt('E {', '''
+enum _E {
+ c;
+
+ const _E();
+
+ factory _E.withValue(int x) => c;
+}
+
+_E e = _E.withValue(0);
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_super_initializing_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_super_initializing_parameter_test.dart
new file mode 100644
index 0000000..df4f094
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_super_initializing_parameter_test.dart
@@ -0,0 +1,484 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertToSuperInitializingParameterTest);
+ });
+}
+
+@reflectiveTest
+class ConvertToSuperInitializingParameterTest extends AssistProcessorTest {
+ @override
+ AssistKind get kind => DartAssistKind.CONVERT_TO_SUPER_INITIALIZING_PARAMETER;
+
+ Future<void> test_named_first() async {
+ await resolveTestCode('''
+class A {
+ A({int? x, int? y});
+}
+class B extends A {
+ B({int? x, int? y}) : super(x: x, y: y);
+}
+''');
+ await assertHasAssistAt('x, int? y}) :', '''
+class A {
+ A({int? x, int? y});
+}
+class B extends A {
+ B({super.x, int? y}) : super(y: y);
+}
+''');
+ }
+
+ Future<void> test_named_last() async {
+ await resolveTestCode('''
+class A {
+ A({int? x, int? y});
+}
+class B extends A {
+ B({int? x, int? y}) : super(x: x, y: y);
+}
+''');
+ await assertHasAssistAt('y}) :', '''
+class A {
+ A({int? x, int? y});
+}
+class B extends A {
+ B({int? x, super.y}) : super(x: x);
+}
+''');
+ }
+
+ Future<void> test_named_middle() async {
+ await resolveTestCode('''
+class A {
+ A({int? x, int? y, int? z});
+}
+class B extends A {
+ B({int? x, int? y, int? z}) : super(x: x, y: y, z: z);
+}
+''');
+ await assertHasAssistAt('y, int? z}) :', '''
+class A {
+ A({int? x, int? y, int? z});
+}
+class B extends A {
+ B({int? x, super.y, int? z}) : super(x: x, z: z);
+}
+''');
+ }
+
+ Future<void> test_named_noSuperInvocation() async {
+ await resolveTestCode('''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({int x = 1});
+}
+''');
+ await assertNoAssistAt('x = 1');
+ }
+
+ Future<void> test_named_notGenerative() async {
+ await resolveTestCode('''
+class A {
+ A({required int x});
+}
+class B extends A {
+ static List<B> instances = [];
+ factory B({required int x}) => instances[x];
+}
+''');
+ await assertNoAssistAt('x}) =>');
+ }
+
+ Future<void> test_named_notInConstructor() async {
+ await resolveTestCode('''
+class A {
+ void m({required int x}) {}
+}
+''');
+ await assertNoAssistAt('x})');
+ }
+
+ Future<void> test_named_notPassed_unreferenced() async {
+ await resolveTestCode('''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({int x = 0}) : super(x: 0);
+}
+''');
+ await assertNoAssistAt('x = 0}) :');
+ }
+
+ Future<void> test_named_notPassed_usedInExpression() async {
+ await resolveTestCode('''
+class A {
+ A({String x = ''});
+}
+class B extends A {
+ B({required Object x}) : super(x: x.toString());
+}
+''');
+ await assertNoAssistAt('x}) :');
+ }
+
+ Future<void> test_named_notSupported() async {
+ await resolveTestCode('''
+// @dart=2.16
+class A {
+ A({int? x});
+}
+class B extends A {
+ B({int? x}) : super(x: x);
+}
+''');
+ await assertNoAssistAt('x}) :');
+ }
+
+ Future<void> test_named_only() async {
+ await resolveTestCode('''
+class A {
+ A({int? x});
+}
+class B extends A {
+ B({int? x}) : super(x: x);
+}
+''');
+ await assertHasAssistAt('x}) :', '''
+class A {
+ A({int? x});
+}
+class B extends A {
+ B({super.x});
+}
+''');
+ }
+
+ Future<void> test_named_withDifferentDefaultValue() async {
+ await resolveTestCode('''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({int x = 2}) : super(x: x);
+}
+''');
+ await assertHasAssistAt('x = 2}) :', '''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({super.x = 2});
+}
+''');
+ }
+
+ Future<void> test_named_withEqualDefaultValue() async {
+ await resolveTestCode('''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({int x = 0}) : super(x: x);
+}
+''');
+ await assertHasAssistAt('x = 0}) :', '''
+class A {
+ A({int x = 0});
+}
+class B extends A {
+ B({super.x});
+}
+''');
+ }
+
+ Future<void> test_optionalPositional_singleSuperParameter_only() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B([int x = 0]) : super(x);
+}
+''');
+ await assertHasAssistAt('x = 0]', '''
+class A {
+ A(int x);
+}
+class B extends A {
+ B([super.x = 0]);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_mixedSuperParameters_first() async {
+ await resolveTestCode('''
+class A {
+ A(int x, {int? y});
+}
+class B extends A {
+ B(int x, int y) : super(x, y: y);
+}
+''');
+ await assertHasAssistAt('x, int y)', '''
+class A {
+ A(int x, {int? y});
+}
+class B extends A {
+ B(super.x, int y) : super(y: y);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_mixedSuperParameters_last() async {
+ await resolveTestCode('''
+class A {
+ A(int x, {int? y});
+}
+class B extends A {
+ B(int y, int x) : super(x, y: y);
+}
+''');
+ await assertHasAssistAt('x) :', '''
+class A {
+ A(int x, {int? y});
+}
+class B extends A {
+ B(int y, super.x) : super(y: y);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_mixedSuperParameters_middle() async {
+ await resolveTestCode('''
+class A {
+ A(int y, {int? z});
+}
+class B extends A {
+ B(int x, int y, int z) : super(y, z: z);
+}
+''');
+ await assertHasAssistAt('y, int z) :', '''
+class A {
+ A(int y, {int? z});
+}
+class B extends A {
+ B(int x, super.y, int z) : super(z: z);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_multipleSuperParameters_first() async {
+ await resolveTestCode('''
+class A {
+ A(int x, int y);
+}
+class B extends A {
+ B(int x, int y) : super(x, y);
+}
+''');
+ await assertNoAssistAt('x, int y) :');
+ }
+
+ Future<void> test_requiredPositional_multipleSuperParameters_last() async {
+ await resolveTestCode('''
+class A {
+ A(int x, int y);
+}
+class B extends A {
+ B(int x, int y) : super(x, y);
+}
+''');
+ await assertNoAssistAt('y) :');
+ }
+
+ Future<void> test_requiredPositional_multipleSuperParameters_middle() async {
+ await resolveTestCode('''
+class A {
+ A(int x, int y, int z);
+}
+class B extends A {
+ B(int x, int y, int z) : super(x, y, z);
+}
+''');
+ await assertNoAssistAt('y, int z) :');
+ }
+
+ Future<void> test_requiredPositional_noSuperInvocation() async {
+ await resolveTestCode('''
+class A {
+ A();
+}
+class B extends A {
+ B(int x);
+}
+''');
+ await assertNoAssistAt('x);');
+ }
+
+ Future<void> test_requiredPositional_notGenerative() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ static List<B> instances = [];
+ factory B(int x) => instances[x];
+}
+''');
+ await assertNoAssistAt('x) =>');
+ }
+
+ Future<void> test_requiredPositional_notInConstructor() async {
+ await resolveTestCode('''
+class A {
+ void m(int x) {}
+}
+''');
+ await assertNoAssistAt('x)');
+ }
+
+ Future<void> test_requiredPositional_notPassed_unreferenced() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x) : super(0);
+}
+''');
+ await assertNoAssistAt('x) :');
+ }
+
+ Future<void> test_requiredPositional_notPassed_usedInExpression() async {
+ await resolveTestCode('''
+class A {
+ A(String x);
+}
+class B extends A {
+ B(Object x) : super(x.toString());
+}
+''');
+ await assertNoAssistAt('x) :');
+ }
+
+ Future<void> test_requiredPositional_notSupported() async {
+ await resolveTestCode('''
+// @dart=2.16
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x) : super(x);
+}
+''');
+ await assertNoAssistAt('x) :');
+ }
+
+ Future<void> test_requiredPositional_singleSuperParameter_first() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x, int y) : super(x);
+}
+''');
+ await assertHasAssistAt('x, int y)', '''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(super.x, int y);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_singleSuperParameter_last() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x, int y) : super(y);
+}
+''');
+ await assertHasAssistAt('y) :', '''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x, super.y);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_singleSuperParameter_middle() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x, int y, int z) : super(y);
+}
+''');
+ await assertHasAssistAt('y, int z) :', '''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x, super.y, int z);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_singleSuperParameter_only() async {
+ await resolveTestCode('''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(int x) : super(x);
+}
+''');
+ await assertHasAssistAt('x) :', '''
+class A {
+ A(int x);
+}
+class B extends A {
+ B(super.x);
+}
+''');
+ }
+
+ Future<void> test_requiredPositional_unpassedOptionalPositional() async {
+ await resolveTestCode('''
+class A {
+ A(int x, [int y = 0]);
+}
+class B extends A {
+ B(int x) : super(x);
+}
+''');
+ await assertHasAssistAt('x) :', '''
+class A {
+ A(int x, [int y = 0]);
+}
+class B extends A {
+ B(super.x);
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
index fc79cb7..5f53ffdd 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
@@ -154,4 +154,36 @@
}
''');
}
+
+ Future<void> test_selectedWidgetName() async {
+ await resolveTestCode('''
+import 'package:flutter/widgets.dart';
+
+class FakeFlutter {
+ main() {
+ return Container(
+ child: Text('aaa'),
+ );
+ }
+}
+''');
+ await assertHasAssistAt(
+ 'Text(',
+ '''
+import 'package:flutter/widgets.dart';
+
+class FakeFlutter {
+ main() {
+ return Container(
+ child: Column(
+ children: [
+ Text('aaa'),
+ ],
+ ),
+ );
+ }
+}
+''',
+ length: 4);
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 1773afd..2c05865 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -9,6 +9,7 @@
import 'add_return_type_test.dart' as add_return_type;
import 'add_type_annotation_test.dart' as add_type_annotation;
import 'assign_to_local_variable_test.dart' as assign_to_local_variable;
+import 'convert_class_to_enum_test.dart' as convert_class_to_enum;
import 'convert_class_to_mixin_test.dart' as convert_class_to_mixin;
import 'convert_documentation_into_block_test.dart'
as convert_documentation_into_block;
@@ -41,6 +42,8 @@
import 'convert_to_single_quoted_string_test.dart'
as convert_to_single_quoted_string;
import 'convert_to_spread_test.dart' as convert_to_spread;
+import 'convert_to_super_initializing_parameter_test.dart'
+ as convert_to_super_initializing_parameter;
import 'encapsulate_field_test.dart' as encapsulate_field;
import 'exchange_operands_test.dart' as exchange_operands;
import 'flutter_convert_to_children_test.dart' as flutter_convert_to_children;
@@ -95,6 +98,7 @@
add_return_type.main();
add_type_annotation.main();
assign_to_local_variable.main();
+ convert_class_to_enum.main();
convert_class_to_mixin.main();
convert_documentation_into_block.main();
convert_documentation_into_line.main();
@@ -122,6 +126,7 @@
convert_to_set_literal.main();
convert_to_single_quoted_string.main();
convert_to_spread.main();
+ convert_to_super_initializing_parameter.main();
encapsulate_field.main();
exchange_operands.main();
flutter_convert_to_children.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart
index 5a4616c..dae57ea 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_positional_test.dart
@@ -19,6 +19,110 @@
@override
FixKind get kind => DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL;
+ Future<void> test_constructor_callingViaSuper() async {
+ await resolveTestCode('''
+class A {
+ A(int a);
+}
+class B extends A {
+ B() : super(1, 2.0);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(int a, [double d]);
+}
+class B extends A {
+ B() : super(1, 2.0);
+}
+''');
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48359')
+ Future<void> test_constructor_callingViaSuperParameter() async {
+ await resolveTestCode('''
+class A {
+ A(int a);
+}
+class B extends A {
+ B(super.a, super.b);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(int a, [double b]);
+}
+class B extends A {
+ B(super.a, super.b);
+}
+''');
+ }
+
+ Future<void> test_constructor_hasOne() async {
+ await resolveTestCode('''
+class A {
+ A(int a);
+}
+void f() {
+ A(1, 2.0);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(int a, [double d]);
+}
+void f() {
+ A(1, 2.0);
+}
+''');
+ }
+
+ Future<void> test_constructor_hasOneFieldFormalParameter() async {
+ await resolveTestCode('''
+class A {
+ int a;
+ A(this.a);
+}
+void f() {
+ A(1, 2.0);
+}
+''');
+ await assertHasFix('''
+class A {
+ int a;
+ A(this.a, [double d]);
+}
+void f() {
+ A(1, 2.0);
+}
+''');
+ }
+
+ Future<void> test_constructor_hasOneSuperParameter() async {
+ await resolveTestCode('''
+class A {
+ A(int a);
+}
+class B extends A {
+ B(super.a);
+}
+void f() {
+ B(1, 2.0);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(int a);
+}
+class B extends A {
+ B(super.a, [double d]);
+}
+void f() {
+ B(1, 2.0);
+}
+''');
+ }
+
Future<void> test_function_hasNamed() async {
await resolveTestCode('''
test({int a = 0}) {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
index 1da0c9d..6aff080 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
@@ -81,6 +81,25 @@
''');
}
+ Future<void> test_nonNullable_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C({required int param});
+}
+class D extends C {
+ D({super.param});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({required int param});
+}
+class D extends C {
+ D({required super.param});
+}
+''');
+ }
+
Future<void> test_withRequiredAnnotation() async {
writeTestPackageConfig(meta: true);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
index bf7c774..f8ba15b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
@@ -72,7 +72,22 @@
@override
String get lintCode => LintNames.require_trailing_commas;
- Future<void> test_comma() async {
+ Future<void> test_named() async {
+ await resolveTestCode('''
+void f({a, b}) {
+ f(a: 'a',
+ b: 'b');
+}
+''');
+ await assertHasFix('''
+void f({a, b}) {
+ f(a: 'a',
+ b: 'b',);
+}
+''');
+ }
+
+ Future<void> test_positional() async {
await resolveTestCode('''
void f(a, b) {
f('a',
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
index d904bf6..a549699 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
@@ -114,14 +114,29 @@
}
@reflectiveTest
-class UseFunctionTypeSyntaxForParametersTest extends FixProcessorLintTest
- with WithNullSafetyLintMixin {
+class UseFunctionTypeSyntaxForParametersTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.CONVERT_TO_GENERIC_FUNCTION_SYNTAX;
@override
String get lintCode => LintNames.use_function_type_syntax_for_parameters;
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3212')
+ Future<void> test_functionTypedParameter_fieldFormal() async {
+ await resolveTestCode('''
+class C {
+ String Function(int) f;
+ C(String this.f(int x));
+}
+''');
+ await assertHasFix('''
+class C {
+ String Function(int) f;
+ C(String Function(int x) this.f);
+}
+''');
+ }
+
Future<void> test_functionTypedParameter_noParameterTypes() async {
await resolveTestCode('''
g(String f(x)) {}
@@ -155,4 +170,24 @@
g(String Function(int x) f) {}
''');
}
+
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3212')
+ Future<void> test_functionTypedParameter_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C(String Function(int x) f);
+}
+class D extends C {
+ D(String super.f(int x));
+}
+''');
+ await assertHasFix('''
+class C {
+ C(String Function(int x) f);
+}
+class D extends C {
+ D(String Function(int x) super.f);
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
index c59880a..9e78353 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
@@ -11,13 +11,75 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ConvertToPackageImportBulkTest);
- defineReflectiveTests(ConvertToPackageImportTest);
+ defineReflectiveTests(
+ ConvertToPackageImport_AvoidRelativeLibImportsBulkTest);
+ defineReflectiveTests(ConvertToPackageImport_AvoidRelativeLibImportsTest);
+ defineReflectiveTests(
+ ConvertToPackageImport_AlwaysUsePackageImportsBulkTest);
+ defineReflectiveTests(ConvertToPackageImport_AlwaysUsePackageImportsTest);
});
}
@reflectiveTest
-class ConvertToPackageImportBulkTest extends BulkFixProcessorTest {
+class ConvertToPackageImport_AlwaysUsePackageImportsBulkTest
+ extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.always_use_package_imports;
+
+ Future<void> test_singleFile() async {
+ writeTestPackageConfig(config: PackageConfigFileBuilder());
+ addSource('$testPackageLibPath/foo.dart', 'class Foo {}');
+ addSource('$testPackageLibPath/bar.dart', 'class Bar {}');
+
+ testFile = convertPath('$testPackageLibPath/test.dart');
+
+ await resolveTestCode('''
+import 'foo.dart';
+import 'bar.dart';
+
+var foo = Foo();
+var bar = Bar();
+''');
+ await assertHasFix('''
+import 'package:test/foo.dart';
+import 'package:test/bar.dart';
+
+var foo = Foo();
+var bar = Bar();
+''');
+ }
+}
+
+@reflectiveTest
+class ConvertToPackageImport_AlwaysUsePackageImportsTest
+ extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.CONVERT_TO_PACKAGE_IMPORT;
+
+ @override
+ String get lintCode => LintNames.always_use_package_imports;
+
+ Future<void> test_relativeImport() async {
+ newFile('$testPackageLibPath/foo.dart', content: '''
+class Foo {}
+''');
+ await resolveTestCode('''
+import 'foo.dart';
+
+var foo = Foo();
+''');
+
+ await assertHasFix('''
+import 'package:test/foo.dart';
+
+var foo = Foo();
+''');
+ }
+}
+
+@reflectiveTest
+class ConvertToPackageImport_AvoidRelativeLibImportsBulkTest
+ extends BulkFixProcessorTest {
@override
String get lintCode => LintNames.avoid_relative_lib_imports;
@@ -42,7 +104,8 @@
}
@reflectiveTest
-class ConvertToPackageImportTest extends FixProcessorLintTest {
+class ConvertToPackageImport_AvoidRelativeLibImportsTest
+ extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.CONVERT_TO_PACKAGE_IMPORT;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart
new file mode 100644
index 0000000..7a0a79e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertToRawStringBulkTest);
+ defineReflectiveTests(ConvertToRawStringTest);
+ });
+}
+
+@reflectiveTest
+class ConvertToRawStringBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.use_raw_strings;
+
+ Future<void> test_bulk() async {
+ await resolveTestCode(r"""
+var a = 'text \\ \$ \\\\' "\\" '${'\\'}';
+var b = '''
+text \\ \$ \\\\
+\\ \$ \\\\
+''';
+""");
+ await assertHasFix(r"""
+var a = r'text \ $ \\' r"\" '${r'\'}';
+var b = r'''
+text \ $ \\
+\ $ \\
+''';
+""");
+ }
+}
+
+@reflectiveTest
+class ConvertToRawStringTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.CONVERT_TO_RAW_STRING;
+
+ @override
+ String get lintCode => LintNames.use_raw_strings;
+
+ Future<void> test_doubleQuotes() async {
+ await resolveTestCode(r'var a = "text \\ \$ \\\\";');
+ await assertHasFix(r'var a = r"text \ $ \\";');
+ }
+
+ Future<void> test_multiLines() async {
+ await resolveTestCode(r"""
+var a = '''
+text \\ \$ \\\\
+\\ \$ \\\\
+''';
+""");
+ await assertHasFix(r"""
+var a = r'''
+text \ $ \\
+\ $ \\
+''';
+""");
+ }
+
+ Future<void> test_singleQuotes() async {
+ await resolveTestCode(r"var a = 'text \\ \$ \\\\';");
+ await assertHasFix(r"var a = r'text \ $ \\';");
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index fc0eaa0..87e18e9 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -236,6 +236,7 @@
void setUp() {
super.setUp();
createAnalysisOptionsFile(
+ experiments: experiments,
lints: [lintCode],
);
}
@@ -246,6 +247,7 @@
/// Return the kind of fixes being tested by this test class.
FixKind get kind;
+ /// Asserts that the resolved compilation unit has a fix which produces [expected] output.
Future<void> assertHasFix(String expected,
{bool Function(AnalysisError)? errorFilter,
int? length,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
index 611de4e..86bdc42 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
@@ -26,10 +26,6 @@
C({String this.s});
}
''');
- // TODO(srawlins): Remove the type if the quick fix as is would use the same
- // type as the field's type. (brianwilkerson) I would argue that removing
- // the type should be a separate fix/assist. There was a reason why the
- // user used an explicit type, and we shouldn't remove it when it's valid.
await assertHasFix('''
class C {
String? s;
@@ -208,4 +204,42 @@
void f<T>({T? s}) {}
''');
}
+
+ Future<void> test_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({String super.s});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({String? super.s});
+}
+''');
+ }
+
+ Future<void> test_superParameter_functionTyped() async {
+ await resolveTestCode('''
+class C {
+ C({void s()?});
+}
+class D extends C {
+ D({void super.s()});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({void s()?});
+}
+class D extends C {
+ D({void super.s()?});
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
index 9d27944..c9ab551 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
@@ -107,9 +107,6 @@
''');
}
- @FailingTest(
- issue: 'https://github.com/dart-lang/linter/issues/3082',
- )
Future<void> test_named_betweenRequiredPositional() async {
await resolveTestCode('''
void foo(int a, int b, {bool c = true}) {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
index 573a033..1992d3f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
@@ -106,6 +106,25 @@
''');
}
+ Future<void> test_parameter_super() async {
+ await resolveTestCode('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({super.s = null});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({super.s});
+}
+''');
+ }
+
Future<void> test_topLevel() async {
await resolveTestCode('''
var x = null;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
new file mode 100644
index 0000000..3f0a3cd
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RemoveLeadingUnderscoreBulkTest);
+ defineReflectiveTests(RemoveLeadingUnderscoreForLibraryPrefixesTest);
+ defineReflectiveTests(RemoveLeadingUnderscoreForLocalVariablesTest);
+ });
+}
+
+@reflectiveTest
+class RemoveLeadingUnderscoreBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.no_leading_underscores_for_local_identifiers;
+
+ Future<void> test_singleFile() async {
+ await resolveTestCode('''
+main() {
+ int _foo = 42;
+ print(_foo);
+ [0, 1, 2].forEach((_bar) {
+ print(_bar);
+ });
+}
+''');
+ await assertHasFix('''
+main() {
+ int foo = 42;
+ print(foo);
+ [0, 1, 2].forEach((bar) {
+ print(bar);
+ });
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveLeadingUnderscoreForLibraryPrefixesTest
+ extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
+
+ @override
+ String get lintCode => LintNames.no_leading_underscores_for_library_prefixes;
+
+ Future<void> test_importPrefix() async {
+ await resolveTestCode('''
+import 'dart:core' as _core;
+_core.int i = 1;
+''');
+ await assertHasFix('''
+import 'dart:core' as core;
+core.int i = 1;
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveLeadingUnderscoreForLocalVariablesTest
+ extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
+
+ @override
+ String get lintCode => LintNames.no_leading_underscores_for_local_identifiers;
+
+ Future<void> test_localVariable() async {
+ await resolveTestCode('''
+void f() {
+ var _foo = 1;
+ print(_foo);
+}
+''');
+ await assertHasFix('''
+void f() {
+ var foo = 1;
+ print(foo);
+}
+''');
+ }
+
+ Future<void> test_parameter_closure() async {
+ await resolveTestCode('''
+void f() {
+ [0, 1, 2].forEach((_foo) {
+ print(_foo);
+ });
+}
+''');
+ await assertHasFix('''
+void f() {
+ [0, 1, 2].forEach((foo) {
+ print(foo);
+ });
+}
+''');
+ }
+
+ Future<void> test_parameter_function() async {
+ await resolveTestCode('''
+void f(int _foo) {
+ print(_foo);
+}
+''');
+ await assertHasFix('''
+void f(int foo) {
+ print(foo);
+}
+''');
+ }
+
+ Future<void> test_parameter_method() async {
+ await resolveTestCode('''
+class A {
+ void f(int _foo) {
+ print(_foo);
+ }
+}
+''');
+ await assertHasFix('''
+class A {
+ void f(int foo) {
+ print(foo);
+ }
+}
+''');
+ }
+
+ Future<void> test_parameter_optionalNamed() async {
+ await resolveTestCode('''
+void f({int? _foo}) {
+ print(_foo);
+}
+''');
+ await assertNoFix();
+ }
+
+ Future<void> test_parameter_optionalPositional() async {
+ await resolveTestCode('''
+void f([int? _foo]) {
+ print(_foo);
+}
+''');
+ await assertHasFix('''
+void f([int? foo]) {
+ print(foo);
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
index f92c463..deefa32 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
@@ -231,7 +231,7 @@
@override
String get lintCode => LintNames.type_init_formals;
- Future<void> test_void() async {
+ Future<void> test_formalFieldParameter() async {
await resolveTestCode('''
class C {
int f;
@@ -245,4 +245,23 @@
}
''');
}
+
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3210')
+ Future<void> test_superParameter() async {
+ // If this issue gets closed as "won't fix," remove this test.
+ await resolveTestCode('''
+class C {
+ C(int f);
+}
+class D extends C {
+ D(int super.f);
+}
+''');
+ await assertHasFix('''
+class C {
+ int f;
+ C(super.f);
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
new file mode 100644
index 0000000..171d193
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RemoveUnnecessaryLateBulkTest);
+ defineReflectiveTests(RemoveUnnecessaryLateTest);
+ });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.unnecessary_late;
+
+ Future<void> test_singleFile() async {
+ await resolveTestCode('''
+late String s1 = '';
+late final String s2 = '';
+''');
+ await assertHasFix('''
+String s1 = '';
+final String s2 = '';
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+ @override
+ String get lintCode => LintNames.unnecessary_late;
+
+ Future<void> test_static() async {
+ await resolveTestCode('''
+class C {
+ static late String s1 = '';
+}
+''');
+ await assertHasFix('''
+class C {
+ static String s1 = '';
+}
+''');
+ }
+
+ Future<void> test_topLevel() async {
+ await resolveTestCode('''
+late String s1 = '';
+''');
+ await assertHasFix('''
+String s1 = '';
+''');
+ }
+
+ Future<void> test_topLevel_multipleVariables_fixFirst() async {
+ await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+ await assertHasFix(
+ '''
+String s1 = '', s2 = '';
+''',
+ errorFilter: (error) => error.toString().contains('test.dart(21..27)'),
+ );
+ }
+
+ Future<void> test_topLevel_multipleVariables_fixSecond() async {
+ await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+ await assertHasFix(
+ '''
+String s1 = '', s2 = '';
+''',
+ errorFilter: (error) => error.toString().contains('test.dart(12..18)'),
+ );
+ }
+
+ Future<void> test_topLevel_multipleVariables_notAllHaveInitializer() async {
+ await resolveTestCode('''
+late String s1, s2 = '';
+''');
+ await assertNoFix();
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
index 6c5fb20..39f4ed5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
@@ -55,4 +55,23 @@
void f({int a = 1}) => null;
''');
}
+
+ Future<void> test_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C({int? i});
+}
+class D extends C {
+ D({int? super.i: 1});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({int? i});
+}
+class D extends C {
+ D({int? super.i = 1});
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_null_check_with_cast_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_null_check_with_cast_test.dart
new file mode 100644
index 0000000..d99e73f
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_null_check_with_cast_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ReplaceNullCheckWithCastBulkTest);
+ defineReflectiveTests(ReplaceNullCheckWithCastTest);
+ });
+}
+
+@reflectiveTest
+class ReplaceNullCheckWithCastBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.null_check_on_nullable_type_parameter;
+
+ Future<void> test_singleFile() async {
+ await resolveTestCode('''
+T f<T>(T? result) {
+ if (1==1) {
+ return result!;
+ } else {
+ return result!;
+ }
+}
+''');
+ await assertHasFix('''
+T f<T>(T? result) {
+ if (1==1) {
+ return result as T;
+ } else {
+ return result as T;
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class ReplaceNullCheckWithCastTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_NULL_CHECK_WITH_CAST;
+
+ @override
+ String get lintCode => LintNames.null_check_on_nullable_type_parameter;
+
+ Future<void> test_simpleIdentifier() async {
+ await resolveTestCode('''
+T run<T>(T? result) {
+ return result!;
+}
+''');
+ await assertHasFix('''
+T run<T>(T? result) {
+ return result as T;
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
index 818dad5..9f22bf1 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -11,11 +12,118 @@
void main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(ReplaceReturnTypeFutureLintBulkTest);
+ defineReflectiveTests(ReplaceReturnTypeFutureLintTest);
defineReflectiveTests(ReplaceReturnTypeFutureTest);
});
}
@reflectiveTest
+class ReplaceReturnTypeFutureLintBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.avoid_void_async;
+
+ Future<void> test_bulk() async {
+ await resolveTestCode('''
+void f1() async {}
+
+void f2() async => null;
+
+class C {
+ void m1() async {}
+
+ void m2() async => null;
+
+ void m3() async {
+ void f() async {};
+ f();
+ }
+}
+''');
+ await assertHasFix('''
+Future<void> f1() async {}
+
+Future<void> f2() async => null;
+
+class C {
+ Future<void> m1() async {}
+
+ Future<void> m2() async => null;
+
+ Future<void> m3() async {
+ Future<void> f() async {};
+ f();
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class ReplaceReturnTypeFutureLintTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_RETURN_TYPE_FUTURE;
+
+ @override
+ String get lintCode => LintNames.avoid_void_async;
+
+ Future<void> test_function() async {
+ await resolveTestCode('void f() async {}');
+ await assertHasFix('Future<void> f() async {}');
+ }
+
+ Future<void> test_functionInMethod() async {
+ await resolveTestCode('''
+class C {
+ void m() {
+ void f() async {};
+ f();
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ void m() {
+ Future<void> f() async {};
+ f();
+ }
+}
+''');
+ }
+
+ Future<void> test_functionReturnNull() async {
+ await resolveTestCode('void f() async => null;');
+ await assertHasFix('Future<void> f() async => null;');
+ }
+
+ Future<void> test_method() async {
+ await resolveTestCode('''
+class C {
+ void m() async {}
+}
+''');
+ await assertHasFix('''
+class C {
+ Future<void> m() async {}
+}
+''');
+ }
+
+ Future<void> test_methodReturnNull() async {
+ await resolveTestCode('''
+class C {
+ void m() async => null;
+}
+''');
+ await assertHasFix('''
+class C {
+ Future<void> m() async => null;
+}
+''');
+ }
+}
+
+@reflectiveTest
class ReplaceReturnTypeFutureTest extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.REPLACE_RETURN_TYPE_FUTURE;
@@ -55,6 +163,19 @@
});
}
+ Future<void> test_method() async {
+ await resolveTestCode('''
+class C {
+ int m() async {}
+}
+''');
+ await assertHasFix('''
+class C {
+ Future<int> m() async {}
+}
+''');
+ }
+
Future<void> test_simpleTypeName_withImport() async {
await resolveTestCode('''
import 'dart:async';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart b/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart
new file mode 100644
index 0000000..a1f240b
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SortConstructorFirstBulkTest);
+ defineReflectiveTests(SortConstructorFirstTest);
+ });
+}
+
+@reflectiveTest
+class SortConstructorFirstBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.sort_constructors_first;
+
+ Future<void> test_multiple_classes() async {
+ await resolveTestCode('''
+class A {
+ X() {}
+ A();
+}
+
+class B {
+ Y() {}
+ B();
+}
+''');
+ await assertHasFix('''
+class A {
+ A();
+ X() {}
+}
+
+class B {
+ B();
+ Y() {}
+}
+''');
+ }
+
+ Future<void> test_single_class() async {
+ await resolveTestCode('''
+class A {
+ X() {}
+
+ A();
+
+ Y() {}
+
+ A._();
+}
+''');
+ await assertHasFix('''
+class A {
+
+ A();
+
+ A._();
+ X() {}
+
+ Y() {}
+}
+''');
+ }
+}
+
+@reflectiveTest
+class SortConstructorFirstTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.SORT_CONSTRUCTOR_FIRST;
+
+ @override
+ String get lintCode => LintNames.sort_constructors_first;
+
+ Future<void> test_one_fix() async {
+ await resolveTestCode('''
+class A {
+ X() {}
+ A();
+}
+''');
+ await assertHasFix('''
+class A {
+ A();
+ X() {}
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/sort_unnamed_constructor_first_test.dart b/pkg/analysis_server/test/src/services/correction/fix/sort_unnamed_constructor_first_test.dart
new file mode 100644
index 0000000..9eddd90b
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/sort_unnamed_constructor_first_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SortUnnamedConstructorFirstBulkTest);
+ defineReflectiveTests(SortUnnamedConstructorFirstTest);
+ });
+}
+
+@reflectiveTest
+class SortUnnamedConstructorFirstBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.sort_unnamed_constructors_first;
+
+ Future<void> test_one_fix() async {
+ await resolveTestCode('''
+class A {
+ A.a();
+ A();
+}
+
+class B {
+ B.b();
+ B();
+}
+''');
+ await assertHasFix('''
+class A {
+ A();
+ A.a();
+}
+
+class B {
+ B();
+ B.b();
+}
+''');
+ }
+}
+
+@reflectiveTest
+class SortUnnamedConstructorFirstTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.SORT_UNNAMED_CONSTRUCTOR_FIRST;
+
+ @override
+ String get lintCode => LintNames.sort_unnamed_constructors_first;
+
+ Future<void> test_one_fix() async {
+ await resolveTestCode('''
+class A {
+ A.a();
+ A();
+}
+''');
+ await assertHasFix('''
+class A {
+ A();
+ A.a();
+}
+''');
+ }
+
+ Future<void> test_with_non_constructors() async {
+ await resolveTestCode('''
+class A {
+ static const int i = 0;
+
+ A.a();
+
+ A();
+}
+''');
+ await assertHasFix('''
+class A {
+ static const int i = 0;
+
+ A();
+
+ A.a();
+}
+''');
+ }
+
+ Future<void> test_with_non_constructors_2() async {
+ await resolveTestCode('''
+class A {
+ A.a();
+
+ static const int i = 0;
+
+ A();
+}
+''');
+ await assertHasFix('''
+class A {
+
+ A();
+ A.a();
+
+ static const int i = 0;
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 001e243..5997525 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -75,6 +75,7 @@
import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
import 'convert_to_on_type_test.dart' as convert_to_on_type;
import 'convert_to_package_import_test.dart' as convert_to_package_import;
+import 'convert_to_raw_string_test.dart' as convert_to_raw_string;
import 'convert_to_relative_import_test.dart' as convert_to_relative_import;
import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
import 'convert_to_single_quoted_string_test.dart'
@@ -143,6 +144,7 @@
import 'remove_if_null_operator_test.dart' as remove_if_null_operator;
import 'remove_initializer_test.dart' as remove_initializer;
import 'remove_interpolation_braces_test.dart' as remove_interpolation_braces;
+import 'remove_leading_underscore_test.dart' as remove_leading_underscore;
import 'remove_method_declaration_test.dart' as remove_method_declaration;
import 'remove_name_from_combinator_test.dart' as remove_name_from_combinator;
import 'remove_non_null_assertion_test.dart' as remove_non_null_assertion_test;
@@ -158,6 +160,7 @@
import 'remove_type_arguments_test.dart' as remove_type_arguments;
import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
+import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
import 'remove_unnecessary_parentheses_test.dart'
as remove_unnecessary_parentheses;
@@ -185,6 +188,7 @@
import 'replace_final_with_const_test.dart' as replace_final_with_const;
import 'replace_final_with_var_test.dart' as replace_final_with_var;
import 'replace_new_with_const_test.dart' as replace_new_with_const;
+import 'replace_null_check_with_cast_test.dart' as replace_null_check_with_cast;
import 'replace_null_with_closure_test.dart' as replace_null_with_closure;
import 'replace_return_type_future_test.dart' as replace_return_type_future;
import 'replace_return_type_iterable_test.dart' as replace_return_type_iterable;
@@ -206,6 +210,9 @@
import 'replace_with_tear_off_test.dart' as replace_with_tear_off;
import 'replace_with_var_test.dart' as replace_with_var;
import 'sort_child_property_last_test.dart' as sort_properties_last;
+import 'sort_constructor_first_test.dart' as sort_constructor_first_test;
+import 'sort_unnamed_constructor_first_test.dart'
+ as sort_unnamed_constructor_first_test;
import 'update_sdk_constraints_test.dart' as update_sdk_constraints;
import 'use_const_test.dart' as use_const;
import 'use_curly_braces_test.dart' as use_curly_braces;
@@ -278,6 +285,7 @@
convert_to_null_aware_spread.main();
convert_to_on_type.main();
convert_to_package_import.main();
+ convert_to_raw_string.main();
convert_to_relative_import.main();
convert_to_set_literal.main();
convert_to_single_quoted_string.main();
@@ -341,6 +349,7 @@
remove_if_null_operator.main();
remove_initializer.main();
remove_interpolation_braces.main();
+ remove_leading_underscore.main();
remove_method_declaration.main();
remove_name_from_combinator.main();
remove_non_null_assertion_test.main();
@@ -354,6 +363,7 @@
remove_type_arguments.main();
remove_unnecessary_cast.main();
remove_unnecessary_const.main();
+ remove_unnecessary_late.main();
remove_unnecessary_new.main();
remove_unnecessary_parentheses.main();
remove_unnecessary_raw_string.main();
@@ -375,6 +385,7 @@
replace_final_with_const.main();
replace_final_with_var.main();
replace_new_with_const.main();
+ replace_null_check_with_cast.main();
replace_null_with_closure.main();
replace_null_with_void.main();
replace_return_type.main();
@@ -396,6 +407,8 @@
replace_with_tear_off.main();
replace_with_var.main();
sort_properties_last.main();
+ sort_constructor_first_test.main();
+ sort_unnamed_constructor_first_test.main();
update_sdk_constraints.main();
use_const.main();
use_curly_braces.main();
diff --git a/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart b/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
index e8d35e3..c25bdcd 100644
--- a/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
+++ b/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
@@ -29,7 +29,7 @@
void _assertArgumentRange(int index, SourceRange expectedRange) {
var list = _argumentList;
- expect(range.nodeInListWithComments(testUnit.lineInfo!, list, list[index]),
+ expect(range.nodeInListWithComments(testUnit.lineInfo, list, list[index]),
expectedRange);
}
@@ -37,7 +37,7 @@
var class_ = findNode.classDeclaration('class');
var list = class_.members;
for (var entry in expectedRanges.entries) {
- expect(range.nodeWithComments(testUnit.lineInfo!, list[entry.key]),
+ expect(range.nodeWithComments(testUnit.lineInfo, list[entry.key]),
entry.value);
}
}
@@ -45,7 +45,7 @@
void _assertUnitRanges(Map<int, SourceRange> expectedRanges) {
var list = testUnit.declarations;
for (var entry in expectedRanges.entries) {
- expect(range.nodeWithComments(testUnit.lineInfo!, list[entry.key]),
+ expect(range.nodeWithComments(testUnit.lineInfo, list[entry.key]),
entry.value);
}
}
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 53e071c..d616586 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -125,7 +125,7 @@
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
var constructorName = creation.constructorName;
- var namedType = constructorName.type2;
+ var namedType = constructorName.type;
var argumentList = creation.argumentList;
expect(_flutter.identifyWidgetExpression(creation), creation);
expect(_flutter.identifyWidgetExpression(constructorName), creation);
@@ -142,7 +142,7 @@
var statement = statements[1] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
var constructorName = creation.constructorName;
- var namedType = constructorName.type2;
+ var namedType = constructorName.type;
var argumentList = creation.argumentList;
expect(_flutter.identifyWidgetExpression(creation), creation);
expect(_flutter.identifyWidgetExpression(constructorName), creation);
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 2f7a688..301c2ad 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -11,7 +12,6 @@
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
/// A runner that can request code completion at the location of each identifier
/// in a Dart file.
@@ -203,8 +203,8 @@
}
}
- List<CompletionSuggestion> _filterBy(
- List<CompletionSuggestion> suggestions, String pattern) {
+ List<CompletionSuggestionBuilder> _filterBy(
+ List<CompletionSuggestionBuilder> suggestions, String pattern) {
return suggestions
.where((suggestion) => suggestion.completion.startsWith(pattern))
.toList();
@@ -220,7 +220,8 @@
/// If the given list of [suggestions] includes a suggestion for the given
/// [identifier], return the index of the suggestion. Otherwise, return `-1`.
- int _indexOf(List<CompletionSuggestion> suggestions, String identifier) {
+ int _indexOf(
+ List<CompletionSuggestionBuilder> suggestions, String identifier) {
for (var i = 0; i < suggestions.length; i++) {
if (suggestions[i].completion == identifier) {
return i;
@@ -237,7 +238,7 @@
}
/// Print information about the given [suggestions].
- void _printSuggestions(List<CompletionSuggestion> suggestions) {
+ void _printSuggestions(List<CompletionSuggestionBuilder> suggestions) {
if (suggestions.isEmpty) {
output.writeln(' No suggestions');
return;
@@ -248,7 +249,8 @@
}
}
- List<CompletionSuggestion> _sort(List<CompletionSuggestion> suggestions) {
+ List<CompletionSuggestionBuilder> _sort(
+ List<CompletionSuggestionBuilder> suggestions) {
suggestions.sort((first, second) => second.relevance - first.relevance);
return suggestions;
}
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index a674281..7de5c96 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -404,8 +404,7 @@
void _runPub(String filePath) {
var directoryPath = path.dirname(filePath);
if (Directory(directoryPath).existsSync()) {
- Process.runSync(
- '/Users/brianwilkerson/Dev/dart/dart-sdk/bin/pub', ['get'],
+ Process.runSync(Platform.resolvedExecutable, ['pub', 'get'],
workingDirectory: directoryPath);
}
}
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 3e5769cc..bdc3ae4 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -26,6 +26,7 @@
import 'socket_server_test.dart' as socket_server;
import 'src/test_all.dart' as src;
import 'tool/test_all.dart' as tool;
+import 'verify_error_fix_status_test.dart' as verify_error_fix_status;
import 'verify_no_solo_test.dart' as verify_no_solo;
import 'verify_sorted_test.dart' as verify_sorted;
import 'verify_tests_test.dart' as verify_tests;
@@ -53,6 +54,7 @@
socket_server.main();
src.main();
tool.main();
+ verify_error_fix_status.main();
verify_no_solo.main();
verify_sorted.main();
verify_tests.main();
diff --git a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
index a424ae1..65bb7ae 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
@@ -15,8 +15,13 @@
Matcher isMapOf(Matcher indexMatcher, Matcher valueMatcher) =>
MapTypeMatcher(wrapMatcher(indexMatcher), wrapMatcher(valueMatcher));
-Matcher isResponseError(ErrorCodes code) => const TypeMatcher<ResponseError>()
- .having((e) => e.code, 'code', equals(code));
+Matcher isResponseError(ErrorCodes code, {String? message}) {
+ final matcher = const TypeMatcher<ResponseError>()
+ .having((e) => e.code, 'code', equals(code));
+ return message != null
+ ? matcher.having((e) => e.message, 'message', equals(message))
+ : matcher;
+}
Matcher isSimpleType(String name) => SimpleTypeMatcher(name);
diff --git a/pkg/analysis_server/test/verify_error_fix_status_test.dart b/pkg/analysis_server/test/verify_error_fix_status_test.dart
new file mode 100644
index 0000000..9da6ca2
--- /dev/null
+++ b/pkg/analysis_server/test/verify_error_fix_status_test.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/lint/registry.dart';
+import 'package:analyzer_utilities/package_root.dart' as package_root;
+import 'package:linter/src/rules.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:yaml/yaml.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(VerifyErrorFixStatusTest);
+ });
+}
+
+@reflectiveTest
+class VerifyErrorFixStatusTest {
+ PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
+
+ void test_statusFile() {
+ var statusInfo = _statusInfo();
+ var errorCodeNames = _errorCodeNames();
+ var lintRuleNames = _lintRuleNames();
+
+ var errorData = _ErrorData();
+ for (var code in errorCodeValues) {
+ var name = code.uniqueName;
+ if (name.startsWith('TodoCode.')) {
+ // To-do codes are ignored.
+ } else {
+ var info = statusInfo.nodes[name];
+ if (info == null) {
+ errorData.codesWithNoEntry.add(name);
+ } else if (info is YamlMap) {
+ var markedAsHavingFix = info['status'] == 'hasFix';
+ var hasFix = _hasCodeFix(code);
+ if (hasFix) {
+ if (!markedAsHavingFix) {
+ errorData.codesWithFixes.add(name);
+ }
+ } else {
+ if (markedAsHavingFix) {
+ errorData.codesWithoutFixes.add(name);
+ }
+ }
+ }
+ }
+ }
+ for (var name in lintRuleNames) {
+ var info = statusInfo.nodes[name];
+ if (info == null) {
+ errorData.codesWithNoEntry.add(name);
+ } else if (info is YamlMap) {
+ var markedAsHavingFix = info['status'] == 'hasFix';
+ var hasFix = _hasLintFix(name);
+ if (hasFix) {
+ if (!markedAsHavingFix) {
+ errorData.codesWithFixes.add(name);
+ }
+ } else {
+ if (markedAsHavingFix) {
+ errorData.codesWithoutFixes.add(name);
+ }
+ }
+ }
+ }
+
+ for (var key in statusInfo.keys) {
+ if (key is String) {
+ if (!errorCodeNames.contains(key) && !lintRuleNames.contains(key)) {
+ errorData.entriesWithNoCode.add(key);
+ }
+ }
+ }
+
+ if (errorData.isNotEmpty) {
+ fail(_failureMessage(errorData));
+ }
+ }
+
+ /// Return the unique names of the error codes.
+ Set<String> _errorCodeNames() {
+ var codes = errorCodeValues;
+ var codeNames = <String>{};
+ for (var code in codes) {
+ codeNames.add(code.uniqueName);
+ }
+ return codeNames;
+ }
+
+ /// Return a failure message composed from the given lists.
+ String _failureMessage(_ErrorData errorData) {
+ var buffer = StringBuffer();
+ var needsBlankLine = false;
+ if (errorData.codesWithNoEntry.isNotEmpty) {
+ buffer.writeln('Add the following entries:');
+ buffer.writeln();
+ for (var code in errorData.codesWithNoEntry) {
+ buffer.writeln('$code:');
+ buffer.writeln(' status: needsEvaluation');
+ }
+ needsBlankLine = true;
+ }
+ if (errorData.entriesWithNoCode.isNotEmpty) {
+ if (needsBlankLine) {
+ buffer.writeln();
+ }
+ buffer.writeln('Remove the following entries:');
+ for (var code in errorData.entriesWithNoCode) {
+ buffer.writeln('- $code');
+ }
+ needsBlankLine = true;
+ }
+ if (errorData.codesWithFixes.isNotEmpty) {
+ if (needsBlankLine) {
+ buffer.writeln();
+ }
+ buffer.writeln('Mark the following entries as having fixes:');
+ for (var code in errorData.codesWithFixes) {
+ buffer.writeln('- $code');
+ }
+ needsBlankLine = true;
+ }
+ if (errorData.codesWithoutFixes.isNotEmpty) {
+ if (needsBlankLine) {
+ buffer.writeln();
+ }
+ buffer.writeln('Mark the following entries as not having fixes:');
+ for (var code in errorData.codesWithoutFixes) {
+ buffer.writeln('- $code');
+ }
+ needsBlankLine = true;
+ }
+ return buffer.toString();
+ }
+
+ /// Return `true` if the given error [code] has a fix associated with it.
+ bool _hasCodeFix(ErrorCode code) {
+ var producers = FixProcessor.nonLintProducerMap[code];
+ if (producers != null) {
+ return true;
+ }
+ var multiProducers = FixProcessor.nonLintMultiProducerMap[code];
+ if (multiProducers != null) {
+ for (var producer in multiProducers) {
+ if (producer is! DataDriven) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// Return `true` if the lint with the given name has a fix associated with
+ /// it.
+ bool _hasLintFix(String codeName) {
+ var name = codeName.substring('LintCode.'.length);
+ var producers = FixProcessor.lintProducerMap[name];
+ return producers != null;
+ }
+
+ /// Return the unique names of the lint rules.
+ Set<String> _lintRuleNames() {
+ registerLintRules();
+ var ruleNames = <String>{};
+ for (var rule in Registry.ruleRegistry.rules) {
+ for (var code in rule.lintCodes) {
+ ruleNames.add(code.uniqueName);
+ }
+ }
+ return ruleNames;
+ }
+
+ /// Return the path to the file containing the status information.
+ String _statusFilePath() {
+ var pathContext = resourceProvider.pathContext;
+ var packageRoot = pathContext.normalize(package_root.packageRoot);
+ return pathContext.join(packageRoot, 'analysis_server', 'lib', 'src',
+ 'services', 'correction', 'error_fix_status.yaml');
+ }
+
+ /// Return the content of the file containing the status information, parsed
+ /// as a YAML map.
+ YamlMap _statusInfo() {
+ var statusFile = resourceProvider.getFile(_statusFilePath());
+ var document = loadYamlDocument(statusFile.readAsStringSync());
+ var statusInfo = document.contents;
+ if (statusInfo is! YamlMap) {
+ fail('Expected a YamlMap, found ${statusInfo.runtimeType}');
+ }
+ return statusInfo;
+ }
+}
+
+class _ErrorData {
+ final List<String> codesWithFixes = [];
+ final List<String> codesWithNoEntry = [];
+ final List<String> codesWithoutFixes = [];
+ final List<String> entriesWithNoCode = [];
+
+ bool get isNotEmpty =>
+ codesWithFixes.isNotEmpty ||
+ codesWithNoEntry.isNotEmpty ||
+ codesWithoutFixes.isNotEmpty ||
+ entriesWithNoCode.isNotEmpty;
+}
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index bcde125..37de909 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_test.dart
@@ -27,6 +27,10 @@
group('analyzer_plugin', () {
buildTestsForAnalyzerPlugin();
});
+
+ group('nnbd_migration', () {
+ buildTestsForNnbdMigration();
+ });
}
void buildTests({
@@ -116,6 +120,12 @@
);
}
+void buildTestsForNnbdMigration() {
+ buildTests(
+ packagePath: 'nnbd_migration',
+ excludedPaths: ['lib/src/front_end/resources/resources.g.dart']);
+}
+
void buildTestsIn(AnalysisSession session, String testDirPath,
List<String> excludedPath, Folder directory) {
var pathContext = session.resourceProvider.pathContext;
diff --git a/pkg/analysis_server/tool/code_completion/code_metrics.dart b/pkg/analysis_server/tool/code_completion/code_metrics.dart
index da9d00b..cdfd1df 100644
--- a/pkg/analysis_server/tool/code_completion/code_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/code_metrics.dart
@@ -326,7 +326,7 @@
'abstractKeyword': node.abstractKeyword,
'name': node.name,
'typeParameters': node.typeParameters,
- 'superclass': node.superclass2,
+ 'superclass': node.superclass,
'withClause': node.withClause,
'implementsClause': node.implementsClause,
});
@@ -409,7 +409,7 @@
@override
void visitConstructorName(ConstructorName node) {
_visitChildren(node, {
- 'type': node.type2,
+ 'type': node.type,
'name': node.name,
});
super.visitConstructorName(node);
@@ -531,7 +531,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
_visitChildren(node, {
- 'superclass': node.superclass2,
+ 'superclass': node.superclass,
});
super.visitExtendsClause(node);
}
@@ -775,7 +775,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
_visitChildren(node, {
- 'interfaces': node.interfaces2,
+ 'interfaces': node.interfaces,
});
super.visitImplementsClause(node);
}
@@ -986,7 +986,7 @@
@override
void visitOnClause(OnClause node) {
_visitChildren(node, {
- 'superclassConstraints': node.superclassConstraints2,
+ 'superclassConstraints': node.superclassConstraints,
});
super.visitOnClause(node);
}
@@ -1286,7 +1286,7 @@
@override
void visitWithClause(WithClause node) {
_visitChildren(node, {
- 'mixinTypes': node.mixinTypes2,
+ 'mixinTypes': node.mixinTypes,
});
super.visitWithClause(node);
}
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 7007b15..d6f8764 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1217,11 +1217,14 @@
var budget = CompletionBudget(Duration(seconds: 30));
if (declarationsTracker == null) {
// available suggestions == false
- suggestions = await DartCompletionManager(
- budget: budget,
- listener: listener,
- notImportedSuggestions: notImportedSuggestions)
- .computeSuggestions(dartRequest, performance);
+ var serverSuggestions = await DartCompletionManager(
+ budget: budget,
+ listener: listener,
+ notImportedSuggestions: notImportedSuggestions,
+ ).computeSuggestions(dartRequest, performance);
+ suggestions = serverSuggestions.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
} else {
// available suggestions == true
var includedElementKinds = <protocol.ElementKind>{};
@@ -1229,13 +1232,16 @@
var includedSuggestionRelevanceTagList =
<protocol.IncludedSuggestionRelevanceTag>[];
var includedSuggestionSetList = <protocol.IncludedSuggestionSet>[];
- suggestions = await DartCompletionManager(
+ var serverSuggestions = await DartCompletionManager(
budget: budget,
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTagList,
listener: listener,
).computeSuggestions(dartRequest, performance);
+ suggestions = serverSuggestions.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
computeIncludedSetList(declarationsTracker, dartRequest,
includedSuggestionSetList, includedElementNames);
@@ -1923,7 +1929,8 @@
String? missingCompletionLocationTable;
@override
- void builtSuggestion(protocol.CompletionSuggestion suggestion) {
+ void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder) {
+ var suggestion = suggestionBuilder.build();
featureMap[suggestion] = cachedFeatures;
cachedFeatures = noFeatures;
}
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 157e2be..97f3c5c 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
@@ -456,7 +456,7 @@
void visitClassTypeAlias(ClassTypeAlias node) {
var wasInGenericContext = inGenericContext;
inGenericContext = inGenericContext || node.typeParameters != null;
- _recordDataForNode('ClassTypeAlias (superclass)', node.superclass2);
+ _recordDataForNode('ClassTypeAlias (superclass)', node.superclass);
var context = 'superclass';
_recordTokenType('ClassDeclaration ($context)', node.withClause);
context = 'with';
@@ -646,7 +646,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
- _recordDataForNode('ExtendsClause (type)', node.superclass2);
+ _recordDataForNode('ExtendsClause (type)', node.superclass);
super.visitExtendsClause(node);
}
@@ -845,7 +845,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
// At the start of each type name.
- for (var namedType in node.interfaces2) {
+ for (var namedType in node.interfaces) {
_recordDataForNode('ImplementsClause (type)', namedType);
}
super.visitImplementsClause(node);
@@ -1068,7 +1068,7 @@
@override
void visitOnClause(OnClause node) {
- for (var constraint in node.superclassConstraints2) {
+ for (var constraint in node.superclassConstraints) {
_recordDataForNode('OnClause (type)', constraint);
}
super.visitOnClause(node);
@@ -1351,7 +1351,7 @@
@override
void visitWithClause(WithClause node) {
- for (var namedType in node.mixinTypes2) {
+ for (var namedType in node.mixinTypes) {
_recordDataForNode('WithClause (type)', namedType);
}
super.visitWithClause(node);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 7111493..a50093b 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -463,7 +463,7 @@
@override
void visitClassTypeAlias(ClassTypeAlias node) {
- _recordDataForNode('ClassTypeAlias_superclass', node.superclass2);
+ _recordDataForNode('ClassTypeAlias_superclass', node.superclass);
var context = 'superclass';
_recordKeyword('ClassTypeAlias_$context', node.withClause);
context = 'with';
@@ -643,7 +643,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
- _recordDataForNode('ExtendsClause_superclass', node.superclass2);
+ _recordDataForNode('ExtendsClause_superclass', node.superclass);
super.visitExtendsClause(node);
}
@@ -819,7 +819,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
// At the start of each type name.
- for (var namedType in node.interfaces2) {
+ for (var namedType in node.interfaces) {
_recordDataForNode('ImplementsClause_interface', namedType);
}
super.visitImplementsClause(node);
@@ -998,7 +998,7 @@
@override
void visitOnClause(OnClause node) {
- for (var constraint in node.superclassConstraints2) {
+ for (var constraint in node.superclassConstraints) {
_recordDataForNode('OnClause_superclassConstraint', constraint);
}
super.visitOnClause(node);
@@ -1251,7 +1251,7 @@
@override
void visitWithClause(WithClause node) {
- for (var namedType in node.mixinTypes2) {
+ for (var namedType in node.mixinTypes) {
_recordDataForNode('WithClause_mixinType', namedType);
}
super.visitWithClause(node);
diff --git a/pkg/analysis_server/tool/code_completion/visitors.dart b/pkg/analysis_server/tool/code_completion/visitors.dart
index f65c8b6..5783758 100644
--- a/pkg/analysis_server/tool/code_completion/visitors.dart
+++ b/pkg/analysis_server/tool/code_completion/visitors.dart
@@ -653,7 +653,7 @@
if (constructorName is ConstructorName) {
var instanceCreationExpression = constructorName.parent;
if (instanceCreationExpression is InstanceCreationExpression &&
- constructorName.type2.name == node) {
+ constructorName.type.name == node) {
if (instanceCreationExpression.keyword != null ||
constructorName.name == null) {
elementKind = protocol.ElementKind.CONSTRUCTOR;
diff --git a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
index f6cf4f0..3c16118 100644
--- a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
+++ b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
@@ -71,7 +71,7 @@
writeln(';');
}
- /// Generate all of the constants associates with the [api].
+ /// Generate all of the constants associated with the [api].
void generateConstants() {
writeln("const String PROTOCOL_VERSION = '${api.version}';");
writeln();
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 3d8e563..d2dda69 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -216,12 +216,12 @@
* not be analyzed.
* @param packageRoots A mapping from source directories to package roots that should override the
* normal package: URI resolution mechanism. If a package root is a file, then the analyzer
- * will behave as though that file is a ".packages" file in the source directory. The
- * effect is the same as specifying the file as a "--packages" parameter to the Dart VM
- * when executing any Dart file inside the source directory. Files in any directories that
- * are not overridden by this mapping have their package: URI's resolved using the normal
- * pubspec.yaml mechanism. If this field is absent, or the empty map is specified, that
- * indicates that the normal pubspec.yaml mechanism should always be used.
+ * will behave as though that file is a ".dart_tool/package_config.json" file in the source
+ * directory. The effect is the same as specifying the file as a "--packages" parameter to
+ * the Dart VM when executing any Dart file inside the source directory. Files in any
+ * directories that are not overridden by this mapping have their package: URI's resolved
+ * using the normal pubspec.yaml mechanism. If this field is absent, or the empty map is
+ * specified, that indicates that the normal pubspec.yaml mechanism should always be used.
*/
public void analysis_setAnalysisRoots(List<String> included, List<String> excluded, Map<String, String> packageRoots);
@@ -440,6 +440,8 @@
* @param offset The offset within the file at which suggestions are to be made.
* @param maxResults The maximum number of suggestions to return. If the number of suggestions
* after filtering is greater than the maxResults, then isIncomplete is set to true.
+ * @param completionCaseMatchingMode The mode of code completion being invoked. If no value is
+ * provided, MATCH_FIRST_CHAR will be assumed.
* @param completionMode The mode of code completion being invoked. If no value is provided, BASIC
* will be assumed. BASIC is also the only currently supported.
* @param invocationCount The number of times that the user has invoked code completion at the same
@@ -449,7 +451,7 @@
* field is intended to be used for benchmarking, and usually should not be provided, so
* that the default timeout is used.
*/
- public void completion_getSuggestions2(String file, int offset, int maxResults, String completionMode, int invocationCount, int timeout, GetSuggestions2Consumer consumer);
+ public void completion_getSuggestions2(String file, int offset, int maxResults, String completionCaseMatchingMode, String completionMode, int invocationCount, int timeout, GetSuggestions2Consumer consumer);
/**
* {@code completion.registerLibraryPaths}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionCaseMatchingMode.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionCaseMatchingMode.java
new file mode 100644
index 0000000..3a4dc2a
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionCaseMatchingMode.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+/**
+ * An enumeration of the character case matching modes that the user may set in the client.
+ *
+ * @coverage dart.server.generated.types
+ */
+public class CompletionCaseMatchingMode {
+
+ /**
+ * Match the first character case only when filtering completions, the default for this
+ * enumeration.
+ */
+ public static final String FIRST_CHAR = "FIRST_CHAR";
+
+ /**
+ * Match all character cases when filtering completion lists.
+ */
+ public static final String ALL_CHARS = "ALL_CHARS";
+
+ /**
+ * Do not match character cases when filtering completion lists.
+ */
+ public static final String NONE = "NONE";
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index f73aa41..9bc6c74 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -176,6 +176,21 @@
private final String parameterType;
/**
+ * This field is omitted if getSuggestions was used rather than getSuggestions2.
+ *
+ * This field is omitted if this suggestion corresponds to a locally declared element.
+ *
+ * If this suggestion corresponds to an already imported element, then this field is the URI of a
+ * library that provides this element, not the URI of the library where the element is declared.
+ *
+ * If this suggestion corresponds to an element from a not yet imported library, this field is the
+ * URI of a library that could be imported to make this suggestion accessible in the file where
+ * completion was requested, such as package:foo/bar.dart or
+ * file:///home/me/workspace/foo/test/bar_test.dart.
+ */
+ private final String libraryUri;
+
+ /**
* True if the suggestion is for an element from a not yet imported library. This field is omitted
* if the element is declared locally, or is from library is already imported, so that the
* suggestion can be inserted as is, or if getSuggestions was used rather than getSuggestions2.
@@ -185,7 +200,7 @@
/**
* Constructor for {@link CompletionSuggestion}.
*/
- public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Boolean isNotImported) {
+ public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String libraryUri, Boolean isNotImported) {
this.kind = kind;
this.relevance = relevance;
this.completion = completion;
@@ -209,6 +224,7 @@
this.hasNamedParameters = hasNamedParameters;
this.parameterName = parameterName;
this.parameterType = parameterType;
+ this.libraryUri = libraryUri;
this.isNotImported = isNotImported;
}
@@ -240,6 +256,7 @@
ObjectUtilities.equals(other.hasNamedParameters, hasNamedParameters) &&
ObjectUtilities.equals(other.parameterName, parameterName) &&
ObjectUtilities.equals(other.parameterType, parameterType) &&
+ ObjectUtilities.equals(other.libraryUri, libraryUri) &&
ObjectUtilities.equals(other.isNotImported, isNotImported);
}
return false;
@@ -269,8 +286,9 @@
Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
+ String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
Boolean isNotImported = jsonObject.get("isNotImported") == null ? null : jsonObject.get("isNotImported").getAsBoolean();
- return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, isNotImported);
+ return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, libraryUri, isNotImported);
}
public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -391,6 +409,23 @@
}
/**
+ * This field is omitted if getSuggestions was used rather than getSuggestions2.
+ *
+ * This field is omitted if this suggestion corresponds to a locally declared element.
+ *
+ * If this suggestion corresponds to an already imported element, then this field is the URI of a
+ * library that provides this element, not the URI of the library where the element is declared.
+ *
+ * If this suggestion corresponds to an element from a not yet imported library, this field is the
+ * URI of a library that could be imported to make this suggestion accessible in the file where
+ * completion was requested, such as package:foo/bar.dart or
+ * file:///home/me/workspace/foo/test/bar_test.dart.
+ */
+ public String getLibraryUri() {
+ return libraryUri;
+ }
+
+ /**
* The name of the optional parameter being suggested. This field is omitted if the suggestion is
* not the addition of an optional argument within an argument list.
*/
@@ -505,6 +540,7 @@
builder.append(hasNamedParameters);
builder.append(parameterName);
builder.append(parameterType);
+ builder.append(libraryUri);
builder.append(isNotImported);
return builder.toHashCode();
}
@@ -578,6 +614,9 @@
if (parameterType != null) {
jsonObject.addProperty("parameterType", parameterType);
}
+ if (libraryUri != null) {
+ jsonObject.addProperty("libraryUri", libraryUri);
+ }
if (isNotImported != null) {
jsonObject.addProperty("isNotImported", isNotImported);
}
@@ -634,6 +673,8 @@
builder.append(parameterName + ", ");
builder.append("parameterType=");
builder.append(parameterType + ", ");
+ builder.append("libraryUri=");
+ builder.append(libraryUri + ", ");
builder.append("isNotImported=");
builder.append(isNotImported);
builder.append("]");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Element.java b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
index 0648fc7..690f101 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Element.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
@@ -101,15 +101,9 @@
private final String aliasedType;
/**
- * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
- * defined.
- */
- private final String libraryUri;
-
- /**
* Constructor for {@link Element}.
*/
- public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType, String libraryUri) {
+ public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType) {
this.kind = kind;
this.name = name;
this.location = location;
@@ -118,7 +112,6 @@
this.returnType = returnType;
this.typeParameters = typeParameters;
this.aliasedType = aliasedType;
- this.libraryUri = libraryUri;
}
@Override
@@ -133,8 +126,7 @@
ObjectUtilities.equals(other.parameters, parameters) &&
ObjectUtilities.equals(other.returnType, returnType) &&
ObjectUtilities.equals(other.typeParameters, typeParameters) &&
- ObjectUtilities.equals(other.aliasedType, aliasedType) &&
- ObjectUtilities.equals(other.libraryUri, libraryUri);
+ ObjectUtilities.equals(other.aliasedType, aliasedType);
}
return false;
}
@@ -148,8 +140,7 @@
String returnType = jsonObject.get("returnType") == null ? null : jsonObject.get("returnType").getAsString();
String typeParameters = jsonObject.get("typeParameters") == null ? null : jsonObject.get("typeParameters").getAsString();
String aliasedType = jsonObject.get("aliasedType") == null ? null : jsonObject.get("aliasedType").getAsString();
- String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
- return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType, libraryUri);
+ return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType);
}
public static List<Element> fromJsonArray(JsonArray jsonArray) {
@@ -194,14 +185,6 @@
}
/**
- * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
- * defined.
- */
- public String getLibraryUri() {
- return libraryUri;
- }
-
- /**
* The location of the name in the declaration of the element.
*/
public Location getLocation() {
@@ -252,7 +235,6 @@
builder.append(returnType);
builder.append(typeParameters);
builder.append(aliasedType);
- builder.append(libraryUri);
return builder.toHashCode();
}
@@ -300,9 +282,6 @@
if (aliasedType != null) {
jsonObject.addProperty("aliasedType", aliasedType);
}
- if (libraryUri != null) {
- jsonObject.addProperty("libraryUri", libraryUri);
- }
return jsonObject;
}
@@ -325,9 +304,7 @@
builder.append("typeParameters=");
builder.append(typeParameters + ", ");
builder.append("aliasedType=");
- builder.append(aliasedType + ", ");
- builder.append("libraryUri=");
- builder.append(libraryUri);
+ builder.append(aliasedType);
builder.append("]");
return builder.toString();
}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
index c315c1c..e858201 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/LinkedEditGroup.java
@@ -40,7 +40,8 @@
public static final List<LinkedEditGroup> EMPTY_LIST = Lists.newArrayList();
/**
- * The positions of the regions that should be edited simultaneously.
+ * The positions of the regions (after applying the relevant edits) that should be edited
+ * simultaneously.
*/
private final List<Position> positions;
@@ -102,7 +103,8 @@
}
/**
- * The positions of the regions that should be edited simultaneously.
+ * The positions of the regions (after applying the relevant edits) that should be edited
+ * simultaneously.
*/
public List<Position> getPositions() {
return positions;
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 51f35a4..5c07676 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- <version>1.32.9</version>
+ <version>1.32.10</version>
</h1>
<p>
This document contains a specification of the API provided by the
@@ -134,6 +134,10 @@
ignoring the item or treating it with some default/fallback handling.
</p>
<h3>Changelog</h3>
+<h4>1.32.10</h4>
+<ul>
+ <li>The <tt>MOVE_FILE</tt> refactor now supports moving/renaming folders.</li>
+</ul>
<h4>1.32.8</h4>
<ul>
<li>Added <tt>server.cancelRequest</tt> to allow clients to request cancellation
@@ -866,7 +870,8 @@
</p>
<p>
If a package root is a file, then the analyzer
- will behave as though that file is a ".packages" file in the
+ will behave as though that file is a
+ ".dart_tool/package_config.json" file in the
source directory. The effect is the same as specifying the file
as a "--packages" parameter to the Dart VM when
executing any Dart file inside the source directory.
@@ -1507,6 +1512,13 @@
then <tt>isIncomplete</tt> is set to <tt>true</tt>.
</p>
</field>
+ <field name="completionCaseMatchingMode" optional="true">
+ <ref>CompletionCaseMatchingMode</ref>
+ <p>
+ The mode of code completion being invoked. If no value is provided,
+ <tt>MATCH_FIRST_CHAR</tt> will be assumed.
+ </p>
+ </field>
<field name="completionMode" experimental="true" optional="true">
<ref>CompletionMode</ref>
<p>
@@ -4146,6 +4158,32 @@
</value>
</enum>
</type>
+ <type name="CompletionCaseMatchingMode">
+ <p>
+ An enumeration of the character case matching modes that the user may set in the client.
+ </p>
+ <enum>
+ <value>
+ <code>FIRST_CHAR</code>
+ <p>
+ Match the first character case only when filtering completions, the default for this
+ enumeration.
+ </p>
+ </value>
+ <value>
+ <code>ALL_CHARS</code>
+ <p>
+ Match all character cases when filtering completion lists.
+ </p>
+ </value>
+ <value>
+ <code>NONE</code>
+ <p>
+ Do not match character cases when filtering completion lists.
+ </p>
+ </value>
+ </enum>
+ </type>
<type name="RuntimeCompletionExpression">
<p>
An expression for which we want to know its runtime type.
@@ -5874,10 +5912,15 @@
</refactoring>
<refactoring kind="MOVE_FILE">
<p>
- Move the given file and update all of the references to that file
- and from it. The move operation is supported in general case - for
- renaming a file in the same folder, moving it to a different folder
- or both.
+ Move the given file or folder and update all of the references to
+ and from it. The move operation is supported in general case -
+ for renaming an item in the same folder, moving it to a different
+ folder or both.
+
+ Moving or renaming large folders may take time and clients should
+ consider showing an indicator to the user with the ability to
+ cancel the request (which can be done using
+ <tt>server.cancelRequest</tt>).
</p>
<p>
The refactoring must be activated before an actual file moving
diff --git a/pkg/analysis_server_client/OWNERS b/pkg/analysis_server_client/OWNERS
new file mode 100644
index 0000000..1592b3e
--- /dev/null
+++ b/pkg/analysis_server_client/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_ANALYZER
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index c1a528b..97e7427 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -612,6 +612,23 @@
/// if the parameterName field is omitted.
String? parameterType;
+ /// This field is omitted if getSuggestions was used rather than
+ /// getSuggestions2.
+ ///
+ /// This field is omitted if this suggestion corresponds to a locally
+ /// declared element.
+ ///
+ /// If this suggestion corresponds to an already imported element, then this
+ /// field is the URI of a library that provides this element, not the URI of
+ /// the library where the element is declared.
+ ///
+ /// If this suggestion corresponds to an element from a not yet imported
+ /// library, this field is the URI of a library that could be imported to
+ /// make this suggestion accessible in the file where completion was
+ /// requested, such as package:foo/bar.dart or
+ /// file:///home/me/workspace/foo/test/bar_test.dart.
+ String? libraryUri;
+
/// True if the suggestion is for an element from a not yet imported library.
/// This field is omitted if the element is declared locally, or is from
/// library is already imported, so that the suggestion can be inserted as
@@ -642,6 +659,7 @@
this.hasNamedParameters,
this.parameterName,
this.parameterType,
+ this.libraryUri,
this.isNotImported});
factory CompletionSuggestion.fromJson(
@@ -781,6 +799,11 @@
parameterType = jsonDecoder.decodeString(
jsonPath + '.parameterType', json['parameterType']);
}
+ String? libraryUri;
+ if (json.containsKey('libraryUri')) {
+ libraryUri = jsonDecoder.decodeString(
+ jsonPath + '.libraryUri', json['libraryUri']);
+ }
bool? isNotImported;
if (json.containsKey('isNotImported')) {
isNotImported = jsonDecoder.decodeBool(
@@ -804,6 +827,7 @@
hasNamedParameters: hasNamedParameters,
parameterName: parameterName,
parameterType: parameterType,
+ libraryUri: libraryUri,
isNotImported: isNotImported);
} else {
throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
@@ -884,6 +908,10 @@
if (parameterType != null) {
result['parameterType'] = parameterType;
}
+ var libraryUri = this.libraryUri;
+ if (libraryUri != null) {
+ result['libraryUri'] = libraryUri;
+ }
var isNotImported = this.isNotImported;
if (isNotImported != null) {
result['isNotImported'] = isNotImported;
@@ -923,6 +951,7 @@
hasNamedParameters == other.hasNamedParameters &&
parameterName == other.parameterName &&
parameterType == other.parameterType &&
+ libraryUri == other.libraryUri &&
isNotImported == other.isNotImported;
}
return false;
@@ -953,6 +982,7 @@
hasNamedParameters,
parameterName,
parameterType,
+ libraryUri,
isNotImported,
]);
}
@@ -1234,17 +1264,12 @@
/// this field will not be defined.
String? aliasedType;
- /// If the element belongs to a library, the URI of the library. Otherwise,
- /// this field will not be defined.
- String? libraryUri;
-
Element(this.kind, this.name, this.flags,
{this.location,
this.parameters,
this.returnType,
this.typeParameters,
- this.aliasedType,
- this.libraryUri});
+ this.aliasedType});
factory Element.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1294,18 +1319,12 @@
aliasedType = jsonDecoder.decodeString(
jsonPath + '.aliasedType', json['aliasedType']);
}
- String? libraryUri;
- if (json.containsKey('libraryUri')) {
- libraryUri = jsonDecoder.decodeString(
- jsonPath + '.libraryUri', json['libraryUri']);
- }
return Element(kind, name, flags,
location: location,
parameters: parameters,
returnType: returnType,
typeParameters: typeParameters,
- aliasedType: aliasedType,
- libraryUri: libraryUri);
+ aliasedType: aliasedType);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Element', json);
}
@@ -1344,10 +1363,6 @@
if (aliasedType != null) {
result['aliasedType'] = aliasedType;
}
- var libraryUri = this.libraryUri;
- if (libraryUri != null) {
- result['libraryUri'] = libraryUri;
- }
return result;
}
@@ -1364,8 +1379,7 @@
parameters == other.parameters &&
returnType == other.returnType &&
typeParameters == other.typeParameters &&
- aliasedType == other.aliasedType &&
- libraryUri == other.libraryUri;
+ aliasedType == other.aliasedType;
}
return false;
}
@@ -1380,7 +1394,6 @@
returnType,
typeParameters,
aliasedType,
- libraryUri,
);
}
@@ -2702,7 +2715,8 @@
///
/// Clients may not extend, implement or mix-in this class.
class LinkedEditGroup implements HasToJson {
- /// The positions of the regions that should be edited simultaneously.
+ /// The positions of the regions (after applying the relevant edits) that
+ /// should be edited simultaneously.
List<Position> positions;
/// The length of the regions that should be edited simultaneously.
@@ -4359,8 +4373,14 @@
}
/// Adds [edit] to the [FileEdit] for the given [file].
- void addEdit(String file, int fileStamp, SourceEdit edit) =>
- addEditToSourceChange(this, file, fileStamp, edit);
+ ///
+ /// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+ /// other edits will be inserted such that they appear before them in the
+ /// resulting document.
+ void addEdit(String file, int fileStamp, SourceEdit edit,
+ {bool insertBeforeExisting = false}) =>
+ addEditToSourceChange(this, file, fileStamp, edit,
+ insertBeforeExisting: insertBeforeExisting);
/// Adds the given [FileEdit].
void addFileEdit(SourceFileEdit edit) {
@@ -4583,10 +4603,22 @@
}
/// Adds the given [Edit] to the list.
- void add(SourceEdit edit) => addEditForSource(this, edit);
+ ///
+ /// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+ /// other edits will be inserted such that they appear before them in the
+ /// resulting document.
+ void add(SourceEdit edit, {bool insertBeforeExisting = false}) =>
+ addEditForSource(this, edit, insertBeforeExisting: insertBeforeExisting);
/// Adds the given [Edit]s.
- void addAll(Iterable<SourceEdit> edits) => addAllEditsForSource(this, edits);
+ ///
+ /// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+ /// other edits will be inserted such that they appear before them in the
+ /// resulting document.
+ void addAll(Iterable<SourceEdit> edits,
+ {bool insertBeforeExisting = false}) =>
+ addAllEditsForSource(this, edits,
+ insertBeforeExisting: insertBeforeExisting);
@override
String toString() => json.encode(toJson());
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 3baa946..e8a4e7e 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.9';
+const String PROTOCOL_VERSION = '1.32.10';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -138,6 +138,8 @@
const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_CASE_MATCHING_MODE =
+ 'completionCaseMatchingMode';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_MODE =
'completionMode';
const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 413c551..58d9f35 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -2583,9 +2583,9 @@
/// the normal package: URI resolution mechanism.
///
/// If a package root is a file, then the analyzer will behave as though that
- /// file is a ".packages" file in the source directory. The effect is the
- /// same as specifying the file as a "--packages" parameter to the Dart VM
- /// when executing any Dart file inside the source directory.
+ /// file is a ".dart_tool/package_config.json" file in the source directory.
+ /// The effect is the same as specifying the file as a "--packages" parameter
+ /// to the Dart VM when executing any Dart file inside the source directory.
///
/// Files in any directories that are not overridden by this mapping have
/// their package: URI's resolved using the normal pubspec.yaml mechanism. If
@@ -4215,6 +4215,68 @@
);
}
+/// CompletionCaseMatchingMode
+///
+/// enum {
+/// FIRST_CHAR
+/// ALL_CHARS
+/// NONE
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionCaseMatchingMode implements Enum {
+ /// Match the first character case only when filtering completions, the
+ /// default for this enumeration.
+ static const CompletionCaseMatchingMode FIRST_CHAR =
+ CompletionCaseMatchingMode._('FIRST_CHAR');
+
+ /// Match all character cases when filtering completion lists.
+ static const CompletionCaseMatchingMode ALL_CHARS =
+ CompletionCaseMatchingMode._('ALL_CHARS');
+
+ /// Do not match character cases when filtering completion lists.
+ static const CompletionCaseMatchingMode NONE =
+ CompletionCaseMatchingMode._('NONE');
+
+ /// A list containing all of the enum values that are defined.
+ static const List<CompletionCaseMatchingMode> VALUES =
+ <CompletionCaseMatchingMode>[FIRST_CHAR, ALL_CHARS, NONE];
+
+ @override
+ final String name;
+
+ const CompletionCaseMatchingMode._(this.name);
+
+ factory CompletionCaseMatchingMode(String name) {
+ switch (name) {
+ case 'FIRST_CHAR':
+ return FIRST_CHAR;
+ case 'ALL_CHARS':
+ return ALL_CHARS;
+ case 'NONE':
+ return NONE;
+ }
+ throw Exception('Illegal enum value: $name');
+ }
+
+ factory CompletionCaseMatchingMode.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+ if (json is String) {
+ try {
+ return CompletionCaseMatchingMode(json);
+ } catch (_) {
+ // Fall through
+ }
+ }
+ throw jsonDecoder.mismatch(jsonPath, 'CompletionCaseMatchingMode', json);
+ }
+
+ @override
+ String toString() => 'CompletionCaseMatchingMode.$name';
+
+ String toJson() => name;
+}
+
/// completion.existingImports params
///
/// {
@@ -4683,6 +4745,7 @@
/// "file": FilePath
/// "offset": int
/// "maxResults": int
+/// "completionCaseMatchingMode": optional CompletionCaseMatchingMode
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -4698,6 +4761,10 @@
/// to true.
int maxResults;
+ /// The mode of code completion being invoked. If no value is provided,
+ /// MATCH_FIRST_CHAR will be assumed.
+ CompletionCaseMatchingMode? completionCaseMatchingMode;
+
/// The mode of code completion being invoked. If no value is provided, BASIC
/// will be assumed. BASIC is also the only currently supported.
CompletionMode? completionMode;
@@ -4714,7 +4781,10 @@
int? timeout;
CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults,
- {this.completionMode, this.invocationCount, this.timeout});
+ {this.completionCaseMatchingMode,
+ this.completionMode,
+ this.invocationCount,
+ this.timeout});
factory CompletionGetSuggestions2Params.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4739,6 +4809,13 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'maxResults');
}
+ CompletionCaseMatchingMode? completionCaseMatchingMode;
+ if (json.containsKey('completionCaseMatchingMode')) {
+ completionCaseMatchingMode = CompletionCaseMatchingMode.fromJson(
+ jsonDecoder,
+ jsonPath + '.completionCaseMatchingMode',
+ json['completionCaseMatchingMode']);
+ }
CompletionMode? completionMode;
if (json.containsKey('completionMode')) {
completionMode = CompletionMode.fromJson(
@@ -4754,6 +4831,7 @@
timeout = jsonDecoder.decodeInt(jsonPath + '.timeout', json['timeout']);
}
return CompletionGetSuggestions2Params(file, offset, maxResults,
+ completionCaseMatchingMode: completionCaseMatchingMode,
completionMode: completionMode,
invocationCount: invocationCount,
timeout: timeout);
@@ -4774,6 +4852,11 @@
result['file'] = file;
result['offset'] = offset;
result['maxResults'] = maxResults;
+ var completionCaseMatchingMode = this.completionCaseMatchingMode;
+ if (completionCaseMatchingMode != null) {
+ result['completionCaseMatchingMode'] =
+ completionCaseMatchingMode.toJson();
+ }
var completionMode = this.completionMode;
if (completionMode != null) {
result['completionMode'] = completionMode.toJson();
@@ -4803,6 +4886,7 @@
return file == other.file &&
offset == other.offset &&
maxResults == other.maxResults &&
+ completionCaseMatchingMode == other.completionCaseMatchingMode &&
completionMode == other.completionMode &&
invocationCount == other.invocationCount &&
timeout == other.timeout;
@@ -4815,6 +4899,7 @@
file,
offset,
maxResults,
+ completionCaseMatchingMode,
completionMode,
invocationCount,
timeout,
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
index 399fb51..431cca2 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_internal.dart
@@ -13,30 +13,54 @@
HashMap<String, RefactoringKind>();
/// Adds the given [sourceEdits] to the list in [sourceFileEdit].
+///
+/// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+/// other edits will be inserted such that they appear before them in the
+/// resulting document.
void addAllEditsForSource(
- SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits) {
- edits.forEach(sourceFileEdit.add);
+ SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits,
+ {bool insertBeforeExisting = false}) {
+ edits.forEach((edit) =>
+ sourceFileEdit.add(edit, insertBeforeExisting: insertBeforeExisting));
}
/// Adds the given [sourceEdit] to the list in [sourceFileEdit].
-void addEditForSource(SourceFileEdit sourceFileEdit, SourceEdit sourceEdit) {
+///
+/// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+/// other edits will be inserted such that they appear before them in the
+/// resulting document.
+void addEditForSource(SourceFileEdit sourceFileEdit, SourceEdit sourceEdit,
+ {bool insertBeforeExisting = false}) {
var edits = sourceFileEdit.edits;
+ var length = edits.length;
var index = 0;
- while (index < edits.length && edits[index].offset > sourceEdit.offset) {
+ while (index < length && edits[index].offset > sourceEdit.offset) {
index++;
}
+ // If it's an insert and it should be inserted before existing edits, also
+ // skip over any with the same offset.
+ if (insertBeforeExisting && sourceEdit.length == 0) {
+ while (index < length && edits[index].offset >= sourceEdit.offset) {
+ index++;
+ }
+ }
edits.insert(index, sourceEdit);
}
/// Adds [edit] to the [FileEdit] for the given [file].
+///
+/// If [insertBeforeExisting] is `true`, inserts made at the same offset as
+/// other edits will be inserted such that they appear before them in the
+/// resulting document.
void addEditToSourceChange(
- SourceChange change, String file, int fileStamp, SourceEdit edit) {
+ SourceChange change, String file, int fileStamp, SourceEdit edit,
+ {bool insertBeforeExisting = false}) {
var fileEdit = change.getFileEdit(file);
if (fileEdit == null) {
fileEdit = SourceFileEdit(file, fileStamp);
change.addFileEdit(fileEdit);
}
- fileEdit.add(edit);
+ fileEdit.add(edit, insertBeforeExisting: insertBeforeExisting);
}
/// Get the result of applying the edit to the given [code]. Access via
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 65409ce..0b6f526 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 3.3.1
+* Report HintCode.OVERRIDE_ON_NON_OVERRIDING_xyz on enum.
+
+## 3.3.0
+* Added `getField` to `ExtensionElement`.
+* Added `isGenerative` to `ConstructorElement`.
+* Added `isDartCoreEnum` to `ClassElement` and `DartType`.
+* Deprecated `superclass2`, `mixinTypes2`, etc. Use `superclass`, `mixinTypes`, etc.
+* APIs for `enhanced-enums` language feature.
+
## 3.2.0
* Deprecated `changes` getter in `File` and `Folder`, use `watch()` instead.
diff --git a/pkg/analyzer/OWNERS b/pkg/analyzer/OWNERS
new file mode 100644
index 0000000..1592b3e
--- /dev/null
+++ b/pkg/analyzer/OWNERS
@@ -0,0 +1 @@
+file:/tools/OWNERS_ANALYZER
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index 8cee120..64dfab7 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -82,14 +82,14 @@
featureSet: featureSet,
);
var token = scanner.tokenize();
+ var lineInfo = LineInfo(scanner.lineStarts);
var parser = Parser(
source,
errorCollector,
featureSet: scanner.featureSet,
+ lineInfo: lineInfo,
);
var unit = parser.parseCompilationUnit(token);
- var lineInfo = LineInfo(scanner.lineStarts);
- unit.lineInfo = lineInfo;
ParseStringResult result =
ParseStringResultImpl(content, unit, errorCollector.errors);
if (throwIfDiagnostics && result.errors.isNotEmpty) {
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 748df11..d49cca3 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -818,9 +818,6 @@
/// Return `true` if this class is declared to be an abstract class.
bool get isAbstract;
- /// Return the 'macro' keyword, or `null` if the keyword was absent.
- Token? get macroKeyword;
-
/// Return the native clause for this class, or `null` if the class does not
/// have a native clause.
NativeClause? get nativeClause;
@@ -908,14 +905,14 @@
/// Return `true` if this class is declared to be an abstract class.
bool get isAbstract;
- /// Return the token for the 'macro' keyword, or `null` if this is not
- /// defining a macro class.
- Token? get macroKeyword;
-
@override
SimpleIdentifier get name;
/// Return the name of the superclass of the class being declared.
+ NamedType get superclass;
+
+ /// Return the name of the superclass of the class being declared.
+ @Deprecated('Use superclass instead')
NamedType get superclass2;
/// Return the type parameters for the class, or `null` if the class does not
@@ -1066,7 +1063,7 @@
LanguageVersionToken? get languageVersionToken;
/// Return the line information for this compilation unit.
- LineInfo? get lineInfo;
+ LineInfo get lineInfo;
/// Return the script tag at the beginning of the compilation unit, or `null`
/// if there is no script tag in this compilation unit.
@@ -1342,6 +1339,10 @@
Token? get period;
/// Return the name of the type defining the constructor.
+ NamedType get type;
+
+ /// Return the name of the type defining the constructor.
+ @Deprecated('Use type instead')
NamedType get type2;
}
@@ -1654,6 +1655,9 @@
/// Return the right curly bracket.
Token get rightBracket;
+ /// Return the optional semicolon after the last constant.
+ Token? get semicolon;
+
/// Returns the type parameters for the enumeration, or `null` if the
/// enumeration does not have any type parameters.
TypeParameterList? get typeParameters;
@@ -1780,6 +1784,10 @@
Token get extendsKeyword;
/// Return the name of the class that is being extended.
+ NamedType get superclass;
+
+ /// Return the name of the class that is being extended.
+ @Deprecated('Use superclass instead')
NamedType get superclass2;
}
@@ -2677,6 +2685,10 @@
Token get implementsKeyword;
/// Return the list of the interfaces that are being implemented.
+ NodeList<NamedType> get interfaces;
+
+ /// Return the list of the interfaces that are being implemented.
+ @Deprecated('Use interfaces instead')
NodeList<NamedType> get interfaces2;
}
@@ -3529,6 +3541,10 @@
Token get onKeyword;
/// Return the list of the classes are superclass constraints for the mixin.
+ NodeList<NamedType> get superclassConstraints;
+
+ /// Return the list of the classes are superclass constraints for the mixin.
+ @Deprecated('Use superclassConstraints instead')
NodeList<NamedType> get superclassConstraints2;
}
@@ -4612,6 +4628,10 @@
/// Clients may not extend, implement or mix-in this class.
abstract class WithClause implements AstNode {
/// Return the names of the mixins that were specified.
+ NodeList<NamedType> get mixinTypes;
+
+ /// Return the names of the mixins that were specified.
+ @Deprecated('Use mixinTypes instead')
NodeList<NamedType> get mixinTypes2;
/// Return the token representing the 'with' keyword.
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 9cb8248..682228e 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
/// A collection of factory methods which may be used to create concrete
@@ -119,16 +120,18 @@
/// [comment] and [metadata] can be `null` if the class does not have the
/// corresponding attribute. The [abstractKeyword] can be `null` if the class
/// is not abstract. The [macroKeyword] can be `null` if the class is not a
- /// macro class. The [typeParameters] can be `null` if the class does not
- /// have any type parameters. Any or all of the [extendsClause], [withClause],
- /// and [implementsClause] can be `null` if the class does not have the
- /// corresponding clause. The list of [members] can be `null` if the class
- /// does not have any members.
+ /// macro class. The [augmentKeyword] can be `null` if the class is not an
+ /// augmentation class. The [typeParameters] can be `null` if the class does
+ /// not have any type parameters. Any or all of the [extendsClause],
+ /// [withClause], and [implementsClause] can be `null` if the class does not
+ /// have the corresponding clause. The list of [members] can be `null` if the
+ /// class does not have any members.
ClassDeclaration classDeclaration(
Comment? comment,
List<Annotation>? metadata,
Token? abstractKeyword,
Token? macroKeyword,
+ Token? augmentKeyword,
Token classKeyword,
SimpleIdentifier name,
TypeParameterList? typeParameters,
@@ -144,7 +147,8 @@
/// corresponding attribute. The [typeParameters] can be `null` if the class
/// does not have any type parameters. The [abstractKeyword] can be `null` if
/// the class is not abstract. The [macroKeyword] can be `null` if the class
- /// is not a macro class. The [implementsClause] can be `null` if the
+ /// is not a macro class. The [augmentKeyword] can be `null` if the class is
+ /// not an augmentation class. The [implementsClause] can be `null` if the
/// class does not implement any interfaces.
ClassTypeAlias classTypeAlias(
Comment? comment,
@@ -155,6 +159,7 @@
Token equals,
Token? abstractKeyword,
Token? macroKeyword,
+ Token? augmentKeyword,
NamedType superclass,
WithClause withClause,
ImplementsClause? implementsClause,
@@ -171,13 +176,15 @@
/// `null` (or omitted) if there are no directives in the compilation unit.
/// The list of `declarations` can be `null` (or omitted) if there are no
/// declarations in the compilation unit.
- CompilationUnit compilationUnit(
- {required Token beginToken,
- ScriptTag? scriptTag,
- List<Directive>? directives,
- List<CompilationUnitMember>? declarations,
- required Token endToken,
- required FeatureSet featureSet});
+ CompilationUnit compilationUnit({
+ required Token beginToken,
+ ScriptTag? scriptTag,
+ List<Directive>? directives,
+ List<CompilationUnitMember>? declarations,
+ required Token endToken,
+ required FeatureSet featureSet,
+ LineInfo? lineInfo,
+ });
/// Returns a newly created conditional expression.
ConditionalExpression conditionalExpression(
@@ -329,6 +336,7 @@
required ImplementsClause? implementsClause,
required Token leftBracket,
required List<EnumConstantDeclaration> constants,
+ required Token? semicolon,
required List<ClassMember> members,
required Token rightBracket,
});
@@ -396,12 +404,14 @@
/// Returns a newly created field declaration. Either or both of the
/// [comment] and [metadata] can be `null` if the declaration does not have
- /// the corresponding attribute. The [staticKeyword] can be `null` if the
- /// field is not a static field.
+ /// the corresponding attribute. The [abstractKeyword], [augmentKeyword],
+ /// [covariantKeyword], [externalKeyword] and [staticKeyword] can be `null` if
+ /// the field does not have the corresponding modifier.
FieldDeclaration fieldDeclaration2(
{Comment? comment,
List<Annotation>? metadata,
Token? abstractKeyword,
+ Token? augmentKeyword,
Token? covariantKeyword,
Token? externalKeyword,
Token? staticKeyword,
@@ -489,13 +499,15 @@
/// Returns a newly created function declaration. Either or both of the
/// [comment] and [metadata] can be `null` if the function does not have the
- /// corresponding attribute. The [externalKeyword] can be `null` if the
- /// function is not an external function. The [returnType] can be `null` if no
- /// return type was specified. The [propertyKeyword] can be `null` if the
- /// function is neither a getter or a setter.
+ /// corresponding attribute. The [augmentKeyword] can be `null` if the
+ /// function is not a function augmentation. The [externalKeyword] can be
+ /// `null` if the function is not an external function. The [returnType] can
+ /// be `null` if no return type was specified. The [propertyKeyword] can be
+ /// `null` if the function is neither a getter or a setter.
FunctionDeclaration functionDeclaration(
Comment? comment,
List<Annotation>? metadata,
+ Token? augmentKeyword,
Token? externalKeyword,
TypeAnnotation? returnType,
Token? propertyKeyword,
@@ -617,8 +629,8 @@
required List<DartType> typeArgumentTypes,
});
- /// Returns a newly created import directive. Either or both of the
- /// [comment] and [metadata] can be `null` if the function does not have the
+ /// Returns a newly created import directive. Either or both of the [comment]
+ /// and [metadata] can be `null` if the function does not have the
/// corresponding attribute. The [deferredKeyword] can be `null` if the import
/// is not deferred. The [asKeyword] and [prefix] can be `null` if the import
/// does not specify a prefix. The list of [combinators] can be `null` if
@@ -737,6 +749,7 @@
MixinDeclaration mixinDeclaration(
Comment? comment,
List<Annotation>? metadata,
+ Token? augmentKeyword,
Token mixinKeyword,
SimpleIdentifier name,
TypeParameterList? typeParameters,
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 400e918..e0478a0 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -104,6 +104,10 @@
/// <i>abstract</i> is different from <i>has unimplemented members</i>.
bool get isAbstract;
+ /// Return `true` if this class represents the class 'Enum' defined in the
+ /// dart:core library.
+ bool get isDartCoreEnum;
+
/// Return `true` if this class represents the class 'Object' defined in the
/// dart:core library.
bool get isDartCoreObject;
@@ -468,6 +472,9 @@
/// Return `true` if this constructor represents a factory constructor.
bool get isFactory;
+ /// Return `true` if this constructor represents a generative constructor.
+ bool get isGenerative;
+
@override
String get name;
@@ -1145,6 +1152,11 @@
/// Return a list containing all of the methods declared in this extension.
List<MethodElement> get methods;
+ /// Return the element representing the field with the given [name] that is
+ /// declared in this extension, or `null` if this extension does not declare a
+ /// field with the given name.
+ FieldElement? getField(String name);
+
/// Return the element representing the getter with the given [name] that is
/// declared in this extension, or `null` if this extension does not declare a
/// getter with the given name.
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index e3f102e..2f479bd 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -69,6 +69,10 @@
/// dart:core library.
bool get isDartCoreDouble;
+ /// Return `true` if this type represents the type 'Enum' defined in the
+ /// dart:core library.
+ bool get isDartCoreEnum;
+
/// Return `true` if this type represents the type 'Function' defined in the
/// dart:core library.
bool get isDartCoreFunction;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 3555ef1..1e78252 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -94,6 +94,7 @@
CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_INSTANCE_MEMBER,
CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_STATIC_MEMBER,
CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER,
+ CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE,
CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD,
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER,
@@ -104,8 +105,10 @@
CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS,
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN,
@@ -159,6 +162,11 @@
CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT,
CompileTimeErrorCode.DUPLICATE_PART,
CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
+ CompileTimeErrorCode.ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR,
+ CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED,
+ CompileTimeErrorCode.ENUM_MIXIN_WITH_INSTANCE_VARIABLE,
+ CompileTimeErrorCode.ENUM_WITH_ABSTRACT_MEMBER,
+ CompileTimeErrorCode.ENUM_WITH_NAME_VALUES,
CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET,
CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP,
CompileTimeErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
@@ -208,6 +216,11 @@
CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE,
+ CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION,
+ CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE,
+ CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
+ CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION,
+ CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE,
CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
@@ -216,10 +229,7 @@
CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+ CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS,
CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
@@ -258,6 +268,7 @@
CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_OVERRIDE,
+ CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS,
CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION,
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST,
@@ -323,6 +334,7 @@
CompileTimeErrorCode.NON_BOOL_EXPRESSION,
CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION,
CompileTimeErrorCode.NON_BOOL_OPERAND,
+ CompileTimeErrorCode.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR,
CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT,
CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR,
CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION,
@@ -337,6 +349,7 @@
CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE,
CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT,
+ CompileTimeErrorCode.NON_FINAL_FIELD_IN_ENUM,
CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR,
CompileTimeErrorCode.NON_SYNC_FACTORY,
@@ -408,6 +421,7 @@
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+ CompileTimeErrorCode.SUPER_IN_ENUM_CONSTRUCTOR,
CompileTimeErrorCode.SUPER_IN_EXTENSION,
CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT,
CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
@@ -439,6 +453,8 @@
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER,
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT,
+ CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED,
+ CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED,
CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
@@ -466,6 +482,7 @@
CompileTimeErrorCode.URI_WITH_INTERPOLATION,
CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
CompileTimeErrorCode.USE_OF_VOID_RESULT,
+ CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM,
CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
@@ -474,6 +491,7 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
@@ -717,6 +735,7 @@
ParserErrorCode.DUPLICATE_PREFIX,
ParserErrorCode.DUPLICATED_MODIFIER,
ParserErrorCode.EMPTY_ENUM_BODY,
+ ParserErrorCode.ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS,
ParserErrorCode.ENUM_IN_CLASS,
ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
ParserErrorCode.EXPECTED_BODY,
@@ -823,6 +842,7 @@
ParserErrorCode.MIXED_PARAMETER_GROUPS,
ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
ParserErrorCode.MODIFIER_OUT_OF_ORDER,
+ ParserErrorCode.MULTIPLE_CLAUSES,
ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES,
ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES,
@@ -846,6 +866,7 @@
ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS,
ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER,
+ ParserErrorCode.OUT_OF_ORDER_CLAUSES,
ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT,
ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP,
ParserErrorCode.PREFIX_AFTER_COMBINATOR,
@@ -869,6 +890,7 @@
ParserErrorCode.TYPEDEF_IN_CLASS,
ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
ParserErrorCode.UNEXPECTED_TOKEN,
+ ParserErrorCode.UNEXPECTED_TOKENS,
ParserErrorCode.VAR_AND_TYPE,
ParserErrorCode.VAR_AS_TYPE_NAME,
ParserErrorCode.VAR_CLASS,
diff --git a/pkg/analyzer/lib/src/analysis_options/error/option_codes.g.dart b/pkg/analyzer/lib/src/analysis_options/error/option_codes.g.dart
index 7690c44..cbe95e2 100644
--- a/pkg/analyzer/lib/src/analysis_options/error/option_codes.g.dart
+++ b/pkg/analyzer/lib/src/analysis_options/error/option_codes.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
diff --git a/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart b/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
index be9069c..bd2a210 100644
--- a/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
+++ b/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
@@ -46,7 +46,7 @@
...uriResolvers,
]);
- var dataStore = SummaryDataStore([]);
+ var dataStore = SummaryDataStore.tmp();
dataStore.addBundle('', sdkBundle);
var logger = PerformanceLog(null);
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index 103c1a6..2f3fd34 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -14,7 +14,7 @@
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:cli_util/cli_util.dart';
+import 'package:analyzer/src/util/sdk.dart';
/// An implementation of [AnalysisContextCollection].
class AnalysisContextCollectionImpl implements AnalysisContextCollection {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index a9c0df3..c999006 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -27,8 +27,8 @@
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:cli_util/cli_util.dart';
/// An implementation of a context builder.
class ContextBuilderImpl implements ContextBuilder {
@@ -72,7 +72,12 @@
SummaryDataStore? summaryData;
if (librarySummaryPaths != null) {
- summaryData = SummaryDataStore(librarySummaryPaths);
+ summaryData = SummaryDataStore.tmp();
+ for (var summaryPath in librarySummaryPaths) {
+ var bytes = resourceProvider.getFile(summaryPath).readAsBytesSync();
+ var bundle = PackageBundleReader(bytes);
+ summaryData.addBundle(summaryPath, bundle);
+ }
}
var workspace = contextRoot.workspace;
diff --git a/pkg/analyzer/lib/src/dart/analysis/defined_names.dart b/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
index c308535..d4d2ed2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
@@ -31,6 +31,12 @@
if (member is ClassDeclaration) {
member.members.forEach(appendClassMemberName);
}
+ if (member is EnumDeclaration) {
+ for (var constant in member.constants) {
+ appendName(names.classMemberNames, constant.name);
+ }
+ member.members.forEach(appendClassMemberName);
+ }
if (member is MixinDeclaration) {
member.members.forEach(appendClassMemberName);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
index d65f695..b8a21dc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
@@ -173,7 +173,7 @@
NamedType? enclosingSuperClass;
if (node is ClassDeclaration) {
- enclosingSuperClass = node.extendsClause?.superclass2;
+ enclosingSuperClass = node.extendsClause?.superclass;
}
enclosingClassNameSignature =
@@ -290,7 +290,7 @@
var api = referenceCollector.collect(
apiTokenSignature,
typeParameters: node.typeParameters,
- superClass: node.superclass2,
+ superClass: node.superclass,
withClause: node.withClause,
implementsClause: node.implementsClause,
);
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
index b9b7403..706248e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
@@ -88,11 +88,11 @@
_visitTypeParameterList(typeParameters2);
// Parts of classes.
- _visitTypeAnnotation(extendsClause?.superclass2);
+ _visitTypeAnnotation(extendsClause?.superclass);
_visitTypeAnnotation(superClass);
- _visitTypeAnnotations(withClause?.mixinTypes2);
- _visitTypeAnnotations(onClause?.superclassConstraints2);
- _visitTypeAnnotations(implementsClause?.interfaces2);
+ _visitTypeAnnotations(withClause?.mixinTypes);
+ _visitTypeAnnotations(onClause?.superclassConstraints);
+ _visitTypeAnnotations(implementsClause?.interfaces);
// Parts of executables.
_visitFormalParameterList(formalParameters);
@@ -305,7 +305,7 @@
void _visitConstructorName(ConstructorName? node) {
if (node == null) return;
- _visitConstructor(node.type2, node.name);
+ _visitConstructor(node.type, node.name);
}
void _visitExpression(Expression? node, {bool get = true, bool set = false}) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 165e57f..84644e4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -82,7 +82,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 201;
+ static const int DATA_VERSION = 209;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -268,37 +268,6 @@
_search = Search(this);
}
- /// Create a new instance of [AnalysisDriver].
- ///
- /// The given [SourceFactory] is cloned to ensure that it does not contain a
- /// reference to a [AnalysisContext] in which it could have been used.
- @Deprecated('Use the unnamed constructor instead')
- AnalysisDriver.tmp1({
- required AnalysisDriverScheduler scheduler,
- required PerformanceLog logger,
- required ResourceProvider resourceProvider,
- required ByteStore byteStore,
- required SourceFactory sourceFactory,
- required AnalysisOptionsImpl analysisOptions,
- required Packages packages,
- FileContentCache? fileContentCache,
- bool enableIndex = false,
- SummaryDataStore? externalSummaries,
- bool retainDataForTesting = false,
- }) : this(
- scheduler: scheduler,
- logger: logger,
- resourceProvider: resourceProvider,
- byteStore: byteStore,
- sourceFactory: sourceFactory,
- analysisOptions: analysisOptions,
- packages: packages,
- fileContentCache: fileContentCache,
- enableIndex: enableIndex,
- externalSummaries: externalSummaries,
- retainDataForTesting: retainDataForTesting,
- );
-
/// Return the set of files explicitly added to analysis using [addFile].
Set<String> get addedFiles => _fileTracker.addedFiles;
@@ -2152,7 +2121,11 @@
FileTracker get fileTracker => driver._fileTracker;
- LibraryContext? get libraryContext => driver._libraryContext;
+ Set<String> get loadedLibraryUriSet {
+ var elementFactory = driver.libraryContext.elementFactory;
+ var libraryReferences = elementFactory.rootReference.children;
+ return libraryReferences.map((e) => e.name).toSet();
+ }
Map<String, ResolvedUnitResult> get priorityResults {
return driver._priorityResults;
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index ee40393..ca06838 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -147,7 +147,7 @@
isExpired: IsExpired.enhanced_enums,
documentation: 'Enhanced Enums',
experimentalReleaseVersion: null,
- releaseVersion: null,
+ releaseVersion: Version.parse('2.17.0'),
);
static final extension_methods = ExperimentalFeature(
@@ -198,7 +198,7 @@
isExpired: IsExpired.named_arguments_anywhere,
documentation: 'Named Arguments Anywhere',
experimentalReleaseVersion: null,
- releaseVersion: null,
+ releaseVersion: Version.parse('2.17.0'),
);
static final non_nullable = ExperimentalFeature(
@@ -248,7 +248,7 @@
isExpired: IsExpired.super_parameters,
documentation: 'Super-Initializer Parameters',
experimentalReleaseVersion: null,
- releaseVersion: null,
+ releaseVersion: Version.parse('2.17.0'),
);
static final test_experiment = ExperimentalFeature(
@@ -309,7 +309,7 @@
static const bool control_flow_collections = true;
/// Default state of the experiment "enhanced-enums"
- static const bool enhanced_enums = false;
+ static const bool enhanced_enums = true;
/// Default state of the experiment "extension-methods"
static const bool extension_methods = true;
@@ -324,7 +324,7 @@
static const bool macros = false;
/// Default state of the experiment "named-arguments-anywhere"
- static const bool named_arguments_anywhere = false;
+ static const bool named_arguments_anywhere = true;
/// Default state of the experiment "non-nullable"
static const bool non_nullable = true;
@@ -339,7 +339,7 @@
static const bool spread_collections = true;
/// Default state of the experiment "super-parameters"
- static const bool super_parameters = false;
+ static const bool super_parameters = true;
/// Default state of the experiment "test-experiment"
static const bool test_experiment = false;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 2c3364c..2e1c323 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -550,11 +550,11 @@
source,
errorListener,
featureSet: scanner.featureSet,
+ lineInfo: lineInfo,
);
parser.enableOptionalNewAndConst = true;
var unit = parser.parseCompilationUnit(token);
- unit.lineInfo = lineInfo;
unit.languageVersion = LibraryLanguageVersion(
package: packageLanguageVersion,
override: scanner.overrideVersion,
@@ -636,7 +636,7 @@
hasPartOfDirective: hasPartOfDirective,
imports: imports,
informativeBytes: writeUnitInformative(unit),
- lineStarts: Uint32List.fromList(unit.lineInfo!.lineStarts),
+ lineStarts: Uint32List.fromList(unit.lineInfo.lineStarts),
partOfName: null,
partOfUri: null,
parts: parts,
@@ -977,14 +977,18 @@
/// expensive to work with, if we do this thousand times.
class FileUriProperties {
static const int _isDart = 1 << 0;
- static const int _isSrc = 1 << 1;
+ static const int _isDartInternal = 1 << 1;
+ static const int _isSrc = 1 << 2;
final int _flags;
final String? packageName;
factory FileUriProperties(Uri uri) {
if (uri.isScheme('dart')) {
- return const FileUriProperties._dart();
+ var dartName = uri.pathSegments.firstOrNull;
+ return FileUriProperties._dart(
+ isInternal: dartName != null && dartName.startsWith('_'),
+ );
} else if (uri.isScheme('package')) {
var segments = uri.pathSegments;
if (segments.length >= 2) {
@@ -997,8 +1001,9 @@
return const FileUriProperties._unknown();
}
- const FileUriProperties._dart()
- : _flags = _isDart,
+ const FileUriProperties._dart({
+ required bool isInternal,
+ }) : _flags = _isDart | (isInternal ? _isDartInternal : 0),
packageName = null;
FileUriProperties._package({
@@ -1013,5 +1018,7 @@
bool get isDart => (_flags & _isDart) != 0;
+ bool get isDartInternal => (_flags & _isDartInternal) != 0;
+
bool get isSrc => (_flags & _isSrc) != 0;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart b/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
index 828d7ad..5396bc0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
@@ -23,7 +23,13 @@
class _AnyFilter implements FileStateFilter {
@override
- bool shouldInclude(FileState file) => true;
+ bool shouldInclude(FileState file) {
+ var uri = file.uriProperties;
+ if (uri.isDart) {
+ return !uri.isDartInternal;
+ }
+ return true;
+ }
}
class _PubFilter implements FileStateFilter {
@@ -66,7 +72,7 @@
bool shouldInclude(FileState file) {
var uri = file.uriProperties;
if (uri.isDart) {
- return true;
+ return !uri.isDartInternal;
}
// Normally only package URIs are available.
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index f9aebb6..74c3887 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -634,13 +634,55 @@
offset = node.period!.offset;
length = node.name!.end - offset;
} else {
- offset = node.type2.end;
+ offset = node.type.end;
length = 0;
}
recordRelationOffset(element, kind, offset, length, true);
- node.type2.accept(this);
+ node.type.accept(this);
+ }
+
+ @override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ var constructorElement = node.constructorElement;
+ if (constructorElement != null) {
+ int offset;
+ int length;
+ var constructorSelector = node.arguments?.constructorSelector;
+ if (constructorSelector != null) {
+ offset = constructorSelector.period.offset;
+ length = constructorSelector.name.end - offset;
+ } else {
+ offset = node.name.end;
+ length = 0;
+ }
+ recordRelationOffset(
+ constructorElement,
+ node.arguments == null
+ ? IndexRelationKind.IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS
+ : IndexRelationKind.IS_INVOKED_BY,
+ offset,
+ length,
+ true,
+ );
+ }
+
+ super.visitEnumConstantDeclaration(node);
+ }
+
+ @override
+ void visitEnumDeclaration(EnumDeclaration node) {
+ _addSubtype(
+ node.name.name,
+ withClause: node.withClause,
+ implementsClause: node.implementsClause,
+ memberNodes: node.members,
+ );
+
+ var declaredElement = node.declaredElement!;
+ recordIsAncestorOf(declaredElement);
+ super.visitEnumDeclaration(node);
}
@override
@@ -662,7 +704,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
- recordSuperType(node.superclass2, IndexRelationKind.IS_EXTENDED_BY);
+ recordSuperType(node.superclass, IndexRelationKind.IS_EXTENDED_BY);
}
@override
@@ -681,7 +723,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
- for (NamedType namedType in node.interfaces2) {
+ for (NamedType namedType in node.interfaces) {
recordSuperType(namedType, IndexRelationKind.IS_IMPLEMENTED_BY);
}
}
@@ -735,7 +777,7 @@
@override
void visitNamedType(NamedType node) {
AstNode parent = node.parent!;
- if (parent is ClassTypeAlias && parent.superclass2 == node) {
+ if (parent is ClassTypeAlias && parent.superclass == node) {
recordSuperType(node, IndexRelationKind.IS_EXTENDED_BY);
} else {
super.visitNamedType(node);
@@ -744,7 +786,7 @@
@override
void visitOnClause(OnClause node) {
- for (NamedType namedType in node.superclassConstraints2) {
+ for (NamedType namedType in node.superclassConstraints) {
recordSuperType(namedType, IndexRelationKind.IS_IMPLEMENTED_BY);
}
}
@@ -865,7 +907,7 @@
@override
void visitWithClause(WithClause node) {
- for (NamedType namedType in node.mixinTypes2) {
+ for (NamedType namedType in node.mixinTypes) {
recordSuperType(namedType, IndexRelationKind.IS_MIXED_IN_BY);
}
}
@@ -897,9 +939,9 @@
}
addSupertype(superclass);
- withClause?.mixinTypes2.forEach(addSupertype);
- onClause?.superclassConstraints2.forEach(addSupertype);
- implementsClause?.interfaces2.forEach(addSupertype);
+ withClause?.mixinTypes.forEach(addSupertype);
+ onClause?.superclassConstraints.forEach(addSupertype);
+ implementsClause?.interfaces.forEach(addSupertype);
void addMemberName(SimpleIdentifier identifier) {
String name = identifier.name;
@@ -927,7 +969,7 @@
/// Record the given class as a subclass of its direct superclasses.
void _addSubtypeForClassDeclaration(ClassDeclaration node) {
_addSubtype(node.name.name,
- superclass: node.extendsClause?.superclass2,
+ superclass: node.extendsClause?.superclass,
withClause: node.withClause,
implementsClause: node.implementsClause,
memberNodes: node.members);
@@ -936,7 +978,7 @@
/// Record the given class as a subclass of its direct superclasses.
void _addSubtypeForClassTypeAlis(ClassTypeAlias node) {
_addSubtype(node.name.name,
- superclass: node.superclass2,
+ superclass: node.superclass,
withClause: node.withClause,
implementsClause: node.implementsClause,
memberNodes: const []);
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 347e551..2322191 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -565,7 +565,7 @@
String content = file.content;
var unit = file.parse(errorListener);
- _fileToLineInfo[file] = unit.lineInfo!;
+ _fileToLineInfo[file] = unit.lineInfo;
_fileToIgnoreInfo[file] = IgnoreInfo.forDart(unit, content);
return unit;
@@ -956,8 +956,16 @@
return true;
}
- // We have a contributor that looks at the type, but it is syntactic.
if (parent is FormalParameter && parent.identifier == node) {
+ // We use elements to access fields.
+ if (parent is FieldFormalParameter) {
+ return false;
+ }
+ // We use elements to access the enclosing constructor.
+ if (parent is SuperFormalParameter) {
+ return false;
+ }
+ // We have a contributor that looks at the type, but it is syntactic.
return true;
}
@@ -972,6 +980,12 @@
// The name of a NamedType does not provide any context.
// So, we don't need to resolve anything.
if (parent is NamedType) {
+ // `{foo^ print(0);}` looks as `foo print; (0);`.
+ var parent3 = parent.parent?.parent;
+ if (parent3 is VariableDeclarationStatement &&
+ parent3.semicolon.isSynthetic) {
+ return false;
+ }
return true;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index c9ee80d..6ec80ea 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -39,7 +39,7 @@
final LibraryContextTestView testView;
final PerformanceLog logger;
final ByteStore byteStore;
- final SummaryDataStore store = SummaryDataStore([]);
+ final SummaryDataStore store = SummaryDataStore.tmp();
late final AnalysisContextImpl analysisContext;
late LinkedElementFactory elementFactory;
diff --git a/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
index 2d5e347..0cc56cb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
@@ -34,16 +34,19 @@
for (CompilationUnitMember declaration in unit.declarations) {
if (declaration is ClassDeclaration) {
- _addSubtypedName(declaration.extendsClause?.superclass2);
- _addSubtypedNames(declaration.withClause?.mixinTypes2);
- _addSubtypedNames(declaration.implementsClause?.interfaces2);
+ _addSubtypedName(declaration.extendsClause?.superclass);
+ _addSubtypedNames(declaration.withClause?.mixinTypes);
+ _addSubtypedNames(declaration.implementsClause?.interfaces);
} else if (declaration is ClassTypeAlias) {
- _addSubtypedName(declaration.superclass2);
- _addSubtypedNames(declaration.withClause.mixinTypes2);
- _addSubtypedNames(declaration.implementsClause?.interfaces2);
+ _addSubtypedName(declaration.superclass);
+ _addSubtypedNames(declaration.withClause.mixinTypes);
+ _addSubtypedNames(declaration.implementsClause?.interfaces);
+ } else if (declaration is EnumDeclaration) {
+ _addSubtypedNames(declaration.withClause?.mixinTypes);
+ _addSubtypedNames(declaration.implementsClause?.interfaces);
} else if (declaration is MixinDeclaration) {
- _addSubtypedNames(declaration.onClause?.superclassConstraints2);
- _addSubtypedNames(declaration.implementsClause?.interfaces2);
+ _addSubtypedNames(declaration.onClause?.superclassConstraints);
+ _addSubtypedNames(declaration.implementsClause?.interfaces);
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index e799e6d..d43672d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -136,7 +136,7 @@
ParseStringResultImpl(this.content, this.unit, this.errors);
@override
- LineInfo get lineInfo => unit.lineInfo!;
+ LineInfo get lineInfo => unit.lineInfo;
}
class ResolvedForCompletionResultImpl {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index cdd7c72..6df7913 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -154,6 +154,7 @@
var unitResult = await _driver.getUnitElement(file);
if (unitResult is UnitElementResult) {
unitResult.element.classes.forEach(addElements);
+ unitResult.element.enums.forEach(addElements);
unitResult.element.mixins.forEach(addElements);
}
}
@@ -534,6 +535,8 @@
List<SearchResult> results = <SearchResult>[];
await _addResults(results, element, searchedFiles, const {
IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION,
+ IndexRelationKind.IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS:
+ SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
IndexRelationKind.IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF:
SearchResultKind.REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
@@ -787,6 +790,7 @@
READ_WRITE,
WRITE,
INVOCATION,
+ INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
REFERENCE,
REFERENCE_BY_CONSTRUCTOR_TEAR_OFF,
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5218135..b033bbe 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -15,7 +15,9 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
+import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -42,19 +44,25 @@
Token get beginToken => _strings.beginToken!;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll(_strings);
-
- @override
Token get endToken => _strings.endToken!;
@override
NodeListImpl<StringLiteral> get strings => _strings;
@override
+ ChildEntities get _childEntities {
+ return ChildEntities()..addNodeList('strings', strings);
+ }
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAdjacentStrings(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitAdjacentStrings(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_strings.accept(visitor);
}
@@ -124,17 +132,11 @@
]..sort(AstNode.LEXICAL_ORDER);
}
- /// Return a holder of child entities that subclasses can add to.
+ @override
ChildEntities get _childEntities {
- ChildEntities result = ChildEntities();
- if (_commentIsBeforeAnnotations()) {
- result
- ..add(_comment)
- ..addAll(_metadata);
- } else {
- result.addAll(sortedCommentAndAnnotations);
- }
- return result;
+ return ChildEntities()
+ ..addNode('documentationComment', documentationComment)
+ ..addNodeList('metadata', metadata);
}
@override
@@ -235,15 +237,6 @@
Token get beginToken => atSign;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(atSign)
- ..add(_name)
- ..add(_typeArguments)
- ..add(period)
- ..add(_constructorName)
- ..add(_arguments);
-
- @override
SimpleIdentifierImpl? get constructorName => _constructorName;
set constructorName(SimpleIdentifier? name) {
@@ -294,6 +287,17 @@
}
@override
+ ChildEntities get _childEntities {
+ return ChildEntities()
+ ..addToken('atSign', atSign)
+ ..addNode('name', name)
+ ..addNode('typeArguments', typeArguments)
+ ..addToken('period', period)
+ ..addNode('constructorName', constructorName)
+ ..addNode('arguments', arguments);
+ }
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAnnotation(this);
@override
@@ -347,13 +351,6 @@
@override
Token get beginToken => leftParenthesis;
- @override
- // TODO(paulberry): Add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftParenthesis)
- ..addAll(_arguments)
- ..add(rightParenthesis);
-
List<ParameterElement?>? get correspondingStaticParameters =>
_correspondingStaticParameters;
@@ -369,6 +366,13 @@
Token get endToken => rightParenthesis;
@override
+ // TODO(paulberry): Add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNodeList('arguments', arguments)
+ ..addToken('rightParenthesis', rightParenthesis);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitArgumentList(this);
@override
@@ -427,12 +431,6 @@
Token get beginToken => _expression.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_expression)
- ..add(asOperator)
- ..add(_type);
-
- @override
Token get endToken => _type.endToken;
@override
@@ -453,9 +451,20 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('expression', expression)
+ ..addToken('asOperator', asOperator)
+ ..addNode('type', type);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAsExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitAsExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
_type.accept(visitor);
@@ -498,15 +507,6 @@
Token get beginToken => assertKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(assertKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(comma)
- ..add(_message)
- ..add(rightParenthesis);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression condition) {
@@ -524,6 +524,15 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('assertKeyword', assertKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('comma', comma)
+ ..addNode('message', message)
+ ..addToken('rightParenthesis', rightParenthesis);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAssertInitializer(this);
@override
@@ -571,16 +580,6 @@
Token get beginToken => assertKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(assertKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(comma)
- ..add(_message)
- ..add(rightParenthesis)
- ..add(semicolon);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression condition) {
@@ -598,6 +597,16 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('assertKeyword', assertKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('comma', comma)
+ ..addNode('message', message)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAssertStatement(this);
@override
@@ -642,12 +651,6 @@
Token get beginToken => _leftHandSide.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_leftHandSide)
- ..add(operator)
- ..add(_rightHandSide);
-
- @override
Token get endToken => _rightHandSide.endToken;
@override
@@ -668,6 +671,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('leftHandSide', leftHandSide)
+ ..addToken('operator', operator)
+ ..addNode('rightHandSide', rightHandSide);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
/// If the AST structure has been resolved, and the function being invoked is
@@ -701,6 +710,11 @@
visitor.visitAssignmentExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitAssignmentExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_leftHandSide.accept(visitor);
_rightHandSide.accept(visitor);
@@ -722,6 +736,10 @@
Map<String, Object>? _propertyMap;
@override
+ Iterable<SyntacticEntity> get childEntities =>
+ _childEntities.syntacticEntities;
+
+ @override
int get end => offset + length;
@override
@@ -734,6 +752,11 @@
return endToken.offset + endToken.length - beginToken.offset;
}
+ /// Return properties (tokens and nodes) of this node, with names, in the
+ /// order in which these entities should normally appear, not necessary in
+ /// the order they really are (because of recovery).
+ Iterable<ChildEntity> get namedChildEntities => _childEntities.entities;
+
@override
int get offset {
final beginToken = this.beginToken;
@@ -754,6 +777,8 @@
return root;
}
+ ChildEntities get _childEntities => ChildEntities();
+
void detachFromParent() {
_parent = null;
}
@@ -843,11 +868,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(awaitKeyword)
- ..add(_expression);
-
- @override
Token get endToken => _expression.endToken;
@override
@@ -861,9 +881,19 @@
Precedence get precedence => Precedence.prefix;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('awaitKeyword', awaitKeyword)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAwaitExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitAwaitExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
}
@@ -903,12 +933,6 @@
Token get beginToken => _leftOperand.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_leftOperand)
- ..add(operator)
- ..add(_rightOperand);
-
- @override
Token get endToken => _rightOperand.endToken;
@override
@@ -929,9 +953,20 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('leftOperand', leftOperand)
+ ..addToken('operator', operator)
+ ..addNode('rightOperand', rightOperand);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitBinaryExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_leftOperand.accept(visitor);
_rightOperand.accept(visitor);
@@ -981,12 +1016,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(keyword)
- ..add(star)
- ..add(_block);
-
- @override
Token get endToken => _block.endToken;
@override
@@ -999,9 +1028,19 @@
bool get isSynchronous => keyword?.lexeme != Keyword.ASYNC.lexeme;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('keyword', keyword)
+ ..addToken('star', star)
+ ..addNode('block', block);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this);
@override
+ DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+ resolver.visitBlockFunctionBody(this, imposedType: imposedType);
+
+ @override
void visitChildren(AstVisitor visitor) {
_block.accept(visitor);
}
@@ -1032,18 +1071,18 @@
Token get beginToken => leftBracket;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftBracket)
- ..addAll(_statements)
- ..add(rightBracket);
-
- @override
Token get endToken => rightBracket;
@override
NodeListImpl<Statement> get statements => _statements;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('statements', statements)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlock(this);
@override
@@ -1072,18 +1111,24 @@
Token get beginToken => literal;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal);
-
- @override
Token get endToken => literal;
@override
bool get isSynthetic => literal.isSynthetic;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('literal', literal);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBooleanLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitBooleanLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -1125,12 +1170,6 @@
Token get beginToken => breakKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(breakKeyword)
- ..add(_label)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -1141,6 +1180,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('breakKeyword', breakKeyword)
+ ..addNode('label', label)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBreakStatement(this);
@override
@@ -1186,11 +1231,6 @@
NodeListImpl<Expression> get cascadeSections => _cascadeSections;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_target)
- ..addAll(_cascadeSections);
-
- @override
Token get endToken => _cascadeSections.endToken!;
@override
@@ -1209,12 +1249,22 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('target', target)
+ ..addNodeList('cascadeSections', cascadeSections);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => null;
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitCascadeExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_target.accept(visitor);
_cascadeSections.accept(visitor);
@@ -1310,18 +1360,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(onKeyword)
- ..add(_exceptionType)
- ..add(catchKeyword)
- ..add(leftParenthesis)
- ..add(_exceptionParameter)
- ..add(comma)
- ..add(_stackTraceParameter)
- ..add(rightParenthesis)
- ..add(_body);
-
- @override
Token get endToken => _body.endToken;
@override
@@ -1346,6 +1384,18 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('onKeyword', onKeyword)
+ ..addNode('exceptionType', exceptionType)
+ ..addToken('catchKeyword', catchKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('exceptionParameter', exceptionParameter)
+ ..addToken('comma', comma)
+ ..addNode('stackTraceParameter', stackTraceParameter)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitCatchClause(this);
@override
@@ -1358,28 +1408,81 @@
}
/// Helper class to allow iteration of child entities of an AST node.
-class ChildEntities
- with IterableMixin<SyntacticEntity>
- implements Iterable<SyntacticEntity> {
+class ChildEntities {
/// The list of child entities to be iterated over.
- final List<SyntacticEntity> _entities = [];
+ final List<ChildEntity> entities = [];
- @override
- Iterator<SyntacticEntity> get iterator => _entities.iterator;
+ List<SyntacticEntity> get syntacticEntities {
+ var result = <SyntacticEntity>[];
+ for (var entity in entities) {
+ var entityValue = entity.value;
+ if (entityValue is SyntacticEntity) {
+ result.add(entityValue);
+ } else if (entityValue is List<Object>) {
+ for (var element in entityValue) {
+ if (element is SyntacticEntity) {
+ result.add(element);
+ }
+ }
+ }
+ }
- /// Add an AST node or token as the next child entity, if it is not `null`.
- void add(SyntacticEntity? entity) {
- if (entity != null) {
- _entities.add(entity);
+ var needsSorting = false;
+ int? lastOffset;
+ for (var entity in result) {
+ if (lastOffset != null && lastOffset > entity.offset) {
+ needsSorting = true;
+ break;
+ }
+ lastOffset = entity.offset;
+ }
+
+ if (needsSorting) {
+ result.sort((a, b) => a.offset - b.offset);
+ }
+
+ return result;
+ }
+
+ void addAll(ChildEntities other) {
+ entities.addAll(other.entities);
+ }
+
+ void addNode(String name, AstNode? value) {
+ if (value != null) {
+ entities.add(
+ ChildEntity(name, value),
+ );
}
}
- /// Add the given items as the next child entities, if [items] is not `null`.
- void addAll(Iterable<SyntacticEntity>? items) {
- if (items != null) {
- _entities.addAll(items);
+ void addNodeList(String name, List<AstNode> value) {
+ entities.add(
+ ChildEntity(name, value),
+ );
+ }
+
+ void addToken(String name, Token? value) {
+ if (value != null) {
+ entities.add(
+ ChildEntity(name, value),
+ );
}
}
+
+ void addTokenList(String name, List<Token> value) {
+ entities.add(
+ ChildEntity(name, value),
+ );
+ }
+}
+
+/// A named child of an [AstNode], usually a token, node, or a list of nodes.
+class ChildEntity {
+ final String name;
+ final Object value;
+
+ ChildEntity(this.name, this.value);
}
/// The declaration of a class.
@@ -1396,9 +1499,11 @@
Token? abstractKeyword;
/// The 'macro' keyword, or `null` if the keyword was absent.
- @override
Token? macroKeyword;
+ /// The 'augment' keyword, or `null` if the keyword was absent.
+ Token? augmentKeyword;
+
/// The token representing the 'class' keyword.
@override
Token classKeyword;
@@ -1428,6 +1533,7 @@
List<Annotation>? metadata,
this.abstractKeyword,
this.macroKeyword,
+ this.augmentKeyword,
this.classKeyword,
SimpleIdentifierImpl name,
TypeParameterListImpl? typeParameters,
@@ -1444,21 +1550,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(abstractKeyword)
- ..add(macroKeyword)
- ..add(classKeyword)
- ..add(_name)
- ..add(_typeParameters)
- ..add(_extendsClause)
- ..add(_withClause)
- ..add(_implementsClause)
- ..add(_nativeClause)
- ..add(leftBracket)
- ..addAll(members)
- ..add(rightBracket);
-
- @override
ClassElement? get declaredElement => _name.staticElement as ClassElement?;
@override
@@ -1470,7 +1561,7 @@
@override
Token get firstTokenAfterCommentAndMetadata {
- return abstractKeyword ?? macroKeyword ?? classKeyword;
+ return abstractKeyword ?? macroKeyword ?? augmentKeyword ?? classKeyword;
}
@override
@@ -1491,6 +1582,22 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('abstractKeyword', abstractKeyword)
+ ..addToken('macroKeyword', macroKeyword)
+ ..addToken('augmentKeyword', augmentKeyword)
+ ..addToken('classKeyword', classKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('extendsClause', extendsClause)
+ ..addNode('withClause', withClause)
+ ..addNode('implementsClause', implementsClause)
+ ..addNode('nativeClause', nativeClause)
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('members', members)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitClassDeclaration(this);
@override
@@ -1652,9 +1759,12 @@
/// The token for the 'macro' keyword, or `null` if this is not defining a
/// macro class.
- @override
Token? macroKeyword;
+ /// The token for the 'augment' keyword, or `null` if this is not defining an
+ /// augmentation class.
+ Token? augmentKeyword;
+
/// The name of the superclass of the class being declared.
NamedTypeImpl _superclass;
@@ -1680,6 +1790,7 @@
this.equals,
this.abstractKeyword,
this.macroKeyword,
+ this.augmentKeyword,
this._superclass,
this._withClause,
this._implementsClause,
@@ -1692,24 +1803,11 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(typedefKeyword)
- ..add(_name)
- ..add(_typeParameters)
- ..add(equals)
- ..add(abstractKeyword)
- ..add(macroKeyword)
- ..add(_superclass)
- ..add(_withClause)
- ..add(_implementsClause)
- ..add(semicolon);
-
- @override
ClassElement? get declaredElement => _name.staticElement as ClassElement?;
@override
Token get firstTokenAfterCommentAndMetadata {
- return abstractKeyword ?? macroKeyword ?? typedefKeyword;
+ return abstractKeyword ?? macroKeyword ?? augmentKeyword ?? typedefKeyword;
}
@override
@@ -1723,10 +1821,14 @@
@override
bool get isAbstract => abstractKeyword != null;
+ @override
+ NamedTypeImpl get superclass => _superclass;
+
set superclass(NamedType superclass) {
_superclass = _becomeParentOf(superclass as NamedTypeImpl);
}
+ @Deprecated('Use superclass instead')
@override
NamedTypeImpl get superclass2 => _superclass;
@@ -1745,6 +1847,20 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('typedefKeyword', typedefKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addToken('equals', equals)
+ ..addToken('abstractKeyword', abstractKeyword)
+ ..addToken('macroKeyword', macroKeyword)
+ ..addToken('augmentKeyword', augmentKeyword)
+ ..addNode('superclass', superclass)
+ ..addNode('withClause', withClause)
+ ..addNode('implementsClause', implementsClause)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitClassTypeAlias(this);
@override
@@ -1759,7 +1875,12 @@
}
abstract class CollectionElementImpl extends AstNodeImpl
- implements CollectionElement {}
+ implements CollectionElement {
+ /// Dispatches this collection element to the [resolver], with the given
+ /// [context] information.
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context);
+}
/// A combinator associated with an import or export directive.
///
@@ -1820,10 +1941,6 @@
Token get beginToken => tokens[0];
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll(tokens);
-
- @override
Token get endToken => tokens[tokens.length - 1];
@override
@@ -1839,6 +1956,10 @@
NodeListImpl<CommentReference> get references => _references;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addTokenList('tokens', tokens);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitComment(this);
@override
@@ -1892,11 +2013,6 @@
Token get beginToken => newKeyword ?? _expression.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(newKeyword)
- ..add(_expression);
-
- @override
Token get endToken => _expression.endToken;
@override
@@ -1916,6 +2032,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('newKeyword', newKeyword)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitCommentReference(this);
@override
@@ -1994,7 +2115,7 @@
/// The line information for this compilation unit.
@override
- LineInfo? lineInfo;
+ final LineInfo lineInfo;
/// The language version information.
LibraryLanguageVersion? languageVersion;
@@ -2013,26 +2134,14 @@
List<Directive>? directives,
List<CompilationUnitMember>? declarations,
this.endToken,
- this.featureSet) {
+ this.featureSet,
+ this.lineInfo) {
_becomeParentOf(_scriptTag);
_directives._initialize(this, directives);
_declarations._initialize(this, declarations);
}
@override
- Iterable<SyntacticEntity> get childEntities {
- ChildEntities result = ChildEntities()..add(_scriptTag);
- if (_directivesAreBeforeDeclarations) {
- result
- ..addAll(_directives)
- ..addAll(_declarations);
- } else {
- result.addAll(sortedDirectivesAndDeclarations);
- }
- return result;
- }
-
- @override
NodeListImpl<CompilationUnitMember> get declarations => _declarations;
@override
@@ -2083,6 +2192,14 @@
]..sort(AstNode.LEXICAL_ORDER);
}
+ @override
+ ChildEntities get _childEntities {
+ return ChildEntities()
+ ..addNode('scriptTag', scriptTag)
+ ..addNodeList('directives', directives)
+ ..addNodeList('declarations', declarations);
+ }
+
/// Return `true` if all of the directives are lexically before any
/// declarations.
bool get _directivesAreBeforeDeclarations {
@@ -2183,14 +2300,6 @@
Token get beginToken => _condition.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_condition)
- ..add(question)
- ..add(_thenExpression)
- ..add(colon)
- ..add(_elseExpression);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression expression) {
@@ -2218,10 +2327,23 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('condition', condition)
+ ..addToken('question', question)
+ ..addNode('thenExpression', thenExpression)
+ ..addToken('colon', colon)
+ ..addNode('elseExpression', elseExpression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitConditionalExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitConditionalExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_condition.accept(visitor);
_thenExpression.accept(visitor);
@@ -2272,16 +2394,6 @@
Token get beginToken => ifKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(ifKeyword)
- ..add(leftParenthesis)
- ..add(_name)
- ..add(equalToken)
- ..add(_value)
- ..add(rightParenthesis)
- ..add(_uri);
-
- @override
Token get endToken => _uri.endToken;
@override
@@ -2306,6 +2418,16 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('ifKeyword', ifKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('name', name)
+ ..addToken('equalToken', equalToken)
+ ..addNode('value', value)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('uri', uri);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitConfiguration(this);
@override
@@ -2450,20 +2572,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(externalKeyword)
- ..add(constKeyword)
- ..add(factoryKeyword)
- ..add(_returnType)
- ..add(period)
- ..add(_name)
- ..add(_parameters)
- ..add(separator)
- ..addAll(initializers)
- ..add(_redirectedConstructor)
- ..add(_body);
-
- @override
Token get endToken {
return _body.endToken;
}
@@ -2508,6 +2616,20 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('externalKeyword', externalKeyword)
+ ..addToken('constKeyword', constKeyword)
+ ..addToken('factoryKeyword', factoryKeyword)
+ ..addNode('returnType', returnType)
+ ..addToken('period', period)
+ ..addNode('name', name)
+ ..addNode('parameters', parameters)
+ ..addToken('separator', separator)
+ ..addNodeList('initializers', initializers)
+ ..addNode('redirectedConstructor', redirectedConstructor)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitConstructorDeclaration(this);
@@ -2566,14 +2688,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(thisKeyword)
- ..add(period)
- ..add(_fieldName)
- ..add(equals)
- ..add(_expression);
-
- @override
Token get endToken => _expression.endToken;
@override
@@ -2591,6 +2705,14 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('thisKeyword', thisKeyword)
+ ..addToken('period', period)
+ ..addNode('fieldName', fieldName)
+ ..addToken('equals', equals)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitConstructorFieldInitializer(this);
@@ -2644,12 +2766,6 @@
Token get beginToken => _type.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_type)
- ..add(period)
- ..add(_name);
-
- @override
Token get endToken {
if (_name != null) {
return _name!.endToken;
@@ -2664,14 +2780,24 @@
_name = _becomeParentOf(name as SimpleIdentifierImpl?);
}
+ @override
+ NamedTypeImpl get type => _type;
+
set type(NamedType type) {
_type = _becomeParentOf(type as NamedTypeImpl);
}
+ @Deprecated('Use type instead')
@override
NamedTypeImpl get type2 => _type;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('type', type)
+ ..addToken('period', period)
+ ..addNode('name', name);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstructorName(this);
@override
@@ -2699,10 +2825,6 @@
Token get beginToken => constructorName.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(constructorName);
-
- @override
ConstructorNameImpl get constructorName => _constructorName;
set constructorName(ConstructorNameImpl value) {
@@ -2716,10 +2838,19 @@
Precedence get precedence => Precedence.postfix;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addNode('constructorName', constructorName);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitConstructorReference(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitConstructorReference(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
constructorName.accept(visitor);
}
@@ -2744,12 +2875,12 @@
Token get beginToken => period;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(period)
- ..add(name);
+ Token get endToken => name.token;
@override
- Token get endToken => name.token;
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('period', period)
+ ..addNode('name', name);
@override
E? accept<E>(AstVisitor<E> visitor) {
@@ -2795,12 +2926,6 @@
Token get beginToken => continueKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(continueKeyword)
- ..add(_label)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -2811,6 +2936,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('continueKeyword', continueKeyword)
+ ..addNode('label', label)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitContinueStatement(this);
@override
@@ -2860,12 +2991,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_type)
- ..add(_identifier);
-
- @override
LocalVariableElement? get declaredElement {
return _identifier.staticElement as LocalVariableElement;
}
@@ -2899,6 +3024,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('type', type)
+ ..addNode('identifier', identifier);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitDeclaredIdentifier(this);
@override
@@ -2964,12 +3095,6 @@
Token get beginToken => _parameter.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_parameter)
- ..add(separator)
- ..add(_defaultValue);
-
- @override
Token? get covariantKeyword => null;
@override
@@ -3013,6 +3138,12 @@
Token? get requiredKeyword => null;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('parameter', parameter)
+ ..addToken('separator', separator)
+ ..addNode('defaultValue', defaultValue);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitDefaultFormalParameter(this);
@@ -3106,16 +3237,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(doKeyword)
- ..add(_body)
- ..add(whileKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(rightParenthesis)
- ..add(semicolon);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression expression) {
@@ -3126,6 +3247,16 @@
Token get endToken => semicolon;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('doKeyword', doKeyword)
+ ..addNode('body', body)
+ ..addToken('whileKeyword', whileKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoStatement(this);
@override
@@ -3152,17 +3283,17 @@
Token get beginToken => _components.beginToken!;
@override
- // TODO(paulberry): add "." tokens.
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll(_components);
-
- @override
NodeListImpl<SimpleIdentifier> get components => _components;
@override
Token get endToken => _components.endToken!;
@override
+ // TODO(paulberry): add "." tokens.
+ ChildEntities get _childEntities =>
+ ChildEntities()..addNodeList('components', components);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitDottedName(this);
@override
@@ -3195,15 +3326,21 @@
Token get beginToken => literal;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal);
-
- @override
Token get endToken => literal;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('literal', literal);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoubleLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitDoubleLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -3228,16 +3365,20 @@
Token get beginToken => semicolon;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyFunctionBody(this);
@override
+ DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+ resolver.visitEmptyFunctionBody(this, imposedType: imposedType);
+
+ @override
void visitChildren(AstVisitor visitor) {
// Empty function bodies have no children.
}
@@ -3259,16 +3400,16 @@
Token get beginToken => semicolon;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
bool get isSynthetic => semicolon.isSynthetic;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyStatement(this);
@override
@@ -3303,13 +3444,13 @@
(typeArguments ?? constructorSelector ?? argumentList).beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(typeArguments)
- ..add(constructorSelector)
- ..add(argumentList);
+ Token get endToken => argumentList.endToken;
@override
- Token get endToken => argumentList.endToken;
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('typeArguments', typeArguments)
+ ..addNode('constructorSelector', constructorSelector)
+ ..addNode('argumentList', argumentList);
@override
E? accept<E>(AstVisitor<E> visitor) {
@@ -3351,11 +3492,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(_name)
- ..add(arguments);
-
- @override
FieldElement get declaredElement => _name.staticElement as FieldElement;
@override
@@ -3372,6 +3508,11 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addNode('name', name)
+ ..addNode('arguments', arguments);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitEnumConstantDeclaration(this);
@@ -3414,6 +3555,9 @@
/// The enumeration constants being declared.
final NodeListImpl<EnumConstantDeclaration> _constants = NodeListImpl._();
+ @override
+ Token? semicolon;
+
/// The members defined by the enum.
final NodeListImpl<ClassMember> _members = NodeListImpl._();
@@ -3435,6 +3579,7 @@
this._implementsClause,
this.leftBracket,
List<EnumConstantDeclaration> constants,
+ this.semicolon,
List<ClassMember> members,
this.rightBracket)
: super(comment, metadata, name) {
@@ -3446,19 +3591,6 @@
}
@override
- // TODO(brianwilkerson) Add commas?
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(enumKeyword)
- ..add(_name)
- ..add(_typeParameters)
- ..add(_withClause)
- ..add(_implementsClause)
- ..add(leftBracket)
- ..addAll(_constants)
- ..addAll(_members)
- ..add(rightBracket);
-
- @override
NodeListImpl<EnumConstantDeclaration> get constants => _constants;
@override
@@ -3496,6 +3628,20 @@
}
@override
+ // TODO(brianwilkerson) Add commas?
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('enumKeyword', enumKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('withClause', withClause)
+ ..addNode('implementsClause', implementsClause)
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('constants', constants)
+ ..addToken('semicolon', semicolon)
+ ..addNodeList('members', members)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitEnumDeclaration(this);
@override
@@ -3541,13 +3687,6 @@
combinators, semicolon);
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_uri)
- ..addAll(combinators)
- ..add(semicolon);
-
- @override
ExportElement? get element => super.element as ExportElement?;
@override
@@ -3556,6 +3695,13 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('uri', uri)
+ ..addNodeList('combinators', combinators)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitExportDirective(this);
@override
@@ -3614,14 +3760,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(keyword)
- ..add(star)
- ..add(functionDefinition)
- ..add(_expression)
- ..add(semicolon);
-
- @override
Token get endToken {
if (semicolon != null) {
return semicolon!;
@@ -3646,10 +3784,22 @@
bool get isSynchronous => keyword?.lexeme != Keyword.ASYNC.lexeme;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('keyword', keyword)
+ ..addToken('star', star)
+ ..addToken('functionDefinition', functionDefinition)
+ ..addNode('expression', expression)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitExpressionFunctionBody(this);
@override
+ DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+ resolver.visitExpressionFunctionBody(this, imposedType: imposedType);
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
}
@@ -3680,6 +3830,8 @@
var parent = child.parent;
if (parent is ConstantContextForExpressionImpl) {
return true;
+ } else if (parent is EnumConstantArguments) {
+ return true;
} else if (parent is TypedLiteralImpl && parent.constKeyword != null) {
// Inside an explicitly `const` list or map literal.
return true;
@@ -3740,6 +3892,20 @@
@override
ExpressionImpl get unParenthesized => this;
+
+ @override
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context) {
+ resolver.analyzeExpression(this, context?.elementType);
+ }
+
+ /// Dispatches this expression to the [resolver], with the given [contextType]
+ /// information.
+ ///
+ /// Note: most code shouldn't call this method directly, but should instead
+ /// call [ResolverVisitor.analyzeExpression], which has some special logic for
+ /// handling dynamic contexts.
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType);
}
/// An expression used as a statement.
@@ -3765,11 +3931,6 @@
Token get beginToken => _expression.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_expression)
- ..add(semicolon);
-
- @override
Token get endToken {
if (semicolon != null) {
return semicolon!;
@@ -3789,6 +3950,11 @@
_expression.isSynthetic && (semicolon == null || semicolon!.isSynthetic);
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('expression', expression)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitExpressionStatement(this);
@override
@@ -3818,21 +3984,25 @@
Token get beginToken => extendsKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(extendsKeyword)
- ..add(_superclass);
+ Token get endToken => _superclass.endToken;
@override
- Token get endToken => _superclass.endToken;
+ NamedTypeImpl get superclass => _superclass;
set superclass(NamedType name) {
_superclass = _becomeParentOf(name as NamedTypeImpl);
}
+ @Deprecated('Use superclass instead')
@override
NamedTypeImpl get superclass2 => _superclass;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('extendsKeyword', extendsKeyword)
+ ..addNode('superclass', superclass);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitExtendsClause(this);
@override
@@ -3911,17 +4081,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(extensionKeyword)
- ..add(name)
- ..add(typeParameters)
- ..add(onKeyword)
- ..add(extendedType)
- ..add(leftBracket)
- ..addAll(members)
- ..add(rightBracket);
-
- @override
ExtensionElement? get declaredElement => _declaredElement;
/// Set the element declared by this declaration to the given [element].
@@ -3974,6 +4133,17 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('extensionKeyword', extensionKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addToken('onKeyword', onKeyword)
+ ..addNode('extendedType', extendedType)
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('members', members)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitExtensionDeclaration(this);
@@ -4029,12 +4199,6 @@
Token get beginToken => _extensionName.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_extensionName)
- ..add(_typeArguments)
- ..add(_argumentList);
-
- @override
Token get endToken => _argumentList.endToken;
@override
@@ -4067,11 +4231,22 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('extensionName', extensionName)
+ ..addNode('typeArguments', typeArguments)
+ ..addNode('argumentList', argumentList);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitExtensionOverride(this);
}
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitExtensionOverride(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_extensionName.accept(visitor);
_typeArguments?.accept(visitor);
@@ -4087,6 +4262,9 @@
@override
Token? abstractKeyword;
+ /// The 'augment' keyword, or `null` if the keyword was not used.
+ Token? augmentKeyword;
+
/// The 'covariant' keyword, or `null` if the keyword was not used.
@override
Token? covariantKeyword;
@@ -4114,6 +4292,7 @@
CommentImpl? comment,
List<Annotation>? metadata,
this.abstractKeyword,
+ this.augmentKeyword,
this.covariantKeyword,
this.externalKeyword,
this.staticKeyword,
@@ -4124,12 +4303,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(staticKeyword)
- ..add(_fieldList)
- ..add(semicolon);
-
- @override
Element? get declaredElement => null;
@override
@@ -4144,8 +4317,8 @@
@override
Token get firstTokenAfterCommentAndMetadata {
- return Token.lexicallyFirst(abstractKeyword, externalKeyword,
- covariantKeyword, staticKeyword) ??
+ return Token.lexicallyFirst(abstractKeyword, augmentKeyword,
+ externalKeyword, covariantKeyword, staticKeyword) ??
_fieldList.beginToken;
}
@@ -4153,6 +4326,12 @@
bool get isStatic => staticKeyword != null;
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('staticKeyword', staticKeyword)
+ ..addNode('fields', fields)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFieldDeclaration(this);
@override
@@ -4243,15 +4422,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_type)
- ..add(thisKeyword)
- ..add(period)
- ..add(identifier)
- ..add(_parameters);
-
- @override
Token get endToken {
return question ?? _parameters?.endToken ?? identifier.endToken;
}
@@ -4287,6 +4457,15 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('type', type)
+ ..addToken('thisKeyword', thisKeyword)
+ ..addToken('period', period)
+ ..addNode('identifier', identifier)
+ ..addNode('parameters', parameters);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitFieldFormalParameter(this);
@@ -4319,11 +4498,6 @@
Token get beginToken => inKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(inKeyword)
- ..add(_iterable);
-
- @override
Token get endToken => _iterable.endToken;
@override
@@ -4334,6 +4508,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('inKeyword', inKeyword)
+ ..addNode('iterable', iterable);
+
+ @override
void visitChildren(AstVisitor visitor) {
_iterable.accept(visitor);
}
@@ -4356,11 +4535,6 @@
Token get beginToken => _loopVariable.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_loopVariable)
- ..addAll(super.childEntities);
-
- @override
DeclaredIdentifierImpl get loopVariable => _loopVariable;
set loopVariable(DeclaredIdentifier variable) {
@@ -4368,6 +4542,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('loopVariable', loopVariable)
+ ..addAll(super._childEntities);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitForEachPartsWithDeclaration(this);
@@ -4395,11 +4574,6 @@
Token get beginToken => _identifier.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_identifier)
- ..addAll(super.childEntities);
-
- @override
SimpleIdentifierImpl get identifier => _identifier;
set identifier(SimpleIdentifier identifier) {
@@ -4407,6 +4581,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('identifier', identifier)
+ ..addAll(super._childEntities);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitForEachPartsWithIdentifier(this);
@@ -4453,15 +4632,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(awaitKeyword)
- ..add(forKeyword)
- ..add(leftParenthesis)
- ..add(_forLoopParts)
- ..add(rightParenthesis)
- ..add(_body);
-
- @override
Token get endToken => _body.endToken;
@override
@@ -4472,9 +4642,24 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('awaitKeyword', awaitKeyword)
+ ..addToken('forKeyword', forKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('forLoopParts', forLoopParts)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitForElement(this);
@override
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context) {
+ resolver.visitForElement(this, context: context);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_forLoopParts.accept(visitor);
_body.accept(visitor);
@@ -4608,25 +4793,6 @@
Token get beginToken => leftParenthesis;
@override
- Iterable<SyntacticEntity> get childEntities {
- // TODO(paulberry): include commas.
- ChildEntities result = ChildEntities()..add(leftParenthesis);
- bool leftDelimiterNeeded = leftDelimiter != null;
- int length = _parameters.length;
- for (int i = 0; i < length; i++) {
- FormalParameter parameter = _parameters[i];
- if (leftDelimiterNeeded && leftDelimiter!.offset < parameter.offset) {
- result.add(leftDelimiter);
- leftDelimiterNeeded = false;
- }
- result.add(parameter);
- }
- return result
- ..add(rightDelimiter)
- ..add(rightParenthesis);
- }
-
- @override
Token get endToken => rightParenthesis;
@override
@@ -4643,6 +4809,25 @@
NodeListImpl<FormalParameter> get parameters => _parameters;
@override
+ ChildEntities get _childEntities {
+ // TODO(paulberry): include commas.
+ var result = ChildEntities()..addToken('leftParenthesis', leftParenthesis);
+ bool leftDelimiterNeeded = leftDelimiter != null;
+ int length = _parameters.length;
+ for (int i = 0; i < length; i++) {
+ FormalParameter parameter = _parameters[i];
+ if (leftDelimiterNeeded && leftDelimiter!.offset < parameter.offset) {
+ result..addToken('leftDelimiter', leftDelimiter);
+ leftDelimiterNeeded = false;
+ }
+ result..addNode('parameter', parameter);
+ }
+ return result
+ ..addToken('rightDelimiter', rightDelimiter)
+ ..addToken('rightParenthesis', rightParenthesis);
+ }
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFormalParameterList(this);
@override
@@ -4679,13 +4864,6 @@
Token get beginToken => leftSeparator;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftSeparator)
- ..add(_condition)
- ..add(rightSeparator)
- ..addAll(_updaters);
-
- @override
ExpressionImpl? get condition => _condition;
set condition(Expression? expression) {
@@ -4699,6 +4877,13 @@
NodeListImpl<Expression> get updaters => _updaters;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftSeparator', leftSeparator)
+ ..addNode('condition', condition)
+ ..addToken('rightSeparator', rightSeparator)
+ ..addNodeList('updaters', updaters);
+
+ @override
void visitChildren(AstVisitor visitor) {
_condition?.accept(visitor);
_updaters.accept(visitor);
@@ -4729,11 +4914,6 @@
Token get beginToken => _variableList.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_variableList)
- ..addAll(super.childEntities);
-
- @override
VariableDeclarationListImpl get variables => _variableList;
set variables(VariableDeclarationList? variableList) {
@@ -4742,6 +4922,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('variables', variables)
+ ..addAll(super._childEntities);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitForPartsWithDeclarations(this);
@@ -4776,11 +4961,6 @@
Token get beginToken => initialization?.beginToken ?? super.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_initialization)
- ..addAll(super.childEntities);
-
- @override
ExpressionImpl? get initialization => _initialization;
set initialization(Expression? initialization) {
@@ -4788,6 +4968,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('initialization', initialization)
+ ..addAll(super._childEntities);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitForPartsWithExpression(this);
@@ -4834,15 +5019,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(awaitKeyword)
- ..add(forKeyword)
- ..add(leftParenthesis)
- ..add(_forLoopParts)
- ..add(rightParenthesis)
- ..add(_body);
-
- @override
Token get endToken => _body.endToken;
@override
@@ -4853,6 +5029,15 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('awaitKeyword', awaitKeyword)
+ ..addToken('forKeyword', forKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('forLoopParts', forLoopParts)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitForStatement(this);
@override
@@ -4911,6 +5096,12 @@
}
return localVariableInfo!.potentiallyMutatedInScope.contains(variable);
}
+
+ /// Dispatch this function body to the resolver, imposing [imposedType] as the
+ /// return type context for `return` statements.
+ ///
+ /// Return value is the actual return type of the method.
+ DartType resolve(ResolverVisitor resolver, DartType? imposedType);
}
/// A top-level declaration.
@@ -4923,6 +5114,10 @@
/// [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
class FunctionDeclarationImpl extends NamedCompilationUnitMemberImpl
implements FunctionDeclaration {
+ /// The token representing the 'augment' keyword, or `null` if this is not an
+ /// function augmentation.
+ Token? augmentKeyword;
+
/// The token representing the 'external' keyword, or `null` if this is not an
/// external function.
@override
@@ -4948,6 +5143,7 @@
FunctionDeclarationImpl(
CommentImpl? comment,
List<Annotation>? metadata,
+ this.augmentKeyword,
this.externalKeyword,
this._returnType,
this.propertyKeyword,
@@ -4959,14 +5155,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(externalKeyword)
- ..add(_returnType)
- ..add(propertyKeyword)
- ..add(_name)
- ..add(_functionExpression);
-
- @override
ExecutableElement? get declaredElement =>
_name.staticElement as ExecutableElement?;
@@ -4975,7 +5163,8 @@
@override
Token get firstTokenAfterCommentAndMetadata {
- return externalKeyword ??
+ return augmentKeyword ??
+ externalKeyword ??
_returnType?.beginToken ??
propertyKeyword ??
_name.beginToken;
@@ -5003,6 +5192,15 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('augmentKeyword', augmentKeyword)
+ ..addToken('externalKeyword', externalKeyword)
+ ..addNode('returnType', returnType)
+ ..addToken('propertyKeyword', propertyKeyword)
+ ..addNode('name', name)
+ ..addNode('functionExpression', functionExpression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionDeclaration(this);
@override
@@ -5029,10 +5227,6 @@
Token get beginToken => _functionDeclaration.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(_functionDeclaration);
-
- @override
Token get endToken => _functionDeclaration.endToken;
@override
@@ -5044,6 +5238,10 @@
}
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addNode('functionDeclaration', functionDeclaration);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitFunctionDeclarationStatement(this);
@@ -5070,6 +5268,11 @@
/// The body of the function.
FunctionBodyImpl _body;
+ /// If resolution has been performed, this boolean indicates whether a
+ /// function type was supplied via context for this function expression.
+ /// `false` if resolution hasn't been performed yet.
+ bool wasFunctionTypeSupplied = false;
+
@override
ExecutableElement? declaredElement;
@@ -5098,12 +5301,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_typeParameters)
- ..add(_parameters)
- ..add(_body);
-
- @override
Token get endToken {
return _body.endToken;
}
@@ -5126,9 +5323,20 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('parameters', parameters)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitFunctionExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_typeParameters?.accept(visitor);
_parameters?.accept(visitor);
@@ -5166,11 +5374,6 @@
Token get beginToken => _function.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_function)
- ..add(_argumentList);
-
- @override
Token get endToken => _argumentList.endToken;
@override
@@ -5184,6 +5387,11 @@
Precedence get precedence => Precedence.postfix;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('function', function)
+ ..addNode('argumentList', argumentList);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
@override
@@ -5191,6 +5399,11 @@
visitor.visitFunctionExpressionInvocation(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitFunctionExpressionInvocation(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_function.accept(visitor);
_typeArguments?.accept(visitor);
@@ -5222,11 +5435,6 @@
Token get beginToken => function.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(function)
- ..add(typeArguments);
-
- @override
Token get endToken => typeArguments?.endToken ?? function.endToken;
@override
@@ -5248,9 +5456,19 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('function', function)
+ ..addNode('typeArguments', typeArguments);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionReference(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitFunctionReference(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
function.accept(visitor);
typeArguments?.accept(visitor);
@@ -5297,15 +5515,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(typedefKeyword)
- ..add(_returnType)
- ..add(_name)
- ..add(_typeParameters)
- ..add(_parameters)
- ..add(semicolon);
-
- @override
TypeAliasElement? get declaredElement =>
_name.staticElement as TypeAliasElement?;
@@ -5331,6 +5540,15 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('typedefKeyword', typedefKeyword)
+ ..addNode('returnType', returnType)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('parameters', parameters)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionTypeAlias(this);
@override
@@ -5401,12 +5619,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(_returnType)
- ..add(identifier)
- ..add(parameters);
-
- @override
Token get endToken => question ?? _parameters.endToken;
@override
@@ -5440,6 +5652,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addNode('returnType', returnType)
+ ..addNode('identifier', identifier)
+ ..addNode('parameters', parameters);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitFunctionTypedFormalParameter(this);
@@ -5520,14 +5738,6 @@
Token get beginToken => _returnType?.beginToken ?? functionKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_returnType)
- ..add(functionKeyword)
- ..add(_typeParameters)
- ..add(_parameters)
- ..add(question);
-
- @override
Token get endToken => question ?? _parameters.endToken;
@override
@@ -5556,6 +5766,14 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('returnType', returnType)
+ ..addToken('functionKeyword', functionKeyword)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('parameters', parameters)
+ ..addToken('question', question);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitGenericFunctionType(this);
}
@@ -5603,15 +5821,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..addAll(metadata)
- ..add(typedefKeyword)
- ..add(name)
- ..add(_typeParameters)
- ..add(equals)
- ..add(_type);
-
- @override
Element? get declaredElement => name.staticElement;
/// The type of function being defined by the alias.
@@ -5645,6 +5854,15 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNodeList('metadata', metadata)
+ ..addToken('typedefKeyword', typedefKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addToken('equals', equals)
+ ..addNode('type', type);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitGenericTypeAlias(this);
}
@@ -5679,17 +5897,17 @@
Token get beginToken => hideKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(hideKeyword)
- ..addAll(elements);
-
- @override
NodeListImpl<ShowHideClauseElement> get elements => _elements;
@override
Token get endToken => _elements.endToken!;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('hideKeyword', hideKeyword)
+ ..addNodeList('elements', elements);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitHideClause(this);
@override
@@ -5714,17 +5932,17 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(keyword)
- ..addAll(_hiddenNames);
-
- @override
Token get endToken => _hiddenNames.endToken!;
@override
NodeListImpl<SimpleIdentifier> get hiddenNames => _hiddenNames;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('keyword', keyword)
+ ..addNodeList('hiddenNames', hiddenNames);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitHideCombinator(this);
@override
@@ -5785,16 +6003,6 @@
Token get beginToken => ifKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(ifKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(rightParenthesis)
- ..add(_thenElement)
- ..add(elseKeyword)
- ..add(_elseElement);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression condition) {
@@ -5819,9 +6027,25 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('ifKeyword', ifKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('thenElement', thenElement)
+ ..addToken('elseKeyword', elseKeyword)
+ ..addNode('elseElement', elseElement);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfElement(this);
@override
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context) {
+ resolver.visitIfElement(this, context: context);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_condition.accept(visitor);
_thenElement.accept(visitor);
@@ -5875,16 +6099,6 @@
Token get beginToken => ifKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(ifKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(rightParenthesis)
- ..add(_thenStatement)
- ..add(elseKeyword)
- ..add(_elseStatement);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression condition) {
@@ -5914,6 +6128,16 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('ifKeyword', ifKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('thenStatement', thenStatement)
+ ..addToken('elseKeyword', elseKeyword)
+ ..addNode('elseStatement', elseStatement);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfStatement(this);
@override
@@ -5945,18 +6169,22 @@
Token get beginToken => implementsKeyword;
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(implementsKeyword)
- ..addAll(interfaces2);
-
- @override
Token get endToken => _interfaces.endToken!;
@override
+ NodeListImpl<NamedType> get interfaces => _interfaces;
+
+ @Deprecated('Use interfaces instead')
+ @override
NodeListImpl<NamedType> get interfaces2 => _interfaces;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('implementsKeyword', implementsKeyword)
+ ..addNodeList('interfaces', interfaces);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitImplementsClause(this);
@override
@@ -5991,11 +6219,6 @@
Token get beginToken => expression.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(expression)
- ..add(typeArguments);
-
- @override
Token get endToken => typeArguments?.endToken ?? expression.endToken;
@override
@@ -6017,11 +6240,21 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('expression', expression)
+ ..addNode('typeArguments', typeArguments);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitImplicitCallReference(this);
}
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitImplicitCallReference(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
expression.accept(visitor);
typeArguments?.accept(visitor);
@@ -6037,6 +6270,10 @@
// [Combinator]* ';'
class ImportDirectiveImpl extends NamespaceDirectiveImpl
implements ImportDirective {
+ /// The token representing the 'augment' keyword, or `null` if the import is
+ /// not a library augmentation import.
+ Token? augmentKeyword;
+
/// The token representing the 'deferred' keyword, or `null` if the imported
/// is not deferred.
@override
@@ -6061,6 +6298,7 @@
CommentImpl? comment,
List<Annotation>? metadata,
Token keyword,
+ this.augmentKeyword,
StringLiteralImpl libraryUri,
List<Configuration>? configurations,
this.deferredKeyword,
@@ -6074,16 +6312,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_uri)
- ..add(deferredKeyword)
- ..add(asKeyword)
- ..add(_prefix)
- ..addAll(combinators)
- ..add(semicolon);
-
- @override
ImportElement? get element => super.element as ImportElement?;
@override
@@ -6099,6 +6327,17 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addToken('augmentKeyword', augmentKeyword)
+ ..addNode('uri', uri)
+ ..addToken('deferredKeyword', deferredKeyword)
+ ..addToken('asKeyword', asKeyword)
+ ..addNode('prefix', prefix)
+ ..addNodeList('combinators', combinators)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitImportDirective(this);
@override
@@ -6166,14 +6405,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_target)
- ..add(period)
- ..add(leftBracket)
- ..add(_index)
- ..add(rightBracket);
-
- @override
Token get endToken => rightBracket;
@override
@@ -6231,6 +6462,14 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('target', target)
+ ..addToken('period', period)
+ ..addToken('leftBracket', leftBracket)
+ ..addNode('index', index)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
AstNode get _nullShortingExtensionCandidate => parent!;
/// If the AST structure has been resolved, and the function being invoked is
@@ -6287,6 +6526,11 @@
}
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitIndexExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_target?.accept(visitor);
_index.accept(visitor);
@@ -6345,13 +6589,6 @@
Token get beginToken => keyword ?? _constructorName.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(keyword)
- ..add(_constructorName)
- ..add(_typeArguments)
- ..add(_argumentList);
-
- @override
ConstructorNameImpl get constructorName => _constructorName;
set constructorName(ConstructorName name) {
@@ -6391,10 +6628,22 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('keyword', keyword)
+ ..addNode('constructorName', constructorName)
+ ..addNode('typeArguments', typeArguments)
+ ..addNode('argumentList', argumentList);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitInstanceCreationExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitInstanceCreationExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_constructorName.accept(visitor);
_typeArguments?.accept(visitor);
@@ -6430,9 +6679,6 @@
Token get beginToken => literal;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal);
-
- @override
Token get endToken => literal;
/// Returns whether this literal's [parent] is a [PrefixExpression] of unary
@@ -6448,9 +6694,18 @@
}
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('literal', literal);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitIntegerLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitIntegerLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -6548,12 +6803,6 @@
Token get beginToken => leftBracket;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftBracket)
- ..add(_expression)
- ..add(rightBracket);
-
- @override
Token get endToken => rightBracket ?? _expression.endToken;
@override
@@ -6564,6 +6813,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftBracket', leftBracket)
+ ..addNode('expression', expression)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitInterpolationExpression(this);
@@ -6595,9 +6850,6 @@
Token get beginToken => contents;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(contents);
-
- @override
int get contentsEnd => offset + _lexemeHelper.end;
@override
@@ -6609,6 +6861,10 @@
@override
StringInterpolation get parent => super.parent as StringInterpolation;
+ @override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('contents', contents);
+
StringLexemeHelper get _lexemeHelper {
String lexeme = contents.lexeme;
return StringLexemeHelper(lexeme, identical(this, parent.elements.first),
@@ -6691,13 +6947,6 @@
Token get beginToken => _expression.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_expression)
- ..add(isOperator)
- ..add(notOperator)
- ..add(_type);
-
- @override
Token get endToken => _type.endToken;
@override
@@ -6718,9 +6967,21 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('expression', expression)
+ ..addToken('isOperator', isOperator)
+ ..addToken('notOperator', notOperator)
+ ..addNode('type', type);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitIsExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitIsExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
_type.accept(visitor);
@@ -6753,11 +7014,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..addAll(_labels)
- ..add(_statement);
-
- @override
Token get endToken => _statement.endToken;
@override
@@ -6774,6 +7030,11 @@
StatementImpl get unlabeled => _statement.unlabeled;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNodeList('labels', labels)
+ ..addNode('statement', statement);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabeledStatement(this);
@override
@@ -6804,11 +7065,6 @@
Token get beginToken => _label.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_label)
- ..add(colon);
-
- @override
Token get endToken => colon;
@override
@@ -6819,6 +7075,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('label', label)
+ ..addToken('colon', colon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabel(this);
@override
@@ -6853,12 +7114,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(libraryKeyword)
- ..add(_name)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -6875,6 +7130,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('libraryKeyword', libraryKeyword)
+ ..addNode('name', name)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitLibraryDirective(this);
@override
@@ -6902,11 +7163,6 @@
Token get beginToken => _components.beginToken!;
@override
- // TODO(paulberry): add "." tokens.
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll(_components);
-
- @override
NodeListImpl<SimpleIdentifier> get components => _components;
@override
@@ -6936,9 +7192,19 @@
Element? get staticElement => null;
@override
+ // TODO(paulberry): add "." tokens.
+ ChildEntities get _childEntities =>
+ ChildEntities()..addNodeList('components', components);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitLibraryIdentifier(this);
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitLibraryIdentifier(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_components.accept(visitor);
}
@@ -6994,22 +7260,27 @@
}
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(leftBracket)
- ..addAll(_elements)
- ..add(rightBracket);
-
- @override
NodeListImpl<CollectionElement> get elements => _elements;
@override
Token get endToken => rightBracket;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('elements', elements)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitListLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitListLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
_elements.accept(visitor);
@@ -7070,12 +7341,6 @@
Token get beginToken => _key.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_key)
- ..add(separator)
- ..add(_value);
-
- @override
Token get endToken => _value.endToken;
@override
@@ -7093,9 +7358,21 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('key', key)
+ ..addToken('separator', separator)
+ ..addNode('value', value);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitMapLiteralEntry(this);
@override
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context) {
+ resolver.visitMapLiteralEntry(this, context: context);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_key.accept(visitor);
_value.accept(visitor);
@@ -7189,17 +7466,6 @@
_body = _becomeParentOf(functionBody as FunctionBodyImpl);
}
- @override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(externalKeyword)
- ..add(modifierKeyword)
- ..add(_returnType)
- ..add(propertyKeyword)
- ..add(operatorKeyword)
- ..add(_name)
- ..add(_parameters)
- ..add(_body);
-
/// Return the element associated with this method, or `null` if the AST
/// structure has not been resolved. The element can either be a
/// [MethodElement], if this represents the declaration of a normal method, or
@@ -7268,6 +7534,17 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('externalKeyword', externalKeyword)
+ ..addToken('modifierKeyword', modifierKeyword)
+ ..addNode('returnType', returnType)
+ ..addToken('propertyKeyword', propertyKeyword)
+ ..addToken('operatorKeyword', operatorKeyword)
+ ..addNode('name', name)
+ ..addNode('parameters', parameters)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodDeclaration(this);
@override
@@ -7330,13 +7607,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_target)
- ..add(operator)
- ..add(_methodName)
- ..add(_argumentList);
-
- @override
Token get endToken => _argumentList.endToken;
@override
@@ -7412,12 +7682,25 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('target', target)
+ ..addToken('operator', operator)
+ ..addNode('methodName', methodName)
+ ..addNode('typeArguments', typeArguments)
+ ..addNode('argumentList', argumentList);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodInvocation(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitMethodInvocation(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_target?.accept(visitor);
_methodName.accept(visitor);
@@ -7436,6 +7719,9 @@
/// [RequiresClause]? [ImplementsClause]? '{' [ClassMember]* '}'
class MixinDeclarationImpl extends ClassOrMixinDeclarationImpl
implements MixinDeclaration {
+ /// Return the 'augment' keyword, or `null` if the keyword was absent.
+ Token? augmentKeyword;
+
@override
Token mixinKeyword;
@@ -7453,6 +7739,7 @@
MixinDeclarationImpl(
CommentImpl? comment,
List<Annotation>? metadata,
+ this.augmentKeyword,
this.mixinKeyword,
SimpleIdentifierImpl name,
TypeParameterListImpl? typeParameters,
@@ -7467,17 +7754,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(mixinKeyword)
- ..add(_name)
- ..add(_typeParameters)
- ..add(_onClause)
- ..add(_implementsClause)
- ..add(leftBracket)
- ..addAll(members)
- ..add(rightBracket);
-
- @override
ClassElement? get declaredElement => _name.staticElement as ClassElement?;
@override
@@ -7502,6 +7778,17 @@
TypeParameterListImpl? get typeParameters => _typeParameters;
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('mixinKeyword', mixinKeyword)
+ ..addNode('name', name)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('onClause', onClause)
+ ..addNode('implementsClause', implementsClause)
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('members', members)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitMixinDeclaration(this);
@override
@@ -7560,11 +7847,6 @@
Token get beginToken => _name.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_name)
- ..add(_expression);
-
- @override
ParameterElement? get element {
var element = _name.label.staticElement;
if (element is ParameterElement) {
@@ -7594,9 +7876,19 @@
Precedence get precedence => Precedence.none;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('name', name)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitNamedExpression(this);
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitNamedExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_name.accept(visitor);
_expression.accept(visitor);
@@ -7635,12 +7927,6 @@
Token get beginToken => _name.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_name)
- ..add(_typeArguments)
- ..add(question);
-
- @override
Token get endToken => question ?? _typeArguments?.endToken ?? _name.endToken;
@override
@@ -7670,6 +7956,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('name', name)
+ ..addNode('typeArguments', typeArguments)
+ ..addToken('question', question);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitNamedType(this);
@override
@@ -7761,11 +8053,6 @@
Token get beginToken => nativeKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(nativeKeyword)
- ..add(_name);
-
- @override
Token get endToken {
return _name?.endToken ?? nativeKeyword;
}
@@ -7778,6 +8065,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('nativeKeyword', nativeKeyword)
+ ..addNode('name', name);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeClause(this);
@override
@@ -7816,12 +8108,6 @@
Token get beginToken => nativeKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(nativeKeyword)
- ..add(_stringLiteral)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -7832,9 +8118,19 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('nativeKeyword', nativeKeyword)
+ ..addNode('stringLiteral', stringLiteral)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeFunctionBody(this);
@override
+ DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+ resolver.visitNativeFunctionBody(this, imposedType: imposedType);
+
+ @override
void visitChildren(AstVisitor visitor) {
_stringLiteral?.accept(visitor);
}
@@ -8030,19 +8326,13 @@
]..sort(AstNode.LEXICAL_ORDER);
}
+ @override
ChildEntities get _childEntities {
- ChildEntities result = ChildEntities();
- if (_commentIsBeforeAnnotations()) {
- result
- ..add(_comment)
- ..addAll(_metadata);
- } else {
- result.addAll(sortedCommentAndAnnotations);
- }
- result
- ..add(requiredKeyword)
- ..add(covariantKeyword);
- return result;
+ return ChildEntities()
+ ..addNode('documentationComment', documentationComment)
+ ..addNodeList('metadata', metadata)
+ ..addToken('requiredKeyword', requiredKeyword)
+ ..addToken('covariantKeyword', covariantKeyword);
}
@override
@@ -8089,15 +8379,21 @@
Token get beginToken => literal;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal);
-
- @override
Token get endToken => literal;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('literal', literal);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitNullLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -8150,18 +8446,22 @@
Token get beginToken => onKeyword;
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(onKeyword)
- ..addAll(superclassConstraints2);
-
- @override
Token get endToken => _superclassConstraints.endToken!;
@override
+ NodeListImpl<NamedType> get superclassConstraints => _superclassConstraints;
+
+ @Deprecated('Use superclassConstraints instead')
+ @override
NodeListImpl<NamedType> get superclassConstraints2 => _superclassConstraints;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('onKeyword', onKeyword)
+ ..addNodeList('superclassConstraints', superclassConstraints);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitOnClause(this);
@override
@@ -8197,12 +8497,6 @@
Token get beginToken => leftParenthesis;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftParenthesis)
- ..add(_expression)
- ..add(rightParenthesis);
-
- @override
Token get endToken => rightParenthesis;
@override
@@ -8227,10 +8521,21 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('expression', expression)
+ ..addToken('rightParenthesis', rightParenthesis);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitParenthesizedExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitParenthesizedExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
}
@@ -8257,12 +8562,6 @@
: super(comment, metadata, partUri);
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(partKeyword)
- ..add(_uri)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -8275,6 +8574,12 @@
CompilationUnitElement? get uriElement => element as CompilationUnitElement?;
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('partKeyword', partKeyword)
+ ..addNode('uri', uri)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPartDirective(this);
}
@@ -8320,14 +8625,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(partKeyword)
- ..add(ofKeyword)
- ..add(_uri)
- ..add(_libraryName)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -8351,6 +8648,14 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('partKeyword', partKeyword)
+ ..addToken('ofKeyword', ofKeyword)
+ ..addNode('uri', uri)
+ ..addNode('libraryName', libraryName)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPartOfDirective(this);
@override
@@ -8390,11 +8695,6 @@
Token get beginToken => _operand.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_operand)
- ..add(operator);
-
- @override
Token get endToken => operator;
@override
@@ -8408,6 +8708,11 @@
Precedence get precedence => Precedence.postfix;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('operand', operand)
+ ..addToken('operator', operator);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
/// If the AST structure has been resolved, and the function being invoked is
@@ -8429,6 +8734,11 @@
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPostfixExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitPostfixExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_operand.accept(visitor);
}
@@ -8464,12 +8774,6 @@
Token get beginToken => _prefix.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_prefix)
- ..add(period)
- ..add(_identifier);
-
- @override
Token get endToken => _identifier.endToken;
@override
@@ -8512,9 +8816,20 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('prefix', prefix)
+ ..addToken('period', period)
+ ..addNode('identifier', identifier);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixedIdentifier(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitPrefixedIdentifier(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_prefix.accept(visitor);
_identifier.accept(visitor);
@@ -8550,11 +8865,6 @@
Token get beginToken => operator;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(operator)
- ..add(_operand);
-
- @override
Token get endToken => _operand.endToken;
@override
@@ -8568,6 +8878,11 @@
Precedence get precedence => Precedence.prefix;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('operator', operator)
+ ..addNode('operand', operand);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
/// If the AST structure has been resolved, and the function being invoked is
@@ -8589,6 +8904,11 @@
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitPrefixExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_operand.accept(visitor);
}
@@ -8634,12 +8954,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_target)
- ..add(operator)
- ..add(_propertyName);
-
- @override
Token get endToken => _propertyName.endToken;
@override
@@ -8697,12 +9011,23 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('target', target)
+ ..addToken('operator', operator)
+ ..addNode('propertyName', propertyName);
+
+ @override
AstNode? get _nullShortingExtensionCandidate => parent;
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitPropertyAccess(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitPropertyAccess(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_target?.accept(visitor);
_propertyName.accept(visitor);
@@ -8762,13 +9087,6 @@
Token get beginToken => thisKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(thisKeyword)
- ..add(period)
- ..add(_constructorName)
- ..add(_argumentList);
-
- @override
SimpleIdentifierImpl? get constructorName => _constructorName;
set constructorName(SimpleIdentifier? identifier) {
@@ -8779,6 +9097,13 @@
Token get endToken => _argumentList.endToken;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('thisKeyword', thisKeyword)
+ ..addToken('period', period)
+ ..addNode('constructorName', constructorName)
+ ..addNode('argumentList', argumentList);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitRedirectingConstructorInvocation(this);
@@ -8806,19 +9131,24 @@
Token get beginToken => rethrowKeyword;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(rethrowKeyword);
-
- @override
Token get endToken => rethrowKeyword;
@override
Precedence get precedence => Precedence.assignment;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('rethrowKeyword', rethrowKeyword);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitRethrowExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitRethrowExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -8851,12 +9181,6 @@
Token get beginToken => returnKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(returnKeyword)
- ..add(_expression)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -8867,6 +9191,12 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('returnKeyword', returnKeyword)
+ ..addNode('expression', expression)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitReturnStatement(this);
@override
@@ -8892,11 +9222,11 @@
Token get beginToken => scriptTag;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(scriptTag);
+ Token get endToken => scriptTag;
@override
- Token get endToken => scriptTag;
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('scriptTag', scriptTag);
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitScriptTag(this);
@@ -8957,13 +9287,6 @@
}
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(leftBracket)
- ..addAll(elements)
- ..add(rightBracket);
-
- @override
NodeListImpl<CollectionElement> get elements => _elements;
@override
@@ -8976,6 +9299,13 @@
bool get isSet => _resolvedKind == _SetOrMapKind.set;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('elements', elements)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSetOrMapLiteral(this);
void becomeMap() {
@@ -8995,6 +9325,11 @@
}
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitSetOrMapLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
_elements.accept(visitor);
@@ -9022,17 +9357,17 @@
Token get beginToken => showKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(showKeyword)
- ..addAll(elements);
-
- @override
NodeListImpl<ShowHideClauseElement> get elements => _elements;
@override
Token get endToken => _elements.endToken!;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('showKeyword', showKeyword)
+ ..addNodeList('elements', elements);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitShowClause(this);
@override
@@ -9058,18 +9393,18 @@
}
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(keyword)
- ..addAll(_shownNames);
-
- @override
Token get endToken => _shownNames.endToken!;
@override
NodeListImpl<SimpleIdentifier> get shownNames => _shownNames;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('keyword', keyword)
+ ..addNodeList('shownNames', shownNames);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitShowCombinator(this);
@override
@@ -9102,11 +9437,12 @@
Token get beginToken => modifier ?? name.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll([if (modifier != null) modifier!, name]);
+ Token get endToken => name.endToken;
@override
- Token get endToken => name.endToken;
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('modifier', modifier)
+ ..addNode('name', name);
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitShowHideElement(this);
@@ -9173,12 +9509,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_type)
- ..add(identifier);
-
- @override
Token get endToken => identifier?.endToken ?? type!.endToken;
@override
@@ -9195,6 +9525,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('type', type)
+ ..addNode('identifier', identifier);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitSimpleFormalParameter(this);
@@ -9253,9 +9589,6 @@
Token get beginToken => token;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(token);
-
- @override
Token get endToken => token;
@override
@@ -9319,6 +9652,9 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()..addToken('token', token);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleIdentifier(this);
@override
@@ -9412,6 +9748,11 @@
}
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitSimpleIdentifier(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -9454,9 +9795,6 @@
Token get beginToken => literal;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal);
-
- @override
int get contentsEnd => offset + _helper.end;
@override
@@ -9477,6 +9815,10 @@
@override
bool get isSynthetic => literal.isSynthetic;
+ @override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('literal', literal);
+
StringLexemeHelper get _helper {
return StringLexemeHelper(literal.lexeme, true, true);
}
@@ -9485,6 +9827,11 @@
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleStringLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitSimpleStringLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -9518,11 +9865,6 @@
Token get beginToken => spreadOperator;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(spreadOperator)
- ..add(_expression);
-
- @override
Token get endToken => _expression.endToken;
@override
@@ -9537,11 +9879,22 @@
spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('spreadOperator', spreadOperator)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitSpreadElement(this);
}
@override
+ void resolveElement(
+ ResolverVisitor resolver, CollectionLiteralContext? context) {
+ resolver.visitSpreadElement(this, context: context);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
}
@@ -9602,10 +9955,6 @@
Token get beginToken => _elements.beginToken!;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..addAll(_elements);
-
- @override
int get contentsEnd {
var element = _elements.last as InterpolationString;
return element.contentsEnd;
@@ -9641,6 +9990,10 @@
InterpolationStringImpl get lastString =>
elements.last as InterpolationStringImpl;
+ @override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addNodeList('elements', elements);
+
StringLexemeHelper get _firstHelper {
var lastString = _elements.first as InterpolationString;
String lexeme = lastString.contents.lexeme;
@@ -9651,6 +10004,11 @@
E? accept<E>(AstVisitor<E> visitor) => visitor.visitStringInterpolation(this);
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitStringInterpolation(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_elements.accept(visitor);
}
@@ -9824,13 +10182,6 @@
Token get beginToken => superKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(superKeyword)
- ..add(period)
- ..add(_constructorName)
- ..add(_argumentList);
-
- @override
SimpleIdentifierImpl? get constructorName => _constructorName;
set constructorName(SimpleIdentifier? identifier) {
@@ -9841,6 +10192,13 @@
Token get endToken => _argumentList.endToken;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('superKeyword', superKeyword)
+ ..addToken('period', period)
+ ..addNode('constructorName', constructorName)
+ ..addNode('argumentList', argumentList);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitSuperConstructorInvocation(this);
@@ -9867,19 +10225,24 @@
Token get beginToken => superKeyword;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(superKeyword);
-
- @override
Token get endToken => superKeyword;
@override
Precedence get precedence => Precedence.primary;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('superKeyword', superKeyword);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSuperExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitSuperExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -9966,15 +10329,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_type)
- ..add(superKeyword)
- ..add(period)
- ..add(identifier)
- ..add(_parameters);
-
- @override
Token get endToken {
return question ?? _parameters?.endToken ?? identifier.endToken;
}
@@ -10010,6 +10364,16 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('type', type)
+ ..addToken('superKeyword', superKeyword)
+ ..addToken('period', period)
+ ..addNode('identifier', identifier)
+ ..addNode('typeParameters', typeParameters)
+ ..addNode('parameters', parameters);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitSuperFormalParameter(this);
@@ -10040,14 +10404,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..addAll(labels)
- ..add(keyword)
- ..add(_expression)
- ..add(colon)
- ..addAll(statements);
-
- @override
ExpressionImpl get expression => _expression;
set expression(Expression expression) {
@@ -10055,6 +10411,14 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNodeList('labels', labels)
+ ..addToken('keyword', keyword)
+ ..addNode('expression', expression)
+ ..addToken('colon', colon)
+ ..addNodeList('statements', statements);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchCase(this);
@override
@@ -10077,11 +10441,11 @@
: super(labels, keyword, colon, statements);
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..addAll(labels)
- ..add(keyword)
- ..add(colon)
- ..addAll(statements);
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNodeList('labels', labels)
+ ..addToken('keyword', keyword)
+ ..addToken('colon', colon)
+ ..addNodeList('statements', statements);
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchDefault(this);
@@ -10194,16 +10558,6 @@
Token get beginToken => switchKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(switchKeyword)
- ..add(leftParenthesis)
- ..add(_expression)
- ..add(rightParenthesis)
- ..add(leftBracket)
- ..addAll(_members)
- ..add(rightBracket);
-
- @override
Token get endToken => rightBracket;
@override
@@ -10217,6 +10571,16 @@
NodeListImpl<SwitchMember> get members => _members;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('switchKeyword', switchKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('expression', expression)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('members', members)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchStatement(this);
@override
@@ -10246,18 +10610,23 @@
Token get beginToken => poundSign;
@override
- // TODO(paulberry): add "." tokens.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(poundSign)
- ..addAll(components);
-
- @override
Token get endToken => components[components.length - 1];
@override
+ // TODO(paulberry): add "." tokens.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('poundSign', poundSign)
+ ..addTokenList('components', components);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitSymbolLiteral(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitSymbolLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -10279,19 +10648,24 @@
Token get beginToken => thisKeyword;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(thisKeyword);
-
- @override
Token get endToken => thisKeyword;
@override
Precedence get precedence => Precedence.primary;
@override
+ ChildEntities get _childEntities =>
+ ChildEntities()..addToken('thisKeyword', thisKeyword);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitThisExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitThisExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
@@ -10318,11 +10692,6 @@
Token get beginToken => throwKeyword;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(throwKeyword)
- ..add(_expression);
-
- @override
Token get endToken {
return _expression.endToken;
}
@@ -10338,9 +10707,19 @@
Precedence get precedence => Precedence.assignment;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('throwKeyword', throwKeyword)
+ ..addNode('expression', expression);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitThrowExpression(this);
@override
+ void resolveExpression(ResolverVisitor visitor, DartType? contextType) {
+ visitor.visitThrowExpression(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_expression.accept(visitor);
}
@@ -10377,11 +10756,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(_variableList)
- ..add(semicolon);
-
- @override
Element? get declaredElement => null;
@override
@@ -10399,6 +10773,11 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addNode('variables', variables)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitTopLevelVariableDeclaration(this);
@@ -10460,14 +10839,6 @@
NodeListImpl<CatchClause> get catchClauses => _catchClauses;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(tryKeyword)
- ..add(_body)
- ..addAll(_catchClauses)
- ..add(finallyKeyword)
- ..add(_finallyBlock);
-
- @override
Token get endToken {
if (_finallyBlock != null) {
return _finallyBlock!.endToken;
@@ -10487,6 +10858,14 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('tryKeyword', tryKeyword)
+ ..addNode('body', body)
+ ..addNodeList('catchClauses', catchClauses)
+ ..addToken('finallyKeyword', finallyKeyword)
+ ..addNode('finallyBlock', finallyBlock);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitTryStatement(this);
@override
@@ -10566,14 +10945,14 @@
Token get beginToken => leftBracket;
@override
- // TODO(paulberry): Add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftBracket)
- ..addAll(_arguments)
- ..add(rightBracket);
+ Token get endToken => rightBracket;
@override
- Token get endToken => rightBracket;
+ // TODO(paulberry): Add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('arguments', arguments)
+ ..addToken('rightBracket', rightBracket);
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeArgumentList(this);
@@ -10618,9 +10997,10 @@
_typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?);
}
+ @override
ChildEntities get _childEntities => ChildEntities()
- ..add(constKeyword)
- ..add(_typeArguments);
+ ..addToken('constKeyword', constKeyword)
+ ..addNode('typeArguments', typeArguments);
@override
void visitChildren(AstVisitor visitor) {
@@ -10650,10 +11030,6 @@
Token get beginToken => _typeName.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities =>
- ChildEntities()..add(_typeName);
-
- @override
Token get endToken => _typeName.endToken;
@override
@@ -10669,9 +11045,17 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()..addNode('type', type);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeLiteral(this);
@override
+ void resolveExpression(ResolverVisitor resolver, DartType? contextType) {
+ resolver.visitTypeLiteral(this, contextType: contextType);
+ }
+
+ @override
void visitChildren(AstVisitor visitor) {
_typeName.accept(visitor);
}
@@ -10719,12 +11103,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(_name)
- ..add(extendsKeyword)
- ..add(_bound);
-
- @override
TypeParameterElement? get declaredElement =>
_name.staticElement as TypeParameterElement?;
@@ -10747,6 +11125,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addNode('name', name)
+ ..addToken('extendsKeyword', extendsKeyword)
+ ..addNode('bound', bound);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeParameter(this);
@override
@@ -10783,18 +11167,18 @@
Token get beginToken => leftBracket;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(leftBracket)
- ..addAll(_typeParameters)
- ..add(rightBracket);
-
- @override
Token get endToken => rightBracket;
@override
NodeListImpl<TypeParameter> get typeParameters => _typeParameters;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('leftBracket', leftBracket)
+ ..addNodeList('typeParameters', typeParameters)
+ ..addToken('rightBracket', rightBracket);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeParameterList(this);
@override
@@ -10928,12 +11312,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(_name)
- ..add(equals)
- ..add(_initializer);
-
- @override
VariableElement? get declaredElement =>
_name.staticElement as VariableElement?;
@@ -10996,6 +11374,12 @@
}
@override
+ ChildEntities get _childEntities => super._childEntities
+ ..addNode('name', name)
+ ..addToken('equals', equals)
+ ..addNode('initializer', initializer);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitVariableDeclaration(this);
@override
@@ -11053,13 +11437,6 @@
}
@override
- // TODO(paulberry): include commas.
- Iterable<SyntacticEntity> get childEntities => super._childEntities
- ..add(keyword)
- ..add(_type)
- ..addAll(_variables);
-
- @override
Token get endToken => _variables.endToken!;
@override
@@ -11089,6 +11466,13 @@
NodeListImpl<VariableDeclaration> get variables => _variables;
@override
+ // TODO(paulberry): include commas.
+ ChildEntities get _childEntities => super._childEntities
+ ..addToken('keyword', keyword)
+ ..addNode('type', type)
+ ..addNodeList('variables', variables);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitVariableDeclarationList(this);
@@ -11123,11 +11507,6 @@
Token get beginToken => _variableList.beginToken;
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(_variableList)
- ..add(semicolon);
-
- @override
Token get endToken => semicolon;
@override
@@ -11138,6 +11517,11 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addNode('variables', variables)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitVariableDeclarationStatement(this);
@@ -11188,14 +11572,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(whileKeyword)
- ..add(leftParenthesis)
- ..add(_condition)
- ..add(rightParenthesis)
- ..add(_body);
-
- @override
ExpressionImpl get condition => _condition;
set condition(Expression expression) {
@@ -11206,6 +11582,14 @@
Token get endToken => _body.endToken;
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('whileKeyword', whileKeyword)
+ ..addToken('leftParenthesis', leftParenthesis)
+ ..addNode('condition', condition)
+ ..addToken('rightParenthesis', rightParenthesis)
+ ..addNode('body', body);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitWhileStatement(this);
@override
@@ -11236,18 +11620,22 @@
Token get beginToken => withKeyword;
@override
- // TODO(paulberry): add commas.
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(withKeyword)
- ..addAll(_mixinTypes);
-
- @override
Token get endToken => _mixinTypes.endToken!;
@override
+ NodeListImpl<NamedType> get mixinTypes => _mixinTypes;
+
+ @Deprecated('Use mixinTypes instead')
+ @override
NodeListImpl<NamedType> get mixinTypes2 => _mixinTypes;
@override
+ // TODO(paulberry): add commas.
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('withKeyword', withKeyword)
+ ..addNodeList('mixinTypes', mixinTypes);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitWithClause(this);
@override
@@ -11289,13 +11677,6 @@
}
@override
- Iterable<SyntacticEntity> get childEntities => ChildEntities()
- ..add(yieldKeyword)
- ..add(star)
- ..add(_expression)
- ..add(semicolon);
-
- @override
Token get endToken {
return semicolon;
}
@@ -11308,6 +11689,13 @@
}
@override
+ ChildEntities get _childEntities => ChildEntities()
+ ..addToken('yieldKeyword', yieldKeyword)
+ ..addToken('star', star)
+ ..addNode('expression', expression)
+ ..addToken('semicolon', semicolon);
+
+ @override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitYieldStatement(this);
@override
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 37cfef3..e427e92 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/ast_factory.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -156,6 +157,7 @@
List<Annotation>? metadata,
Token? abstractKeyword,
Token? macroKeyword,
+ Token? augmentKeyword,
Token classKeyword,
SimpleIdentifier name,
TypeParameterList? typeParameters,
@@ -170,6 +172,7 @@
metadata,
abstractKeyword,
macroKeyword,
+ augmentKeyword,
classKeyword,
name as SimpleIdentifierImpl,
typeParameters as TypeParameterListImpl?,
@@ -190,6 +193,7 @@
Token equals,
Token? abstractKeyword,
Token? macroKeyword,
+ Token? augmentKeyword,
NamedType superclass,
WithClause withClause,
ImplementsClause? implementsClause,
@@ -203,6 +207,7 @@
equals,
abstractKeyword,
macroKeyword,
+ augmentKeyword,
superclass as NamedTypeImpl,
withClause as WithClauseImpl,
implementsClause as ImplementsClauseImpl?,
@@ -221,9 +226,14 @@
List<Directive>? directives,
List<CompilationUnitMember>? declarations,
required Token endToken,
- required FeatureSet featureSet}) =>
+ required FeatureSet featureSet,
+ // TODO(dantup): LineInfo should be made required and non-nullable
+ // when breaking API changes can be made. Callers that do not
+ // provide lineInfos may have offsets incorrectly mapped to line/col
+ // for LSP.
+ LineInfo? lineInfo}) =>
CompilationUnitImpl(beginToken, scriptTag as ScriptTagImpl?, directives,
- declarations, endToken, featureSet);
+ declarations, endToken, featureSet, lineInfo ?? LineInfo([0]));
@override
ConditionalExpressionImpl conditionalExpression(
@@ -411,6 +421,7 @@
implementsClause: null,
leftBracket: leftBracket,
constants: constants,
+ semicolon: null,
members: [],
rightBracket: rightBracket);
@@ -426,6 +437,7 @@
required Token leftBracket,
required List<EnumConstantDeclaration> constants,
required List<ClassMember> members,
+ required Token? semicolon,
required Token rightBracket,
}) {
return EnumDeclarationImpl(
@@ -438,6 +450,7 @@
implementsClause as ImplementsClauseImpl?,
leftBracket,
constants,
+ semicolon,
members,
rightBracket,
);
@@ -532,6 +545,7 @@
{Comment? comment,
List<Annotation>? metadata,
Token? abstractKeyword,
+ Token? augmentKeyword,
Token? covariantKeyword,
Token? externalKeyword,
Token? staticKeyword,
@@ -541,6 +555,7 @@
comment as CommentImpl?,
metadata,
abstractKeyword,
+ augmentKeyword,
covariantKeyword,
externalKeyword,
staticKeyword,
@@ -666,6 +681,7 @@
FunctionDeclarationImpl functionDeclaration(
Comment? comment,
List<Annotation>? metadata,
+ Token? augmentKeyword,
Token? externalKeyword,
TypeAnnotation? returnType,
Token? propertyKeyword,
@@ -674,6 +690,7 @@
FunctionDeclarationImpl(
comment as CommentImpl?,
metadata,
+ augmentKeyword,
externalKeyword,
returnType as TypeAnnotationImpl?,
propertyKeyword,
@@ -859,11 +876,13 @@
Token? asKeyword,
SimpleIdentifier? prefix,
List<Combinator>? combinators,
- Token semicolon) =>
+ Token semicolon,
+ {Token? augmentKeyword}) =>
ImportDirectiveImpl(
comment as CommentImpl?,
metadata,
keyword,
+ augmentKeyword,
libraryUri as StringLiteralImpl,
configurations,
deferredKeyword,
@@ -1018,6 +1037,7 @@
MixinDeclarationImpl mixinDeclaration(
Comment? comment,
List<Annotation>? metadata,
+ Token? augmentKeyword,
Token mixinKeyword,
SimpleIdentifier name,
TypeParameterList? typeParameters,
@@ -1029,6 +1049,7 @@
MixinDeclarationImpl(
comment as CommentImpl?,
metadata,
+ augmentKeyword,
mixinKeyword,
name as SimpleIdentifierImpl,
typeParameters as TypeParameterListImpl?,
diff --git a/pkg/analyzer/lib/src/dart/ast/element_locator.dart b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
index 8159d3a..e0bfc35 100644
--- a/pkg/analyzer/lib/src/dart/ast/element_locator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
@@ -52,6 +52,18 @@
}
@override
+ Element? visitConstructorSelector(ConstructorSelector node) {
+ var parent = node.parent;
+ if (parent is EnumConstantArguments) {
+ var parent2 = parent.parent;
+ if (parent2 is EnumConstantDeclaration) {
+ return parent2.constructorElement;
+ }
+ }
+ return null;
+ }
+
+ @override
Element? visitExportDirective(ExportDirective node) {
return node.element;
}
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index d2c7f88..856da93 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -148,10 +148,11 @@
}
@override
- void visitClassDeclaration(ClassDeclaration node) {
+ void visitClassDeclaration(covariant ClassDeclarationImpl node) {
_visitNodeList(node.metadata, separator: ' ', suffix: ' ');
_visitToken(node.abstractKeyword, suffix: ' ');
_visitToken(node.macroKeyword, suffix: ' ');
+ _visitToken(node.augmentKeyword, suffix: ' ');
sink.write('class ');
_visitNode(node.name);
_visitNode(node.typeParameters);
@@ -164,17 +165,18 @@
}
@override
- void visitClassTypeAlias(ClassTypeAlias node) {
+ void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
_visitNodeList(node.metadata, separator: ' ', suffix: ' ');
if (node.abstractKeyword != null) {
sink.write('abstract ');
}
_visitToken(node.macroKeyword, suffix: ' ');
+ _visitToken(node.augmentKeyword, suffix: ' ');
sink.write('class ');
_visitNode(node.name);
_visitNode(node.typeParameters);
sink.write(' = ');
- _visitNode(node.superclass2);
+ _visitNode(node.superclass);
_visitNode(node.withClause, prefix: ' ');
_visitNode(node.implementsClause, prefix: ' ');
sink.write(';');
@@ -239,7 +241,7 @@
@override
void visitConstructorName(ConstructorName node) {
- _visitNode(node.type2);
+ _visitNode(node.type);
_visitNode(node.name, prefix: '.');
}
@@ -335,7 +337,8 @@
_visitNode(node.implementsClause, prefix: ' ');
sink.write(' {');
_visitNodeList(node.constants, separator: ', ');
- _visitNodeList(node.members, prefix: '; ', separator: ' ');
+ _visitToken(node.semicolon);
+ _visitNodeList(node.members, prefix: ' ', separator: ' ');
sink.write('}');
}
@@ -375,7 +378,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
sink.write('extends ');
- _visitNode(node.superclass2);
+ _visitNode(node.superclass);
}
@override
@@ -621,7 +624,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
sink.write('implements ');
- _visitNodeList(node.interfaces2, separator: ', ');
+ _visitNodeList(node.interfaces, separator: ', ');
}
@override
@@ -812,7 +815,7 @@
@override
void visitOnClause(OnClause node) {
sink.write('on ');
- _visitNodeList(node.superclassConstraints2, separator: ', ');
+ _visitNodeList(node.superclassConstraints, separator: ', ');
}
@override
@@ -1112,7 +1115,7 @@
@override
void visitWithClause(WithClause node) {
sink.write('with ');
- _visitNodeList(node.mixinTypes2, separator: ', ');
+ _visitNodeList(node.mixinTypes, separator: ', ');
}
@override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 1aca07f..dd78df6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -255,7 +255,7 @@
isEqualNodes(node.typeParameters, other.typeParameters) &&
isEqualTokens(node.equals, other.equals) &&
isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
- isEqualNodes(node.superclass2, other.superclass2) &&
+ isEqualNodes(node.superclass, other.superclass) &&
isEqualNodes(node.withClause, other.withClause) &&
isEqualNodes(node.implementsClause, other.implementsClause) &&
isEqualTokens(node.semicolon, other.semicolon);
@@ -338,7 +338,7 @@
@override
bool visitConstructorName(ConstructorName node) {
ConstructorName other = _other as ConstructorName;
- return isEqualNodes(node.type2, other.type2) &&
+ return isEqualNodes(node.type, other.type) &&
isEqualTokens(node.period, other.period) &&
isEqualNodes(node.name, other.name);
}
@@ -482,7 +482,7 @@
bool visitExtendsClause(ExtendsClause node) {
ExtendsClause other = _other as ExtendsClause;
return isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
- isEqualNodes(node.superclass2, other.superclass2);
+ isEqualNodes(node.superclass, other.superclass);
}
@override
@@ -733,7 +733,7 @@
bool visitImplementsClause(ImplementsClause node) {
ImplementsClause other = _other as ImplementsClause;
return isEqualTokens(node.implementsKeyword, other.implementsKeyword) &&
- _isEqualNodeLists(node.interfaces2, other.interfaces2);
+ _isEqualNodeLists(node.interfaces, other.interfaces);
}
@override
@@ -938,7 +938,7 @@
OnClause other = _other as OnClause;
return isEqualTokens(node.onKeyword, other.onKeyword) &&
_isEqualNodeLists(
- node.superclassConstraints2, other.superclassConstraints2);
+ node.superclassConstraints, other.superclassConstraints);
}
@override
@@ -1281,7 +1281,7 @@
bool visitWithClause(WithClause node) {
WithClause other = _other as WithClause;
return isEqualTokens(node.withKeyword, other.withKeyword) &&
- _isEqualNodeLists(node.mixinTypes2, other.mixinTypes2);
+ _isEqualNodeLists(node.mixinTypes, other.mixinTypes);
}
@override
@@ -1797,7 +1797,7 @@
} else if (identical(node.typeParameters, _oldNode)) {
node.typeParameters = _newNode as TypeParameterList;
return true;
- } else if (identical(node.superclass2, _oldNode)) {
+ } else if (identical(node.superclass, _oldNode)) {
node.superclass = _newNode as NamedType;
return true;
} else if (identical(node.withClause, _oldNode)) {
@@ -1908,7 +1908,7 @@
@override
bool visitConstructorName(covariant ConstructorNameImpl node) {
- if (identical(node.type2, _oldNode)) {
+ if (identical(node.type, _oldNode)) {
node.type = _newNode as NamedType;
return true;
} else if (identical(node.name, _oldNode)) {
@@ -2061,7 +2061,7 @@
@override
bool visitExtendsClause(covariant ExtendsClauseImpl node) {
- if (identical(node.superclass2, _oldNode)) {
+ if (identical(node.superclass, _oldNode)) {
node.superclass = _newNode as NamedType;
return true;
}
@@ -2402,7 +2402,7 @@
@override
bool visitImplementsClause(covariant ImplementsClauseImpl node) {
- if (_replaceInList(node.interfaces2)) {
+ if (_replaceInList(node.interfaces)) {
return true;
}
return visitNode(node);
@@ -2674,7 +2674,7 @@
@override
bool visitOnClause(covariant OnClauseImpl node) {
- if (_replaceInList(node.superclassConstraints2)) {
+ if (_replaceInList(node.superclassConstraints)) {
return true;
}
return visitNode(node);
@@ -3046,7 +3046,7 @@
@override
bool visitWithClause(covariant WithClauseImpl node) {
- if (_replaceInList(node.mixinTypes2)) {
+ if (_replaceInList(node.mixinTypes)) {
return true;
}
return visitNode(node);
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 9af29c4..d51f9d9 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -103,7 +103,11 @@
if (constKeyword != null) {
_validateConstructorInitializers(node);
if (node.factoryKeyword == null) {
- _validateFieldInitializers(node.parent.classMembers, constKeyword);
+ _validateFieldInitializers(
+ node.parent.classMembers,
+ constKeyword,
+ isEnumDeclaration: node.parent is EnumDeclaration,
+ );
}
}
_validateDefaultValues(node.parameters);
@@ -114,12 +118,28 @@
void visitConstructorReference(ConstructorReference node) {
super.visitConstructorReference(node);
if (node.inConstantContext || node.inConstantExpression) {
- _checkForConstWithTypeParameters(node.constructorName.type2,
+ _checkForConstWithTypeParameters(node.constructorName.type,
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF);
}
}
@override
+ visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ super.visitEnumConstantDeclaration(node);
+
+ var argumentList = node.arguments?.argumentList;
+ if (argumentList != null) {
+ _validateConstantArguments(argumentList);
+ }
+
+ var element = node.declaredElement as ConstFieldElementImpl;
+ var result = element.evaluationResult;
+ if (result != null) {
+ _reportErrors(result.errors, null);
+ }
+ }
+
+ @override
void visitFunctionExpression(FunctionExpression node) {
super.visitFunctionExpression(node);
_validateDefaultValues(node.parameters);
@@ -155,7 +175,7 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
if (node.isConst) {
- NamedType namedType = node.constructorName.type2;
+ NamedType namedType = node.constructorName.type;
_checkForConstWithTypeParameters(
namedType, CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS);
@@ -548,11 +568,17 @@
/// required if the class has a constant constructor, the error is reported at
/// [constKeyword], the const keyword on such a constant constructor.
void _validateFieldInitializers(
- List<ClassMember> members, Token constKeyword) {
+ List<ClassMember> members,
+ Token constKeyword, {
+ required bool isEnumDeclaration,
+ }) {
for (ClassMember member in members) {
if (member is FieldDeclaration && !member.isStatic) {
for (VariableDeclaration variableDeclaration
in member.fields.variables) {
+ if (isEnumDeclaration && variableDeclaration.name.name == 'values') {
+ continue;
+ }
var initializer = variableDeclaration.initializer;
if (initializer != null) {
// Ignore any errors produced during validation--if the constant
@@ -603,7 +629,7 @@
.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
);
- var expressionValueType = _typeSystem.toLegacyType(
+ var expressionValueType = _typeSystem.toLegacyTypeIfOptOut(
expressionValue.type,
);
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 72131f5..ba68d5e 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -28,6 +28,12 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/task/api/model.dart';
+/// During evaluation of enum constants we might need to report an error
+/// that is associated with the [InstanceCreationExpression], but this
+/// expression is synthetic. Instead, we remember the corresponding
+/// [EnumConstantDeclaration] and report the error on it.
+final enumConstantErrorNodes = Expando<EnumConstantDeclaration>();
+
/// Helper class encapsulating the methods for evaluating constants and
/// constant instance creation expressions.
class ConstantEvaluationEngine {
@@ -187,6 +193,18 @@
/// [callback].
void computeDependencies(
ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
+ if (constant is ConstFieldElementImpl && constant.isEnumConstant) {
+ var enclosing = constant.enclosingElement;
+ if (enclosing is EnumElementImpl) {
+ if (enclosing.name == 'values') {
+ return;
+ }
+ if (constant.name == enclosing.name) {
+ return;
+ }
+ }
+ }
+
ReferenceFinder referenceFinder = ReferenceFinder(callback);
if (constant is ConstructorElement) {
constant = constant.declaration;
@@ -662,7 +680,7 @@
// The result is already instantiated during resolution;
// [_dartObjectComputer.typeInstantiate] is unnecessary.
var typeElement =
- node.constructorName.type2.name.staticElement as TypeDefiningElement;
+ node.constructorName.type.name.staticElement as TypeDefiningElement;
TypeAliasElement? viaTypeAlias;
if (typeElement is TypeAliasElementImpl) {
@@ -2541,7 +2559,7 @@
declaredVariables,
errorReporter,
library,
- node,
+ enumConstantErrorNodes[node] ?? node,
constructor,
typeArguments,
namedNodes: namedNodes,
@@ -2605,7 +2623,7 @@
DartType type,
) {
if (!isNonNullableByDefault) {
- type = toLegacyType(type);
+ type = toLegacyTypeIfOptOut(type);
}
var objType = obj.type;
return isSubtypeOf(objType, type);
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
index ae554f5..66503bc 100644
--- a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -188,7 +188,7 @@
}
if (node is ConstructorReference) {
- _typeArgumentList(node.constructorName.type2.typeArguments);
+ _typeArgumentList(node.constructorName.type.typeArguments);
return;
}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 62f7b47..38b14dc 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/element/element.dart';
/// Callback used by [ReferenceFinder] to report that a dependency was found.
typedef ReferenceFinderCallback = void Function(
@@ -141,6 +142,17 @@
}
@override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ super.visitEnumConstantDeclaration(node);
+
+ var element = node.declaredElement as ConstFieldElementImpl;
+ constantsToCompute.add(element);
+
+ var constantInitializer = element.constantInitializer!;
+ enumConstantErrorNodes[constantInitializer] = node;
+ }
+
+ @override
void visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
var initializer = node.initializer;
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index ef76c24..06b9e06 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -167,16 +167,14 @@
TypeSystemImpl typeSystem,
DartType type,
) {
- if (type.element!.library!.isDartCore) {
- if (type.isDartCoreBool) {
- return DartObjectImpl(typeSystem, type, BoolState.UNKNOWN_VALUE);
- } else if (type.isDartCoreDouble) {
- return DartObjectImpl(typeSystem, type, DoubleState.UNKNOWN_VALUE);
- } else if (type.isDartCoreInt) {
- return DartObjectImpl(typeSystem, type, IntState.UNKNOWN_VALUE);
- } else if (type.isDartCoreString) {
- return DartObjectImpl(typeSystem, type, StringState.UNKNOWN_VALUE);
- }
+ if (type.isDartCoreBool) {
+ return DartObjectImpl(typeSystem, type, BoolState.UNKNOWN_VALUE);
+ } else if (type.isDartCoreDouble) {
+ return DartObjectImpl(typeSystem, type, DoubleState.UNKNOWN_VALUE);
+ } else if (type.isDartCoreInt) {
+ return DartObjectImpl(typeSystem, type, IntState.UNKNOWN_VALUE);
+ } else if (type.isDartCoreString) {
+ return DartObjectImpl(typeSystem, type, StringState.UNKNOWN_VALUE);
}
return DartObjectImpl(typeSystem, type, GenericState.UNKNOWN_VALUE);
}
diff --git a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
index 0a44e08..1a8a0ca 100644
--- a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
+++ b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
@@ -183,7 +183,7 @@
);
}
} else {
- var legacyType = _typeSystem.toLegacyType(type) as InterfaceType;
+ var legacyType = _typeSystem.toLegacyTypeIfOptOut(type) as InterfaceType;
if (_currentResult == null) {
_currentResult = legacyType;
} else {
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index 2e58795..77422fc 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -74,6 +74,8 @@
_write('enum ');
_write(element.displayName);
_writeTypeParameters(element.typeParameters);
+ _writeTypesIfNotEmpty(' with ', element.mixins);
+ _writeTypesIfNotEmpty(' implements ', element.interfaces);
}
void writeExecutableElement(ExecutableElement element, String name) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index b79c1a0..060903e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -46,8 +46,19 @@
/// A concrete implementation of a [ClassElement].
abstract class AbstractClassElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements ClassElement {
+ /// The superclass of the class, or `null` for [Object].
+ InterfaceType? _supertype;
+
+ /// A list containing all of the mixins that are applied to the class being
+ /// extended in order to derive the superclass of this class.
+ List<InterfaceType> _mixins = const [];
+
+ /// A list containing all of the interfaces that are implemented by this
+ /// class.
+ List<InterfaceType> _interfaces = const [];
+
/// The type defined by the class.
InterfaceType? _thisType;
@@ -61,6 +72,10 @@
/// A list containing all of the methods contained in this class.
List<MethodElement> _methods = _Sentinel.methodElement;
+ /// This callback is set during mixins inference to handle reentrant calls.
+ List<InterfaceType>? Function(AbstractClassElementImpl)?
+ mixinInferenceCallback;
+
/// Initialize a newly created class element to have the given [name] at the
/// given [offset] in the file that contains the declaration of this element.
AbstractClassElementImpl(String name, int offset) : super(name, offset);
@@ -75,6 +90,12 @@
}
@override
+ List<InterfaceType> get allSupertypes {
+ var sessionImpl = library.session as AnalysisSessionImpl;
+ return sessionImpl.classHierarchy.implementedInterfaces(this);
+ }
+
+ @override
String get displayName => name;
@override
@@ -92,6 +113,23 @@
}
@override
+ List<InterfaceType> get interfaces =>
+ ElementTypeProvider.current.getClassInterfaces(this);
+
+ set interfaces(List<InterfaceType> interfaces) {
+ _interfaces = interfaces;
+ }
+
+ List<InterfaceType> get interfacesInternal {
+ return _interfaces;
+ }
+
+ @override
+ bool get isDartCoreEnum {
+ return name == 'Enum' && library.isDartCore;
+ }
+
+ @override
bool get isDartCoreObject => false;
@override
@@ -101,9 +139,40 @@
bool get isMixin => false;
@override
+ List<InterfaceType> get mixins {
+ if (mixinInferenceCallback != null) {
+ var mixins = mixinInferenceCallback!(this);
+ if (mixins != null) {
+ return _mixins = mixins;
+ }
+ }
+
+ return _mixins;
+ }
+
+ set mixins(List<InterfaceType> mixins) {
+ _mixins = mixins;
+ }
+
+ @override
List<InterfaceType> get superclassConstraints => const <InterfaceType>[];
@override
+ InterfaceType? get supertype {
+ if (_supertype != null) return _supertype!;
+
+ if (hasModifier(Modifier.DART_CORE_OBJECT)) {
+ return null;
+ }
+
+ return _supertype;
+ }
+
+ set supertype(InterfaceType? supertype) {
+ _supertype = supertype;
+ }
+
+ @override
InterfaceType get thisType {
if (_thisType == null) {
List<DartType> typeArguments;
@@ -200,11 +269,6 @@
required List<DartType> typeArguments,
required NullabilitySuffix nullabilitySuffix,
}) {
- if (typeArguments.length != typeParameters.length) {
- var ta = 'typeArguments.length (${typeArguments.length})';
- var tp = 'typeParameters.length (${typeParameters.length})';
- throw ArgumentError('$ta != $tp');
- }
return InterfaceTypeImpl(
element: this,
typeArguments: typeArguments,
@@ -325,6 +389,9 @@
super.visitChildren(visitor);
safelyVisitChildren(accessors, visitor);
safelyVisitChildren(fields, visitor);
+ safelyVisitChildren(constructors, visitor);
+ safelyVisitChildren(methods, visitor);
+ safelyVisitChildren(typeParameters, visitor);
}
/// Return an iterable containing all of the implementations of a getter with
@@ -444,17 +511,6 @@
/// An [AbstractClassElementImpl] which is a class.
class ClassElementImpl extends AbstractClassElementImpl {
- /// The superclass of the class, or `null` for [Object].
- InterfaceType? _supertype;
-
- /// A list containing all of the mixins that are applied to the class being
- /// extended in order to derive the superclass of this class.
- List<InterfaceType> _mixins = const [];
-
- /// A list containing all of the interfaces that are implemented by this
- /// class.
- List<InterfaceType> _interfaces = const [];
-
/// For classes which are not mixin applications, a list containing all of the
/// constructors contained in this class, or `null` if the list of
/// constructors has not yet been built.
@@ -468,9 +524,6 @@
/// of this class have been inferred.
bool hasBeenInferred = false;
- /// This callback is set during mixins inference to handle reentrant calls.
- List<InterfaceType>? Function(ClassElementImpl)? mixinInferenceCallback;
-
ElementLinkedData? linkedData;
/// Initialize a newly created class element to have the given [name] at the
@@ -493,12 +546,6 @@
}
@override
- List<InterfaceType> get allSupertypes {
- var sessionImpl = library.session as AnalysisSessionImpl;
- return sessionImpl.classHierarchy.implementedInterfaces(this);
- }
-
- @override
List<ConstructorElement> get constructors {
if (!identical(_constructors, _Sentinel.constructorElement)) {
return _constructors;
@@ -611,13 +658,6 @@
}
@override
- List<InterfaceType> get interfaces =>
- ElementTypeProvider.current.getClassInterfaces(this);
-
- set interfaces(List<InterfaceType> interfaces) {
- _interfaces = interfaces;
- }
-
List<InterfaceType> get interfacesInternal {
linkedData?.read(this);
return _interfaces;
@@ -740,19 +780,8 @@
@override
List<InterfaceType> get mixins {
- if (mixinInferenceCallback != null) {
- var mixins = mixinInferenceCallback!(this);
- if (mixins != null) {
- return _mixins = mixins;
- }
- }
-
linkedData?.read(this);
- return _mixins;
- }
-
- set mixins(List<InterfaceType> mixins) {
- _mixins = mixins;
+ return super.mixins;
}
@override
@@ -768,17 +797,7 @@
@override
InterfaceType? get supertype {
linkedData?.read(this);
- if (_supertype != null) return _supertype!;
-
- if (hasModifier(Modifier.DART_CORE_OBJECT)) {
- return null;
- }
-
- return _supertype;
- }
-
- set supertype(InterfaceType? supertype) {
- _supertype = supertype;
+ return super.supertype;
}
@override
@@ -799,14 +818,6 @@
this.linkedData = linkedData;
}
- @override
- void visitChildren(ElementVisitor visitor) {
- super.visitChildren(visitor);
- safelyVisitChildren(constructors, visitor);
- safelyVisitChildren(methods, visitor);
- safelyVisitChildren(typeParameters, visitor);
- }
-
/// Compute a list of constructors for this class, which is a mixin
/// application. If specified, [visitedClasses] is a list of the other mixin
/// application classes which have been visited on the way to reaching this
@@ -1349,9 +1360,6 @@
}
@override
- bool get isStatic => false;
-
- @override
ElementKind get kind => ElementKind.CONSTRUCTOR;
@override
@@ -1457,6 +1465,11 @@
// OK, can be used as default constructor
return true;
}
+
+ @override
+ bool get isGenerative {
+ return !isFactory;
+ }
}
/// A [TopLevelVariableElement] for a top-level 'const' variable that has an
@@ -2675,10 +2688,6 @@
return _accessors;
}
- @override
- List<InterfaceType> get allSupertypes =>
- <InterfaceType>[...interfaces, supertype];
-
List<FieldElement> get constants {
return fields.where((field) => field.isEnumConstant).toList();
}
@@ -2707,9 +2716,6 @@
bool get hasStaticMember => true;
@override
- List<InterfaceType> get interfaces => const [];
-
- @override
bool get isAbstract => false;
@override
@@ -2753,17 +2759,14 @@
}
@override
- List<InterfaceType> get mixins => const <InterfaceType>[];
-
- @override
String get name {
return super.name!;
}
@override
- InterfaceType get supertype {
- var enumType = library.typeProvider.enumType;
- return enumType ?? library.typeProvider.objectType;
+ InterfaceType? get supertype {
+ linkedData?.read(this);
+ return super.supertype;
}
@override
@@ -2772,6 +2775,17 @@
return super.typeParameters;
}
+ ConstFieldElementImpl? get valuesField {
+ for (var field in fields) {
+ if (field is ConstFieldElementImpl &&
+ field.name == 'values' &&
+ field.isSyntheticEnumField) {
+ return field;
+ }
+ }
+ return null;
+ }
+
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeEnumElement(this);
@@ -2787,7 +2801,7 @@
/// A base class for concrete implementations of an [ExecutableElement].
abstract class ExecutableElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements ExecutableElement, ElementImplWithFunctionType {
/// A list containing all of the parameters defined by this executable
/// element.
@@ -2858,6 +2872,15 @@
bool get isOperator => false;
@override
+ bool get isStatic {
+ return hasModifier(Modifier.STATIC);
+ }
+
+ set isStatic(bool isStatic) {
+ setModifier(Modifier.STATIC, isStatic);
+ }
+
+ @override
bool get isSynchronous => !isAsynchronous;
@override
@@ -3002,7 +3025,7 @@
/// A concrete implementation of an [ExtensionElement].
class ExtensionElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements ExtensionElement {
/// The type being extended.
DartType? _extendedType;
@@ -3128,6 +3151,16 @@
}
@override
+ FieldElement? getField(String name) {
+ for (FieldElement fieldElement in fields) {
+ if (name == fieldElement.name) {
+ return fieldElement;
+ }
+ }
+ return null;
+ }
+
+ @override
PropertyAccessorElement? getGetter(String getterName) {
int length = accessors.length;
for (int i = 0; i < length; i++) {
@@ -3176,6 +3209,7 @@
/// A concrete implementation of a [FieldElement].
class FieldElementImpl extends PropertyInducingElementImpl
+ with HasCompletionData
implements FieldElement {
/// True if this field inherits from a covariant parameter. This happens
/// when it overrides a field in a supertype that is covariant.
@@ -3217,16 +3251,6 @@
return hasModifier(Modifier.EXTERNAL);
}
- @override
- bool get isStatic {
- return hasModifier(Modifier.STATIC);
- }
-
- /// Set whether this field is static.
- set isStatic(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
- }
-
/// Return `true` if this element is a synthetic enum field.
///
/// It is synthetic because it is not written explicitly in code, but it
@@ -3320,9 +3344,6 @@
}
@override
- bool get isStatic => enclosingElement is CompilationUnitElement;
-
- @override
ElementKind get kind => ElementKind.FUNCTION;
@override
@@ -3448,6 +3469,11 @@
}
}
+/// This mixins is added to elements that can have cache completion data.
+mixin HasCompletionData {
+ Object? completionData;
+}
+
/// A concrete implementation of a [HideElementCombinator].
class HideElementCombinatorImpl implements HideElementCombinator {
@override
@@ -4171,16 +4197,6 @@
}
@override
- bool get isStatic {
- return hasModifier(Modifier.STATIC);
- }
-
- /// Set whether this method is static.
- set isStatic(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
- }
-
- @override
ElementKind get kind => ElementKind.METHOD;
@override
@@ -5010,16 +5026,6 @@
}
@override
- bool get isStatic {
- return hasModifier(Modifier.STATIC);
- }
-
- /// Set whether this accessor is static.
- set isStatic(bool isStatic) {
- setModifier(Modifier.STATIC, isStatic);
- }
-
- @override
ElementKind get kind {
if (isGetter) {
return ElementKind.GETTER;
@@ -5077,12 +5083,12 @@
@override
Element get nonSynthetic {
- if (enclosingElement is EnumElementImpl) {
- if (name == 'index' || name == 'values') {
- return enclosingElement;
- }
+ final variable = this.variable;
+ if (!variable.isSynthetic) {
+ return variable;
}
- return variable;
+ assert(enclosingElement is EnumElementImpl);
+ return enclosingElement;
}
@override
@@ -5227,6 +5233,7 @@
Element get nonSynthetic {
if (isSynthetic) {
if (enclosingElement is EnumElementImpl) {
+ // TODO(scheglov) remove 'index'?
if (name == 'index' || name == 'values') {
return enclosingElement;
}
@@ -5409,6 +5416,7 @@
/// A concrete implementation of a [TopLevelVariableElement].
class TopLevelVariableElementImpl extends PropertyInducingElementImpl
+ with HasCompletionData
implements TopLevelVariableElement {
/// Initialize a newly created synthetic top-level variable element to have
/// the given [name] and [offset].
@@ -5443,7 +5451,7 @@
///
/// Clients may not extend, implement or mix-in this class.
class TypeAliasElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements TypeAliasElement {
/// Is `true` if the element has direct or indirect reference to itself
/// from anywhere except a class element or type parameter bounds.
@@ -5892,6 +5900,10 @@
@override
bool get isStatic => hasModifier(Modifier.STATIC);
+ set isStatic(bool isStatic) {
+ setModifier(Modifier.STATIC, isStatic);
+ }
+
@override
String get name => super.name!;
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index 06fb704..f4077d4 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -551,10 +551,10 @@
return;
}
if (errorNode is ConstructorName &&
- !(errorNode.type2.type as InterfaceType).element.hasOptionalTypeArgs) {
+ !(errorNode.type.type as InterfaceType).element.hasOptionalTypeArgs) {
String constructorName = errorNode.name == null
- ? errorNode.type2.name.name
- : '${errorNode.type2}.${errorNode.name}';
+ ? errorNode.type.name.name
+ : '${errorNode.type}.${errorNode.name}';
errorReporter.reportErrorForNode(
HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
errorNode,
diff --git a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
index fdabfea..92fc5ba 100644
--- a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
@@ -273,18 +273,13 @@
// The bounds of type parameters must be equal.
// Otherwise the result is `Never`.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
- if (freshTypeFormalTypes == null) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return NeverTypeImpl.instance;
}
- var typeFormals = freshTypeFormalTypes
- .map<TypeParameterElement>((t) => t.element)
- .toList();
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
var fParameters = f.parameters;
var gParameters = g.parameters;
@@ -379,7 +374,7 @@
var returnType = getGreatestLowerBound(f.returnType, g.returnType);
return FunctionTypeImpl(
- typeFormals: typeFormals,
+ typeFormals: fresh.typeParameters,
parameters: parameters,
returnType: returnType,
nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index df0e9e2..c675895 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -248,7 +248,7 @@
return result;
} else {
return result.map((e) {
- return e.mapArguments(typeSystem.toLegacyType);
+ return e.mapArguments(typeSystem.toLegacyTypeIfOptOut);
}).toSet();
}
}
@@ -723,18 +723,13 @@
// The bounds of type parameters must be equal.
// Otherwise the result is `Function`.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
- if (freshTypeFormalTypes == null) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return _interfaceTypeFunctionNone;
}
- var typeFormals = freshTypeFormalTypes
- .map<TypeParameterElement>((t) => t.element)
- .toList();
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
var fParameters = f.parameters;
var gParameters = g.parameters;
@@ -822,7 +817,7 @@
var returnType = getLeastUpperBound(f.returnType, g.returnType);
return FunctionTypeImpl(
- typeFormals: typeFormals,
+ typeFormals: fresh.typeParameters,
parameters: parameters,
returnType: returnType,
nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/subtype.dart b/pkg/analyzer/lib/src/dart/element/subtype.dart
index 4c8850c..9ff6e69 100644
--- a/pkg/analyzer/lib/src/dart/element/subtype.dart
+++ b/pkg/analyzer/lib/src/dart/element/subtype.dart
@@ -20,16 +20,17 @@
/// https://github.com/dart-lang/language
/// See `resources/type-system/subtyping.md`
class SubtypeHelper {
+ final TypeSystemImpl _typeSystem;
final TypeProviderImpl _typeProvider;
final InterfaceTypeImpl _nullNone;
final InterfaceTypeImpl _objectNone;
final InterfaceTypeImpl _objectQuestion;
- SubtypeHelper(TypeSystemImpl typeSystem)
- : _typeProvider = typeSystem.typeProvider,
- _nullNone = typeSystem.nullNone,
- _objectNone = typeSystem.objectNone,
- _objectQuestion = typeSystem.objectQuestion;
+ SubtypeHelper(this._typeSystem)
+ : _typeProvider = _typeSystem.typeProvider,
+ _nullNone = _typeSystem.nullNone,
+ _objectNone = _typeSystem.objectNone,
+ _objectQuestion = _typeSystem.objectQuestion;
/// Return `true` if [T0_] is a subtype of [T1_].
bool isSubtypeOf(DartType T0_, DartType T1_) {
@@ -342,25 +343,13 @@
/// Check that [f] is a subtype of [g].
bool _isFunctionSubtypeOf(FunctionType f, FunctionType g) {
- var fTypeFormals = f.typeFormals;
- var gTypeFormals = g.typeFormals;
-
- // The number of type parameters must be the same.
- if (fTypeFormals.length != gTypeFormals.length) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return false;
}
- // The bounds of type parameters must be equal.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) {
- return isSubtypeOf(t, s) && isSubtypeOf(s, t);
- });
- if (freshTypeFormalTypes == null) {
- return false;
- }
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
if (!isSubtypeOf(f.returnType, g.returnType)) {
return false;
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 70f398c..92ac1d9 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -180,8 +180,8 @@
// To test this, we instantiate both types with the same (unique) type
// variables, and see if the result is equal.
if (typeFormals.isNotEmpty) {
- var freshVariables = FunctionTypeImpl.relateTypeFormals(
- this, other, (t, s, _, __) => t == s);
+ var freshVariables =
+ FunctionTypeImpl.relateTypeFormals(this, other, (t, s) => t == s);
if (freshVariables == null) {
return false;
}
@@ -295,9 +295,7 @@
static List<TypeParameterType>? relateTypeFormals(
FunctionType f1,
FunctionType f2,
- bool Function(DartType bound2, DartType bound1,
- TypeParameterElement formal2, TypeParameterElement formal1)
- relation) {
+ bool Function(DartType bound2, DartType bound1) relation) {
List<TypeParameterElement> params1 = f1.typeFormals;
List<TypeParameterElement> params2 = f2.typeFormals;
return relateTypeFormals2(params1, params2, relation);
@@ -306,9 +304,7 @@
static List<TypeParameterType>? relateTypeFormals2(
List<TypeParameterElement> params1,
List<TypeParameterElement> params2,
- bool Function(DartType bound2, DartType bound1,
- TypeParameterElement formal2, TypeParameterElement formal1)
- relation) {
+ bool Function(DartType bound2, DartType bound1) relation) {
int count = params1.length;
if (params2.length != count) {
return null;
@@ -340,7 +336,7 @@
.substituteType(bound1);
bound2 = Substitution.fromPairs(variables2, variablesFresh)
.substituteType(bound2);
- if (!relation(bound2, bound1, p2, p1)) {
+ if (!relation(bound2, bound1)) {
return null;
}
@@ -454,10 +450,19 @@
required this.typeArguments,
required this.nullabilitySuffix,
InstantiatedTypeAliasElement? alias,
- }) : super(
- element,
- alias: alias,
- );
+ }) : super(element, alias: alias) {
+ var typeParameters = element.typeParameters;
+ if (typeArguments.length != typeParameters.length) {
+ throw ArgumentError(
+ '[typeParameters.length: ${typeParameters.length}]'
+ '[typeArguments.length: ${typeArguments.length}]'
+ '[element: $element]'
+ '[reference: ${element is ClassElementImpl ? element.reference : null}]'
+ '[typeParameters: $typeParameters]'
+ '[typeArguments: $typeArguments]',
+ );
+ }
+ }
@override
List<PropertyAccessorElement> get accessors {
@@ -532,6 +537,11 @@
}
@override
+ bool get isDartCoreEnum {
+ return element.isDartCoreEnum;
+ }
+
+ @override
bool get isDartCoreFunction {
return element.name == "Function" && element.library.isDartCore;
}
@@ -988,6 +998,9 @@
bool get isDartCoreDouble => false;
@override
+ bool get isDartCoreEnum => false;
+
+ @override
bool get isDartCoreFunction => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index b38a654..9097f205 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -30,6 +30,20 @@
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
+import 'package:analyzer/src/dart/element/well_bounded.dart';
+
+/// Fresh type parameters created to unify two lists of type parameters.
+class RelatedTypeParameters {
+ static final _empty = RelatedTypeParameters._([], []);
+
+ final List<TypeParameterElement> typeParameters;
+ final List<TypeParameterType> typeParameterTypes;
+
+ RelatedTypeParameters._(
+ this.typeParameters,
+ this.typeParameterTypes,
+ );
+}
/// The [TypeSystem] implementation.
class TypeSystemImpl implements TypeSystem {
@@ -543,7 +557,7 @@
typeArguments: typeArguments,
nullabilitySuffix: nullabilitySuffix,
);
- type = toLegacyType(type) as InterfaceType;
+ type = toLegacyTypeIfOptOut(type) as InterfaceType;
return type;
} else if (typeAliasElement != null) {
var typeParameters = typeAliasElement.typeParameters;
@@ -552,7 +566,7 @@
typeArguments: typeArguments,
nullabilitySuffix: nullabilitySuffix,
);
- type = toLegacyType(type);
+ type = toLegacyTypeIfOptOut(type);
return type;
} else {
throw ArgumentError('Missing element');
@@ -802,6 +816,15 @@
return false;
}
+ /// Check if [left] is equal to [right].
+ ///
+ /// Implements:
+ /// https://github.com/dart-lang/language
+ /// See `resources/type-system/subtyping.md#type-equality`
+ bool isEqualTo(DartType left, DartType right) {
+ return isSubtypeOf(left, right) && isSubtypeOf(right, left);
+ }
+
/// A function bounded type is either `Function` itself, or a type variable
/// whose bound is function bounded, or an intersection (promoted type
/// parameter type) whose second operand is function bounded.
@@ -1178,6 +1201,17 @@
return false;
}
+ /// See `15.2 Super-bounded types` in the language specification.
+ TypeBoundedResult isWellBounded(
+ DartType type, {
+ required bool allowSuperBounded,
+ }) {
+ return TypeBoundedHelper(this).isWellBounded(
+ type,
+ allowSuperBounded: allowSuperBounded,
+ );
+ }
+
/// Returns the least closure of [type] with respect to [typeParameters].
///
/// https://github.com/dart-lang/language
@@ -1283,8 +1317,8 @@
// TODO(scheglov) waiting for the spec
// https://github.com/dart-lang/sdk/issues/42605
} else {
- srcType = toLegacyType(srcType);
- destType = toLegacyType(destType);
+ srcType = toLegacyTypeIfOptOut(srcType);
+ destType = toLegacyTypeIfOptOut(destType);
}
if (srcType != destType) {
// Failed to find an appropriate substitution
@@ -1411,6 +1445,72 @@
}
}
+ /// Given two lists of type parameters, check that that they have the same
+ /// number of elements, and their bounds are equal.
+ ///
+ /// The return value will be a new list of fresh type parameters, that can
+ /// be used to instantiate both function types, allowing further comparison.
+ RelatedTypeParameters? relateTypeParameters(
+ List<TypeParameterElement> typeParameters1,
+ List<TypeParameterElement> typeParameters2,
+ ) {
+ if (typeParameters1.length != typeParameters2.length) {
+ return null;
+ }
+ if (typeParameters1.isEmpty) {
+ return RelatedTypeParameters._empty;
+ }
+
+ var freshTypeParameters = <TypeParameterElementImpl>[];
+ var freshTypeParameterTypes = <TypeParameterType>[];
+ for (var i = 0; i < typeParameters1.length; i++) {
+ var freshTypeParameter = TypeParameterElementImpl(
+ typeParameters1[i].name,
+ -1,
+ );
+ freshTypeParameters.add(freshTypeParameter);
+ freshTypeParameterTypes.add(
+ TypeParameterTypeImpl(
+ element: freshTypeParameter,
+ nullabilitySuffix: NullabilitySuffix.none,
+ ),
+ );
+ }
+
+ var substitution1 = Substitution.fromPairs(
+ typeParameters1,
+ freshTypeParameterTypes,
+ );
+ var substitution2 = Substitution.fromPairs(
+ typeParameters2,
+ freshTypeParameterTypes,
+ );
+
+ for (var i = 0; i < typeParameters1.length; i++) {
+ var bound1 = typeParameters1[i].bound;
+ var bound2 = typeParameters2[i].bound;
+ if (bound1 == null && bound2 == null) {
+ continue;
+ }
+ bound1 ??= DynamicTypeImpl.instance;
+ bound2 ??= DynamicTypeImpl.instance;
+ bound1 = substitution1.substituteType(bound1);
+ bound2 = substitution2.substituteType(bound2);
+ if (!isEqualTo(bound1, bound2)) {
+ return null;
+ }
+
+ if (!bound1.isDynamic) {
+ freshTypeParameters[i].bound = bound1;
+ }
+ }
+
+ return RelatedTypeParameters._(
+ freshTypeParameters,
+ freshTypeParameterTypes,
+ );
+ }
+
/// Replaces all covariant occurrences of `dynamic`, `void`, and `Object` or
/// `Object?` with `Null` or `Never` and all contravariant occurrences of
/// `Null` or `Never` with `Object` or `Object?`.
@@ -1468,17 +1568,10 @@
return RuntimeTypeEqualityHelper(this).equal(T1, T2);
}
- DartType toLegacyType(DartType type) {
- if (isNonNullableByDefault) return type;
- return NullabilityEliminator.perform(typeProvider, type);
- }
-
/// If a legacy library, return the legacy version of the [type].
/// Otherwise, return the original type.
DartType toLegacyTypeIfOptOut(DartType type) {
- if (isNonNullableByDefault) {
- return type;
- }
+ if (isNonNullableByDefault) return type;
return NullabilityEliminator.perform(typeProvider, type);
}
diff --git a/pkg/analyzer/lib/src/dart/element/well_bounded.dart b/pkg/analyzer/lib/src/dart/element/well_bounded.dart
new file mode 100644
index 0000000..9ca8629
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/well_bounded.dart
@@ -0,0 +1,138 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
+
+class NotWellBoundedTypeResult implements TypeBoundedResult {
+ final String elementName;
+ final List<TypeArgumentIssue> issues;
+
+ NotWellBoundedTypeResult._({
+ required this.elementName,
+ required this.issues,
+ });
+}
+
+class RegularBoundedTypeResult implements WellBoundedTypeResult {
+ const RegularBoundedTypeResult._();
+}
+
+class SuperBoundedTypeResult implements WellBoundedTypeResult {
+ const SuperBoundedTypeResult._();
+}
+
+class TypeArgumentIssue {
+ /// The index for type argument within the passed type arguments.
+ final int index;
+
+ /// The type parameter with the bound that was violated.
+ final TypeParameterElement parameter;
+
+ /// The substituted bound of the [parameter].
+ final DartType parameterBound;
+
+ /// The type argument that violated the [parameterBound].
+ final DartType argument;
+
+ TypeArgumentIssue(
+ this.index,
+ this.parameter,
+ this.parameterBound,
+ this.argument,
+ );
+
+ @override
+ String toString() {
+ return 'TypeArgumentIssue(index=$index, parameter=$parameter, '
+ 'parameterBound=$parameterBound, argument=$argument)';
+ }
+}
+
+/// Helper for checking whether a type if well-bounded.
+///
+/// See `15.2 Super-bounded types` in the language specification.
+class TypeBoundedHelper {
+ final TypeSystemImpl typeSystem;
+
+ TypeBoundedHelper(this.typeSystem);
+
+ TypeBoundedResult isWellBounded(
+ DartType type, {
+ required bool allowSuperBounded,
+ }) {
+ var result = _isRegularBounded(type);
+ if (!allowSuperBounded) {
+ return result;
+ }
+
+ return _isSuperBounded(type);
+ }
+
+ TypeBoundedResult _isRegularBounded(DartType type) {
+ List<TypeArgumentIssue>? issues;
+
+ final String elementName;
+ final List<TypeParameterElement> typeParameters;
+ final List<DartType> typeArguments;
+ final alias = type.alias;
+ if (alias != null) {
+ elementName = alias.element.name;
+ typeParameters = alias.element.typeParameters;
+ typeArguments = alias.typeArguments;
+ } else if (type is InterfaceType) {
+ elementName = type.element.name;
+ typeParameters = type.element.typeParameters;
+ typeArguments = type.typeArguments;
+ } else {
+ return const RegularBoundedTypeResult._();
+ }
+
+ final substitution = Substitution.fromPairs(typeParameters, typeArguments);
+ for (var i = 0; i < typeParameters.length; i++) {
+ var typeParameter = typeParameters[i];
+ var typeArgument = typeArguments[i];
+
+ var bound = typeParameter.bound;
+ if (bound == null) {
+ continue;
+ }
+
+ bound = typeSystem.toLegacyTypeIfOptOut(bound);
+ bound = substitution.substituteType(bound);
+
+ if (!typeSystem.isSubtypeOf(typeArgument, bound)) {
+ issues ??= <TypeArgumentIssue>[];
+ issues.add(
+ TypeArgumentIssue(i, typeParameter, bound, typeArgument),
+ );
+ }
+ }
+
+ if (issues == null) {
+ return const RegularBoundedTypeResult._();
+ } else {
+ return NotWellBoundedTypeResult._(
+ elementName: elementName,
+ issues: issues,
+ );
+ }
+ }
+
+ TypeBoundedResult _isSuperBounded(DartType type) {
+ final invertedType = typeSystem.replaceTopAndBottom(type);
+ var result = _isRegularBounded(invertedType);
+ if (result is RegularBoundedTypeResult) {
+ return const SuperBoundedTypeResult._();
+ } else {
+ return result;
+ }
+ }
+}
+
+abstract class TypeBoundedResult {}
+
+class WellBoundedTypeResult implements TypeBoundedResult {}
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
index 873531a..18488af 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
import "package:analyzer/src/error/analyzer_error_code.dart";
@@ -103,6 +103,7 @@
"Fields in a struct class whose type is 'Pointer' shouldn't have any "
"annotations.",
correctionMessage: "Try removing the annotation.",
+ hasPublishedDocs: true,
);
/**
@@ -163,6 +164,7 @@
'ARGUMENT_MUST_BE_A_CONSTANT',
"Argument '{0}' must be a constant.",
correctionMessage: "Try replacing the value with a literal or const.",
+ hasPublishedDocs: true,
);
/**
@@ -220,6 +222,7 @@
"be instantiated by a generative constructor.",
correctionMessage:
"Try allocating it via allocation, or load from a 'Pointer'.",
+ hasPublishedDocs: true,
);
/**
@@ -279,6 +282,7 @@
"The class '{0}' can't be empty because it's a subclass of '{1}'.",
correctionMessage:
"Try adding a field to '{0}' or use a different superclass.",
+ hasPublishedDocs: true,
);
/**
@@ -323,6 +327,7 @@
"Fields in a struct class must have exactly one annotation indicating the "
"native type.",
correctionMessage: "Try removing the extra annotation.",
+ hasPublishedDocs: true,
);
/**
@@ -367,6 +372,7 @@
'EXTRA_SIZE_ANNOTATION_CARRAY',
"'Array's must have exactly one 'Array' annotation.",
correctionMessage: "Try removing the extra annotation.",
+ hasPublishedDocs: true,
);
/**
@@ -465,6 +471,7 @@
"initializers.",
correctionMessage:
"Try removing the field initializer and marking the field as external.",
+ hasPublishedDocs: true,
);
/**
@@ -508,6 +515,7 @@
"Fields in subclasses of 'Struct' and 'Union' can't have initializers.",
correctionMessage:
"Try removing the initializer and marking the field as external.",
+ hasPublishedDocs: true,
);
/**
@@ -550,6 +558,7 @@
'FIELD_MUST_BE_EXTERNAL_IN_STRUCT',
"Fields of 'Struct' and 'Union' subclasses must be marked external.",
correctionMessage: "Try adding the 'external' modifier.",
+ hasPublishedDocs: true,
);
/**
@@ -592,6 +601,7 @@
"The class '{0}' can't extend 'Struct' or 'Union' because '{0}' is "
"generic.",
correctionMessage: "Try removing the type parameters from '{0}'.",
+ hasPublishedDocs: true,
);
/**
@@ -644,6 +654,7 @@
"(the second argument) when the return type of the function is either "
"'void', 'Handle' or 'Pointer'.",
correctionMessage: "Try removing the exceptional return value.",
+ hasPublishedDocs: true,
);
/**
@@ -698,6 +709,7 @@
correctionMessage:
"Try using 'int', 'double', 'Array', 'Pointer', or subtype of 'Struct' "
"or 'Union'.",
+ hasPublishedDocs: true,
);
/**
@@ -758,6 +770,7 @@
'LEAF_CALL_MUST_NOT_RETURN_HANDLE',
"FFI leaf call can't return a 'Handle'.",
correctionMessage: "Try changing the return type to primitive or struct.",
+ hasPublishedDocs: true,
);
/**
@@ -812,6 +825,7 @@
'LEAF_CALL_MUST_NOT_TAKE_HANDLE',
"FFI leaf call can't take arguments of type 'Handle'.",
correctionMessage: "Try changing the argument type to primitive or struct.",
+ hasPublishedDocs: true,
);
/**
@@ -867,6 +881,7 @@
correctionMessage:
"Try using a different annotation or changing the declared type to "
"match.",
+ hasPublishedDocs: true,
);
/**
@@ -912,6 +927,7 @@
"Fields in a struct class must either have the type 'Pointer' or an "
"annotation indicating the native type.",
correctionMessage: "Try adding an annotation.",
+ hasPublishedDocs: true,
);
/**
@@ -961,6 +977,7 @@
"(the second argument) when the return type of the function is neither "
"'void', 'Handle', nor 'Pointer'.",
correctionMessage: "Try adding an exceptional return value.",
+ hasPublishedDocs: true,
);
/**
@@ -1012,6 +1029,7 @@
"Fields in struct classes must have an explicitly declared type of 'int', "
"'double' or 'Pointer'.",
correctionMessage: "Try using 'int', 'double' or 'Pointer'.",
+ hasPublishedDocs: true,
);
/**
@@ -1056,6 +1074,7 @@
correctionMessage:
"Try adding an 'Array' annotation, or removing all but one of the "
"annotations.",
+ hasPublishedDocs: true,
);
/**
@@ -1110,6 +1129,7 @@
"type.",
correctionMessage:
"Try changing the type to only use members for 'dart:ffi'.",
+ hasPublishedDocs: true,
);
/**
@@ -1180,6 +1200,7 @@
'MUST_BE_A_SUBTYPE',
"The type '{0}' must be a subtype of '{1}' for '{2}'.",
correctionMessage: "Try changing one or both of the type arguments.",
+ hasPublishedDocs: true,
);
/**
@@ -1231,6 +1252,7 @@
"The type arguments to '{0}' must be known at compile time, so they can't "
"be type parameters.",
correctionMessage: "Try changing the type argument to be a constant type.",
+ hasPublishedDocs: true,
);
/**
@@ -1287,6 +1309,7 @@
correctionMessage:
"Try changing the function argument in 'NativeFunction' to only use "
"NativeTypes.",
+ hasPublishedDocs: true,
);
/**
@@ -1329,6 +1352,7 @@
'NON_POSITIVE_ARRAY_DIMENSION',
"Array dimensions must be positive numbers.",
correctionMessage: "Try changing the input to a positive number.",
+ hasPublishedDocs: true,
);
/**
@@ -1378,6 +1402,7 @@
correctionMessage:
"Try using a native integer, 'Float', 'Double', 'Pointer', or subtype "
"of 'Struct', 'Union', or 'AbiSpecificInteger'.",
+ hasPublishedDocs: true,
);
/**
@@ -1421,6 +1446,7 @@
'PACKED_ANNOTATION',
"Structs must have at most one 'Packed' annotation.",
correctionMessage: "Try removing extra 'Packed' annotations.",
+ hasPublishedDocs: true,
);
/**
@@ -1464,6 +1490,7 @@
"Only packing to 1, 2, 4, 8, and 16 bytes is supported.",
correctionMessage:
"Try changing the 'Packed' annotation alignment to 1, 2, 4, 8, or 16.",
+ hasPublishedDocs: true,
);
/**
@@ -1554,6 +1581,7 @@
correctionMessage:
"Try packing the nested struct or packing the nested struct more "
"tightly.",
+ hasPublishedDocs: true,
);
/**
@@ -1610,6 +1638,7 @@
'SIZE_ANNOTATION_DIMENSIONS',
"'Array's must have an 'Array' annotation that matches the dimensions.",
correctionMessage: "Try adjusting the arguments in the 'Array' annotation.",
+ hasPublishedDocs: true,
);
/**
@@ -1661,6 +1690,7 @@
'SUBTYPE_OF_FFI_CLASS',
"The class '{0}' can't extend '{1}'.",
correctionMessage: "Try extending 'Struct' or 'Union'.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_EXTENDS',
);
@@ -1673,6 +1703,7 @@
'SUBTYPE_OF_FFI_CLASS',
"The class '{0}' can't implement '{1}'.",
correctionMessage: "Try implementing 'Allocator' or 'Finalizable'.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS',
);
@@ -1685,6 +1716,7 @@
'SUBTYPE_OF_FFI_CLASS',
"The class '{0}' can't mix in '{1}'.",
correctionMessage: "Try extending 'Struct' or 'Union'.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_WITH',
);
@@ -1743,6 +1775,7 @@
"'Struct', 'Union', or 'AbiSpecificInteger'.",
correctionMessage:
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS',
);
@@ -1757,6 +1790,7 @@
"'Struct', 'Union', or 'AbiSpecificInteger'.",
correctionMessage:
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS',
);
@@ -1771,6 +1805,7 @@
"'Struct', 'Union', or 'AbiSpecificInteger'.",
correctionMessage:
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
+ hasPublishedDocs: true,
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_WITH',
);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index 6f9b09b..aa8d8df 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
import "package:analyzer/src/error/analyzer_error_code.dart";
@@ -83,17 +83,76 @@
/**
* Users should not assign values marked `@doNotStore`.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the value of a function
+ // (including methods and getters) that is explicitly or implicitly marked by
+ // the `[doNotStore][meta-doNotStore]` annotation is stored in either a field
+ // or top-level variable.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the value of the
+ // function `f` is being stored in the top-level variable `x`:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @doNotStore
+ // int f() => 1;
+ //
+ // var x = [!f()!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Replace references to the field or variable with invocations of the
+ // function producing the value.
static const HintCode ASSIGNMENT_OF_DO_NOT_STORE = HintCode(
'ASSIGNMENT_OF_DO_NOT_STORE',
"'{0}' is marked 'doNotStore' and shouldn't be assigned to a field or "
"top-level variable.",
correctionMessage: "Try removing the assignment.",
+ hasPublishedDocs: true,
);
/**
* Parameters:
* 0: the name of the declared return type
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a method or function can
+ // implicitly return `null` by falling off the end. While this is valid Dart
+ // code, it's better for the return of `null` to be explicit.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the function `f`
+ // implicitly returns `null`:
+ //
+ // ```dart
+ // String? [!f!]() {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the return of `null` is intentional, then make it explicit:
+ //
+ // ```dart
+ // String? f() {
+ // return null;
+ // }
+ // ```
+ //
+ // If the function should return a non-null value along that path, then add
+ // the missing return statement:
+ //
+ // ```dart
+ // String? f() {
+ // return '';
+ // }
+ // ```
static const HintCode BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE = HintCode(
'BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE',
"This function has a nullable return type of '{0}', but ends without "
@@ -461,10 +520,59 @@
/**
* No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a comment reference (the name
+ // of a declaration enclosed in square brackets in a documentation comment)
+ // uses the keyword `new` to refer to a constructor. This form is deprecated.
+ //
+ // #### Examples
+ //
+ // The following code produces this diagnostic because the unnamed
+ // constructor is being referenced using `new C`:
+ //
+ // ```dart
+ // /// See [[!new!] C].
+ // class C {
+ // C();
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because the constructor named
+ // `c` is being referenced using `new C.c`:
+ //
+ // ```dart
+ // /// See [[!new!] C.c].
+ // class C {
+ // C.c();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you're referencing a named constructor, then remove the keyword `new`:
+ //
+ // ```dart
+ // /// See [C.c].
+ // class C {
+ // C.c();
+ // }
+ // ```
+ //
+ // If you're referencing the unnamed constructor, then remove the keyword
+ // `new` and append `.new` after the class name:
+ //
+ // ```dart
+ // /// See [C.new].
+ // class C {
+ // C.c();
+ // }
+ // ```
static const HintCode DEPRECATED_NEW_IN_COMMENT_REFERENCE = HintCode(
'DEPRECATED_NEW_IN_COMMENT_REFERENCE',
"Using the 'new' keyword in a comment reference is deprecated.",
correctionMessage: "Try referring to a constructor by its name.",
+ hasPublishedDocs: true,
);
/**
@@ -866,7 +974,8 @@
// ```
//
// If type arguments shouldn't be required for the class, then mark the class
- // with the `@optionalTypeArgs` annotation (from `package:meta`):
+ // with the `[optionalTypeArgs][meta-optionalTypeArgs]` annotation (from
+ // `package:meta`):
static const HintCode IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION = HintCode(
'IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION',
"The imported library defines a top-level function named 'loadLibrary' "
@@ -878,13 +987,49 @@
);
/**
+ * No parameters.
+ *
* https://github.com/dart-lang/sdk/issues/44063
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a library that is null safe
+ // imports a library that isn't null safe.
+ //
+ // #### Example
+ //
+ // Given a file named `a.dart` that contains the following:
+ //
+ // ```dart
+ // %uri="lib/a.dart"
+ // // @dart = 2.9
+ //
+ // class A {}
+ // ```
+ //
+ // The following code produces this diagnostic because a library that null
+ // safe is importing a library that isn't null safe:
+ //
+ // ```dart
+ // import [!'a.dart'!];
+ //
+ // A? f() => null;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you can migrate the imported library to be null safe, then migrate it
+ // and update or remove the migrated library's language version.
+ //
+ // If you can't migrate the imported library, then the importing library
+ // needs to have a language version that is before 2.12, when null safety was
+ // enabled by default.
static const HintCode IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE = HintCode(
'IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE',
- "The library '{0}' is legacy, and should not be imported into a null safe "
+ "The library '{0}' is legacy, and shouldn't be imported into a null safe "
"library.",
correctionMessage: "Try migrating the imported library.",
+ hasPublishedDocs: true,
);
/**
@@ -967,37 +1112,126 @@
* 0: the name of the annotation
* 1: the list of valid targets
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an annotation is applied to a
+ // kind of declaration that it doesn't support.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the `optionalTypeArgs`
+ // annotation isn't defined to be valid for top-level variables:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @[!optionalTypeArgs!]
+ // int x = 0;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the annotation from the declaration.
static const HintCode INVALID_ANNOTATION_TARGET = HintCode(
'INVALID_ANNOTATION_TARGET',
- "The annotation '{0}' can only be used on {1}",
+ "The annotation '{0}' can only be used on {1}.",
+ hasPublishedDocs: true,
);
/**
- * This hint is generated anywhere where an element annotated with `@internal`
- * is exported as a part of a package's public API.
- *
* Parameters:
* 0: the name of the element
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a [public library][] exports a
+ // declaration that is marked with the `[internal][meta-internal]`
+ // annotation.
+ //
+ // #### Example
+ //
+ // Given a file named `a.dart` in the `src` directory that contains:
+ //
+ // ```dart
+ // %uri="lib/src/a.dart"
+ // import 'package:meta/meta.dart';
+ //
+ // @internal class One {}
+ // ```
+ //
+ // The following code, when found in a [public library][] produces this
+ // diagnostic because the `export` directive is exporting a name that is only
+ // intended to be used internally:
+ //
+ // ```dart
+ // [!export 'src/a.dart';!]
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the export is needed, then add a `hide` clause to hide the internal
+ // names:
+ //
+ // ```dart
+ // export 'src/a.dart' hide One;
+ // ```
+ //
+ // If the export isn't needed, then remove it.
static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT = HintCode(
'INVALID_EXPORT_OF_INTERNAL_ELEMENT',
"The member '{0}' can't be exported as a part of a package's public API.",
correctionMessage: "Try using a hide clause to hide '{0}'.",
+ hasPublishedDocs: true,
);
/**
- * This hint is generated anywhere where an element annotated with `@internal`
- * is exported indirectly as a part of a package's public API.
- *
* Parameters:
* 0: the name of the element
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a [public library][] exports a
+ // top-level function with a return type or at least one parameter type that
+ // is marked with the `[internal][meta-internal]` annotation.
+ //
+ // #### Example
+ //
+ // Given a file named `a.dart` in the `src` directory that contains the
+ // following:
+ //
+ // ```dart
+ // %uri="lib/src/a.dart"
+ // import 'package:meta/meta.dart';
+ //
+ // @internal
+ // typedef IntFunction = int Function();
+ //
+ // int f(IntFunction g) => g();
+ // ```
+ //
+ // The following code produces this diagnostic because the function `f` has a
+ // parameter of type `IntFunction`, and `IntFunction` is only intended to be
+ // used internally:
+ //
+ // ```dart
+ // [!export 'src/a.dart' show f;!]
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the function must be public, then make all the types in the function's
+ // signature public types.
+ //
+ // If the function doesn't need to be exported, then stop exporting it,
+ // either by removing it from the `show` clause, adding it to the `hide`
+ // clause, or by removing the export.
static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY =
HintCode(
'INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY',
"The member '{0}' can't be exported as a part of a package's public API, "
"but is indirectly exported as part of the signature of '{1}'.",
correctionMessage: "Try using a hide clause to hide '{0}'.",
+ hasPublishedDocs: true,
);
/**
@@ -1010,25 +1244,97 @@
);
/**
- * This hint is generated anywhere a @factory annotation is associated with
- * a method that does not declare a return type.
+ * Parameters:
+ * 0: The name of the method
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a method that is annotated with
+ // the `[factory][meta-factory]` annotation has a return type of `void`.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the method `createC`
+ // is annotated with the `[factory][meta-factory]` annotation but doesn't
+ // return any value:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class Factory {
+ // @factory
+ // void [!createC!]() {}
+ // }
+ //
+ // class C {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Change the return type to something other than `void`:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class Factory {
+ // @factory
+ // C createC() => C();
+ // }
+ //
+ // class C {}
+ // ```
static const HintCode INVALID_FACTORY_METHOD_DECL = HintCode(
'INVALID_FACTORY_METHOD_DECL',
"Factory method '{0}' must have a return type.",
+ hasPublishedDocs: true,
);
/**
- * This hint is generated anywhere a @factory annotation is associated with
- * a non-abstract method that can return anything other than a newly allocated
- * object.
- *
* Parameters:
* 0: the name of the method
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a method that is annotated with
+ // the `[factory][meta-factory]` annotation doesn't return a newly allocated
+ // object.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the method `createC`
+ // returns the value of a field rather than a newly created instance of `C`:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class Factory {
+ // C c = C();
+ //
+ // @factory
+ // C [!createC!]() => c;
+ // }
+ //
+ // class C {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Change the method to return a newly created instance of the return type:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class Factory {
+ // @factory
+ // C createC() => C();
+ // }
+ //
+ // class C {}
+ // ```
static const HintCode INVALID_FACTORY_METHOD_IMPL = HintCode(
'INVALID_FACTORY_METHOD_IMPL',
"Factory method '{0}' doesn't return a newly allocated object.",
+ hasPublishedDocs: true,
);
/**
@@ -1041,108 +1347,153 @@
);
/**
- * This hint is generated anywhere a @internal annotation is associated with
- * an element found in a package's public API.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a declaration is annotated with
+ // the `[internal][meta-internal]` annotation and that declaration is either
+ // in a [public library][] or has a private name.
+ //
+ // #### Example
+ //
+ // The following code, when in a [public library][], produces this diagnostic
+ // because the `[internal][meta-internal]` annotation can't be applied to
+ // declarations in a [public library][]:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // [!@internal!]
+ // class C {}
+ // ```
+ //
+ // The following code, whether in a public or internal library, produces this
+ // diagnostic because the `[internal][meta-internal]` annotation can't be
+ // applied to declarations with private names:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // [!@internal!]
+ // class _C {}
+ //
+ // void f(_C c) {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the declaration has a private name, then remove the annotation:
+ //
+ // ```dart
+ // class _C {}
+ //
+ // void f(_C c) {}
+ // ```
+ //
+ // If the declaration has a public name and is intended to be internal to the
+ // package, then move the annotated declaration into an internal library (in
+ // other words, a library inside the `src` directory).
+ //
+ // Otherwise, remove the use of the annotation:
+ //
+ // ```dart
+ // class C {}
+ // ```
static const HintCode INVALID_INTERNAL_ANNOTATION = HintCode(
'INVALID_INTERNAL_ANNOTATION',
"Only public elements in a package's private API can be annotated as being "
"internal.",
+ hasPublishedDocs: true,
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a comment that appears to be an
+ // attempt to specify a language version override doesn't conform to the
+ // requirements for such a comment. For more information, see
+ // [Per-library language version selection](https://dart.dev/guides/language/evolution#per-library-language-version-selection).
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the word `dart` must
+ // be lowercase in such a comment and because there's no equal sign between
+ // the word `dart` and the version number:
+ //
+ // ```dart
+ // [!// @Dart 2.9!]
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the comment is intended to be a language version override, then change
+ // the comment to follow the correct format:
+ //
+ // ```dart
+ // // @dart = 2.9
+ // ```
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
- "The Dart language version override number must begin with '@dart'",
+ "The Dart language version override number must begin with '@dart'.",
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
"The Dart language version override comment must be specified with an '=' "
- "character",
+ "character.",
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS',
);
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
"The language version override can't specify a version greater than the "
- "latest known language version: {0}.{1}",
+ "latest known language version: {0}.{1}.",
correctionMessage: "Try removing the language version override.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER',
);
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
- "The language version override must be before any declaration or "
+ "The language version override must be specified before any declaration or "
"directive.",
correctionMessage:
"Try moving the language version override to the top of the file.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
"The Dart language version override comment must be specified with the "
- "word 'dart' in all lower case",
+ "word 'dart' in all lower case.",
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
@@ -1151,64 +1502,41 @@
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX = HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
- "The Dart language version override number can't be prefixed with a letter",
+ "The Dart language version override number can't be prefixed with a "
+ "letter.",
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS =
HintCode(
'INVALID_LANGUAGE_VERSION_OVERRIDE',
"The Dart language version override comment can't be followed by any "
- "non-whitespace characters",
+ "non-whitespace characters.",
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS',
);
/**
- * Invalid Dart language version comments don't follow the specification [1].
- * If a comment begins with "@dart" or "dart" (letters in any case),
- * followed by optional whitespace, followed by optional non-alphanumeric,
- * non-whitespace characters, followed by optional whitespace, followed by
- * an optional alphabetical character, followed by a digit, then the
- * comment is considered to be an attempt at a language version override
- * comment. If this attempted language version override comment is not a
- * valid language version override comment, it is reported.
- *
- * [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ * No parameters.
*/
static const HintCode INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES =
HintCode(
@@ -1218,6 +1546,7 @@
correctionMessage:
"Specify a Dart language version override with a comment like '// "
"@dart = 2.0'.",
+ hasPublishedDocs: true,
uniqueName: 'INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES',
);
@@ -1226,8 +1555,8 @@
*/
// #### Description
//
- // The analyzer produces this diagnostic when the `@literal` annotation is
- // applied to anything other than a const constructor.
+ // The analyzer produces this diagnostic when the `[literal][[meta-literal]]`
+ // annotation is applied to anything other than a const constructor.
//
// #### Examples
//
@@ -1364,15 +1693,44 @@
);
/**
- * This hint is generated anywhere where a member annotated with `@internal`
- * is used outside of the package in which it is declared.
- *
* Parameters:
* 0: the name of the member
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a reference to a declaration
+ // that is annotated with the `[internal][meta-internal]` annotation is found
+ // outside the package containing the declaration.
+ //
+ // #### Example
+ //
+ // Given a package `p` that defines a library containing a declaration marked
+ // with the `[internal][meta-internal]` annotation:
+ //
+ // ```dart
+ // %uri="package:p/src/p.dart"
+ // import 'package:meta/meta.dart';
+ //
+ // @internal
+ // class C {}
+ // ```
+ //
+ // The following code produces this diagnostic because it's referencing the
+ // class `C`, which isn't intended to be used outside the package `p`:
+ //
+ // ```dart
+ // import 'package:p/src/p.dart';
+ //
+ // void f([!C!] c) {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the reference to the internal declaration.
static const HintCode INVALID_USE_OF_INTERNAL_MEMBER = HintCode(
'INVALID_USE_OF_INTERNAL_MEMBER',
"The member '{0}' can only be used within its package.",
+ hasPublishedDocs: true,
);
/**
@@ -1396,8 +1754,9 @@
// #### Description
//
// The analyzer produces this diagnostic when an instance member that is
- // annotated with `visibleForOverriding` is referenced outside the library in
- // which it's declared for any reason other than to override it.
+ // annotated with `[visibleForOverriding][meta-visibleForOverriding]` is
+ // referenced outside the library in which it's declared for any reason other
+ // than to override it.
//
// #### Example
//
@@ -1472,8 +1831,9 @@
*/
// #### Description
//
- // The analyzer produces this diagnostic when either the `@visibleForTemplate`
- // or `@visibleForTesting` annotation is applied to a non-public declaration.
+ // The analyzer produces this diagnostic when either the `visibleForTemplate`
+ // or `[visibleForTesting][meta-visibleForTesting]` annotation is applied to
+ // a non-public declaration.
//
// #### Example
//
@@ -1522,9 +1882,10 @@
// #### Description
//
// The analyzer produces this diagnostic when anything other than a public
- // instance member of a class is annotated with `visibleForOverriding`.
- // Because only public instance members can be overridden outside the defining
- // library, there's no value to annotating any other declarations.
+ // instance member of a class is annotated with
+ // `[visibleForOverriding][meta-visibleForOverriding]`. Because only public
+ // instance members can be overridden outside the defining library, there's
+ // no value to annotating any other declarations.
//
// #### Example
//
@@ -1663,9 +2024,9 @@
// #### Description
//
// The analyzer produces this diagnostic when the superclass constraint of a
- // mixin is a class from a different package that was marked as `@sealed`.
- // Classes that are sealed can't be extended, implemented, mixed in, or used
- // as a superclass constraint.
+ // mixin is a class from a different package that was marked as
+ // `[sealed][meta-sealed]`. Classes that are sealed can't be extended,
+ // implemented, mixed in, or used as a superclass constraint.
//
// #### Example
//
@@ -1712,8 +2073,8 @@
//
// The analyzer produces this diagnostic when an immutable class defines one
// or more instance fields that aren't final. A class is immutable if it's
- // marked as being immutable using the annotation `@immutable` or if it's a
- // subclass of an immutable class.
+ // marked as being immutable using the annotation
+ // `[immutable][meta-immutable]` or if it's a subclass of an immutable class.
//
// #### Example
//
@@ -1773,8 +2134,8 @@
// #### Description
//
// The analyzer produces this diagnostic when a method that overrides a method
- // that is annotated as `@mustCallSuper` doesn't invoke the overridden method
- // as required.
+ // that is annotated as `[mustCallSuper][meta-mustCallSuper]` doesn't invoke
+ // the overridden method as required.
//
// #### Example
//
@@ -1831,10 +2192,10 @@
// #### Description
//
// The analyzer produces this diagnostic when a constructor that has the
- // `@literal` annotation is invoked without using the `const` keyword, but all
- // of the arguments to the constructor are constants. The annotation indicates
- // that the constructor should be used to create a constant value whenever
- // possible.
+ // `[literal][meta-literal]` annotation is invoked without using the `const`
+ // keyword, but all of the arguments to the constructor are constants. The
+ // annotation indicates that the constructor should be used to create a
+ // constant value whenever possible.
//
// #### Example
//
@@ -2009,13 +2370,47 @@
);
/**
- * This hint indicates that a null literal is null-checked with `!`, but null
- * is never not null.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the null check operator (`!`)
+ // is used on an expression whose value can only be `null`. In such a case
+ // the operator always throws an exception, which likely isn't the intended
+ // behavior.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the function `g` will
+ // always return `null`, which means that the null check in `f` will always
+ // throw:
+ //
+ // ```dart
+ // void f() {
+ // [!g()!!];
+ // }
+ //
+ // Null g() => null;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you intend to always throw an exception, then replace the null check
+ // with an explicit `throw` expression to make the intent more clear:
+ //
+ // ```dart
+ // void f() {
+ // g();
+ // throw TypeError();
+ // }
+ //
+ // Null g() => null;
+ // ```
static const HintCode NULL_CHECK_ALWAYS_FAILS = HintCode(
'NULL_CHECK_ALWAYS_FAILS',
"This null-check will always throw an exception because the expression "
"will always evaluate to 'null'.",
+ hasPublishedDocs: true,
);
/**
@@ -2145,14 +2540,62 @@
);
/**
- * Users should not return values marked `@doNotStore` from functions,
- * methods or getters not marked `@doNotStore`.
+ * Parameters:
+ * 0: the name of the annotated function being invoked
+ * 1: the name of the function containing the return
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a value that is annotated with
+ // the `[doNotStore][meta-doNotStore]` annotation is returned from a method,
+ // getter, or function that doesn't have the same annotation.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the result of invoking
+ // `f` shouldn't be stored, but the function `g` isn't annotated to preserve
+ // that semantic:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @doNotStore
+ // int f() => 0;
+ //
+ // int g() => [!f()!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the value that shouldn't be stored is the correct value to return, then
+ // mark the function with the `[doNotStore][meta-doNotStore]` annotation:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @doNotStore
+ // int f() => 0;
+ //
+ // @doNotStore
+ // int g() => f();
+ // ```
+ //
+ // Otherwise, return a different value from the function:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @doNotStore
+ // int f() => 0;
+ //
+ // int g() => 0;
+ // ```
static const HintCode RETURN_OF_DO_NOT_STORE = HintCode(
'RETURN_OF_DO_NOT_STORE',
"'{0}' is annotated with 'doNotStore' and shouldn't be returned unless "
"'{1}' is also annotated.",
correctionMessage: "Annotate '{1}' with 'doNotStore'.",
+ hasPublishedDocs: true,
);
/**
@@ -2955,10 +3398,10 @@
// #### Description
//
// The analyzer produces this diagnostic when a sealed class (one that either
- // has the `@sealed` annotation or inherits or mixes in a sealed class) is
- // referenced in either the `extends`, `implements`, or `with` clause of a
- // class or mixin declaration if the declaration isn't in the same package as
- // the sealed class.
+ // has the `[sealed][meta-sealed]` annotation or inherits or mixes in a
+ // sealed class) is referenced in either the `extends`, `implements`, or
+ // `with` clause of a class or mixin declaration if the declaration isn't in
+ // the same package as the sealed class.
//
// #### Example
//
@@ -3213,8 +3656,8 @@
// #### Description
//
// The analyzer produces this diagnostic when an annotation of the form
- // `@UnusedResult.unless(parameterDefined: parameterName)` specifies a
- // parameter name that isn't defined by the annotated function.
+ // `[UseResult][meta-UseResult].unless(parameterDefined: parameterName)`
+ // specifies a parameter name that isn't defined by the annotated function.
//
// #### Example
//
@@ -3941,16 +4384,16 @@
// #### Description
//
// The analyzer produces this diagnostic when a function annotated with
- // `useResult` is invoked, and the value returned by that function isn't used.
- // The value is considered to be used if a member of the value is invoked, if
- // the value is passed to another function, or if the value is assigned to a
- // variable or field.
+ // `[useResult][meta-useResult]` is invoked, and the value returned by that
+ // function isn't used. The value is considered to be used if a member of the
+ // value is invoked, if the value is passed to another function, or if the
+ // value is assigned to a variable or field.
//
// #### Example
//
// The following code produces this diagnostic because the invocation of
// `c.a()` isn't used, even though the method `a` is annotated with
- // `useResult`:
+ // `[useResult][meta-useResult]`:
//
// ```dart
// import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index 1a6f7b2..06dc036 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
@@ -135,6 +135,9 @@
ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS,
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR,
ParserErrorCode.TYPE_PARAMETER_ON_OPERATOR,
+ ParserErrorCode.MULTIPLE_CLAUSES,
+ ParserErrorCode.OUT_OF_ORDER_CLAUSES,
+ ParserErrorCode.UNEXPECTED_TOKENS,
];
class ParserErrorCode extends ErrorCode {
@@ -458,6 +461,13 @@
correctionMessage: "Try declaring a constant.",
);
+ static const ParserErrorCode
+ ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS = ParserErrorCode(
+ 'ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS',
+ "Missing arguments in enum constructor invocation.",
+ correctionMessage: "Try adding an argument list.",
+ );
+
static const ParserErrorCode ENUM_IN_CLASS = ParserErrorCode(
'ENUM_IN_CLASS',
"Enums can't be declared inside classes.",
@@ -781,6 +791,7 @@
'FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
"Field formal parameters can only be used in a constructor.",
correctionMessage: "Try removing 'this.'.",
+ hasPublishedDocs: true,
);
static const ParserErrorCode FINAL_AND_COVARIANT = ParserErrorCode(
@@ -1287,6 +1298,13 @@
correctionMessage: "Try re-ordering the modifiers.",
);
+ static const ParserErrorCode MULTIPLE_CLAUSES = ParserErrorCode(
+ 'MULTIPLE_CLAUSES',
+ "Each '{0}' definition can have at most one '{1}' clause.",
+ correctionMessage:
+ "Try combining all of the '{1}' clauses into a single clause.",
+ );
+
static const ParserErrorCode MULTIPLE_EXTENDS_CLAUSES = ParserErrorCode(
'MULTIPLE_EXTENDS_CLAUSES',
"Each class definition can have at most one extends clause.",
@@ -1461,6 +1479,12 @@
"sequence.",
);
+ static const ParserErrorCode OUT_OF_ORDER_CLAUSES = ParserErrorCode(
+ 'OUT_OF_ORDER_CLAUSES',
+ "The '{0}' clause must come before the '{1}' clause.",
+ correctionMessage: "Try moving the '{0}' clause before the '{1}' clause.",
+ );
+
static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT =
ParserErrorCode(
'POSITIONAL_AFTER_NAMED_ARGUMENT',
@@ -1629,6 +1653,11 @@
correctionMessage: "Try removing the text.",
);
+ static const ParserErrorCode UNEXPECTED_TOKENS = ParserErrorCode(
+ 'UNEXPECTED_TOKENS',
+ "Unexpected tokens.",
+ );
+
static const ParserErrorCode VAR_AND_TYPE = ParserErrorCode(
'VAR_AND_TYPE',
"Variables can't be declared using both 'var' and a type name.",
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 0652729..6e65351 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -495,7 +495,7 @@
AnalysisErrorListener errorListener = _getErrorListener(file);
var unit = file.parse(errorListener, content);
- LineInfo lineInfo = unit.lineInfo!;
+ LineInfo lineInfo = unit.lineInfo;
_fileToLineInfo[file] = lineInfo;
_fileToIgnoreInfo[file] = IgnoreInfo.forDart(unit, content);
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 6476871..9597bff 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -870,10 +870,10 @@
location.source,
errorListener,
featureSet: scanner.featureSet,
+ lineInfo: lineInfo,
);
parser.enableOptionalNewAndConst = true;
var unit = parser.parseCompilationUnit(token);
- unit.lineInfo = lineInfo;
// StringToken uses a static instance of StringCanonicalizer, so we need
// to clear it explicitly once we are done using it for this file.
@@ -961,7 +961,7 @@
hasPartOfDirective: hasPartOfDirective,
imports: imports,
informativeBytes: writeUnitInformative(unit),
- lineStarts: Uint32List.fromList(unit.lineInfo!.lineStarts),
+ lineStarts: Uint32List.fromList(unit.lineInfo.lineStarts),
partOfName: partOfName,
partOfUri: partOfUriStr,
parts: parts,
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index ac5a4809..73c6f51 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -204,7 +204,7 @@
references.add(CiderSearchMatch(
path,
offsets
- .map((offset) => lineInfo?.getLocation(offset))
+ .map((offset) => lineInfo.getLocation(offset))
.toList()));
}
});
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 192c94c..46980c7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -2,17 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -25,9 +21,6 @@
ErrorReporter get _errorReporter => _resolver.errorReporter;
- bool get _genericMetadataIsEnabled =>
- _definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
-
void resolve(
AnnotationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList) {
node.typeArguments?.accept(_resolver);
@@ -112,127 +105,35 @@
constructorElement = _resolver.toLegacyElement(constructorElement);
constructorName?.staticElement = constructorElement;
node.element = constructorElement;
+ var annotationInferrer =
+ AnnotationInferrer(constructorName: constructorName);
if (constructorElement == null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_ANNOTATION,
node,
);
- _resolver.visitArgumentList(argumentList,
+ annotationInferrer.resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: null,
+ contextType: null,
whyNotPromotedList: whyNotPromotedList);
return;
}
- // If no type parameters, the elements are correct.
- if (typeParameters.isEmpty) {
- var typeArgumentList = node.typeArguments;
- if (typeArgumentList != null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
- typeArgumentList,
- [
- typeDisplayName,
- typeParameters.length,
- typeArgumentList.arguments.length,
- ],
- );
- }
- _resolveConstructorInvocationArguments(node);
- InferenceContext.setType(argumentList, constructorElement.type);
- _resolver.visitArgumentList(argumentList,
- whyNotPromotedList: whyNotPromotedList);
- return;
- }
-
- void resolveWithFixedTypeArguments(
- List<DartType> typeArguments,
- ConstructorElement constructorElement,
- ) {
- var type = instantiateElement(typeArguments);
- constructorElement = ConstructorMember.from(constructorElement, type);
- constructorName?.staticElement = constructorElement;
- node.element = constructorElement;
- _resolveConstructorInvocationArguments(node);
-
- InferenceContext.setType(argumentList, constructorElement.type);
- _resolver.visitArgumentList(argumentList,
- whyNotPromotedList: whyNotPromotedList);
- }
-
- if (!_genericMetadataIsEnabled) {
- var typeArguments = List.filled(
- typeParameters.length,
- DynamicTypeImpl.instance,
- );
- resolveWithFixedTypeArguments(typeArguments, constructorElement);
- return;
- }
-
- var typeArgumentList = node.typeArguments;
- if (typeArgumentList != null) {
- List<DartType> typeArguments;
- if (typeArgumentList.arguments.length == typeParameters.length) {
- typeArguments = typeArgumentList.arguments
- .map((element) => element.typeOrThrow)
- .toList();
- var substitution = Substitution.fromPairs(
- typeParameters,
- typeArguments,
- );
- for (var i = 0; i < typeParameters.length; i++) {
- var typeParameter = typeParameters[i];
- var bound = typeParameter.bound;
- if (bound != null) {
- bound = substitution.substituteType(bound);
- var typeArgument = typeArguments[i];
- if (!_resolver.typeSystem.isSubtypeOf(typeArgument, bound)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
- typeArgumentList.arguments[i],
- [typeArgument, typeParameter.name, bound],
- );
- }
- }
- }
- } else {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
- typeArgumentList,
- [
- typeDisplayName,
- typeParameters.length,
- typeArgumentList.arguments.length,
- ],
- );
- typeArguments = List.filled(
- typeParameters.length,
- DynamicTypeImpl.instance,
- );
- }
- resolveWithFixedTypeArguments(typeArguments, constructorElement);
- return;
- }
-
- _resolver.visitArgumentList(argumentList,
- whyNotPromotedList: whyNotPromotedList);
-
var elementToInfer = ConstructorElementToInfer(
typeParameters,
constructorElement,
);
var constructorRawType = elementToInfer.asType;
- var inferred = _resolver.inferenceHelper.inferGenericInvoke(
- node, constructorRawType, typeArgumentList, argumentList, node,
- isConst: true)!;
-
- constructorElement = ConstructorMember.from(
- constructorElement,
- inferred.returnType as InterfaceType,
- );
- constructorName?.staticElement = constructorElement;
- node.element = constructorElement;
- _resolveConstructorInvocationArguments(node);
+ annotationInferrer.resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: constructorRawType,
+ contextType: null,
+ whyNotPromotedList: whyNotPromotedList);
}
void _extensionGetter(
@@ -432,24 +333,6 @@
}
}
- void _resolveConstructorInvocationArguments(AnnotationImpl node) {
- var argumentList = node.arguments;
- // error will be reported in ConstantVerifier
- if (argumentList == null) {
- return;
- }
- // resolve arguments to parameters
- var constructor = node.element;
- if (constructor is ConstructorElement) {
- argumentList.correspondingStaticParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- argumentList: argumentList,
- parameters: constructor.parameters,
- errorReporter: _errorReporter,
- );
- }
- }
-
void _typeAliasConstructorInvocation(
AnnotationImpl node,
TypeAliasElement typeAliasElement,
@@ -516,7 +399,11 @@
AnnotationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList) {
var arguments = node.arguments;
if (arguments != null) {
- _resolver.visitArgumentList(arguments,
+ AnnotationInferrer(constructorName: null).resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: null,
+ contextType: null,
whyNotPromotedList: whyNotPromotedList);
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 718c99b..f9b9cc8 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -42,7 +42,8 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(AssignmentExpressionImpl node) {
+ void resolve(AssignmentExpressionImpl node,
+ {required DartType? contextType}) {
var operator = node.operator.type;
var hasRead = operator != TokenType.EQ;
var isIfNull = operator == TokenType.QUESTION_QUESTION_EQ;
@@ -69,13 +70,14 @@
// TODO(scheglov) Use VariableElement and do in resolveForWrite() ?
_assignmentShared.checkFinalAlreadyAssigned(left);
+ DartType? rhsContext;
{
var leftType = node.writeType;
if (writeElement is VariableElement) {
leftType = _resolver.localVariableTypeProvider
.getType(left as SimpleIdentifier, isRead: false);
}
- _setRhsContext(node, leftType!, operator, right);
+ rhsContext = _computeRhsContext(node, leftType!, operator, right);
}
var flow = _resolver.flowAnalysis.flow;
@@ -83,11 +85,12 @@
flow.ifNullExpression_rightBegin(left, node.readType!);
}
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, rhsContext);
right = node.rightHandSide;
var whyNotPromoted = flow?.whyNotPromoted(right);
- _resolveTypes(node, whyNotPromoted: whyNotPromoted);
+ _resolveTypes(node,
+ whyNotPromoted: whyNotPromoted, contextType: contextType);
if (flow != null) {
if (writeElement is PromotableElement) {
@@ -147,6 +150,28 @@
return true;
}
+ DartType? _computeRhsContext(AssignmentExpressionImpl node, DartType leftType,
+ TokenType operator, Expression right) {
+ switch (operator) {
+ case TokenType.EQ:
+ case TokenType.QUESTION_QUESTION_EQ:
+ return leftType;
+ case TokenType.AMPERSAND_AMPERSAND_EQ:
+ case TokenType.BAR_BAR_EQ:
+ return _typeProvider.boolType;
+ default:
+ var method = node.staticElement;
+ if (method != null) {
+ var parameters = method.parameters;
+ if (parameters.isNotEmpty) {
+ return _typeSystem.refineNumericInvocationContext(
+ leftType, method, leftType, parameters[0].type);
+ }
+ }
+ return null;
+ }
+ }
+
void _resolveOperator(AssignmentExpressionImpl node) {
var left = node.leftHandSide;
var operator = node.operator;
@@ -200,29 +225,19 @@
}
void _resolveTypes(AssignmentExpressionImpl node,
- {required Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
+ {required Map<DartType, NonPromotionReason> Function()? whyNotPromoted,
+ required DartType? contextType}) {
DartType assignedType;
- DartType nodeType;
var rightHandSide = node.rightHandSide;
var operator = node.operator.type;
if (operator == TokenType.EQ) {
assignedType = rightHandSide.typeOrThrow;
- nodeType = assignedType;
} else if (operator == TokenType.QUESTION_QUESTION_EQ) {
- var leftType = node.readType!;
-
- // The LHS value will be used only if it is non-null.
- if (_isNonNullableByDefault) {
- leftType = _typeSystem.promoteToNonNull(leftType);
- }
-
assignedType = rightHandSide.typeOrThrow;
- nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
} else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
operator == TokenType.BAR_BAR_EQ) {
assignedType = _typeProvider.boolType;
- nodeType = assignedType;
} else {
var operatorElement = node.staticElement;
if (operatorElement != null) {
@@ -238,14 +253,22 @@
} else {
assignedType = DynamicTypeImpl.instance;
}
- nodeType = assignedType;
}
- _inferenceHelper.recordStaticType(node, nodeType);
- var callReference = _resolver.insertImplicitCallReference(rightHandSide);
- if (callReference != rightHandSide) {
- assignedType = callReference.typeOrThrow;
+ DartType nodeType;
+ if (operator == TokenType.QUESTION_QUESTION_EQ) {
+ var leftType = node.readType!;
+
+ // The LHS value will be used only if it is non-null.
+ if (_isNonNullableByDefault) {
+ leftType = _typeSystem.promoteToNonNull(leftType);
+ }
+
+ nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
+ } else {
+ nodeType = assignedType;
}
+ _inferenceHelper.recordStaticType(node, nodeType, contextType: contextType);
// TODO(scheglov) Remove from ErrorVerifier?
_checkForInvalidAssignment(
@@ -260,32 +283,6 @@
whyNotPromoted: whyNotPromoted);
}
}
-
- void _setRhsContext(AssignmentExpressionImpl node, DartType leftType,
- TokenType operator, Expression right) {
- switch (operator) {
- case TokenType.EQ:
- case TokenType.QUESTION_QUESTION_EQ:
- InferenceContext.setType(right, leftType);
- break;
- case TokenType.AMPERSAND_AMPERSAND_EQ:
- case TokenType.BAR_BAR_EQ:
- InferenceContext.setType(right, _typeProvider.boolType);
- break;
- default:
- var method = node.staticElement;
- if (method != null) {
- var parameters = method.parameters;
- if (parameters.isNotEmpty) {
- InferenceContext.setType(
- right,
- _typeSystem.refineNumericInvocationContext(
- leftType, method, leftType, parameters[0].type));
- }
- }
- break;
- }
- }
}
class AssignmentExpressionShared {
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
index 61f364e..0fdb8cc 100644
--- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -45,7 +45,7 @@
// Either `new` or `const` has been specified.
return node;
}
- var typeName = node.constructorName.type2.name;
+ var typeName = node.constructorName.type.name;
if (typeName is SimpleIdentifier) {
var element = nameScope.lookup(typeName.name).getter;
if (element is FunctionElement ||
@@ -525,8 +525,8 @@
required TypeAliasElement element,
}) {
var typeName = astFactory.namedType(
- name: node.constructorName.type2.name,
- typeArguments: node.constructorName.type2.typeArguments,
+ name: node.constructorName.type.name,
+ typeArguments: node.constructorName.type.typeArguments,
);
typeName.type = element.aliasedType;
typeName.name.staticType = element.aliasedType;
@@ -543,18 +543,24 @@
return methodInvocation;
}
- MethodInvocation _toMethodInvocationOfFunctionReference({
+ AstNode _toMethodInvocationOfFunctionReference({
required InstanceCreationExpression node,
required Identifier function,
}) {
+ var period = node.constructorName.period;
+ var constructorId = node.constructorName.name;
+ if (period == null || constructorId == null) {
+ return node;
+ }
+
var functionReference = astFactory.functionReference(
function: function,
- typeArguments: node.constructorName.type2.typeArguments,
+ typeArguments: node.constructorName.type.typeArguments,
);
var methodInvocation = astFactory.methodInvocation(
functionReference,
- node.constructorName.period,
- node.constructorName.name!,
+ period,
+ constructorId,
null,
node.argumentList,
);
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index ad08e2b..5e1246d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -39,31 +39,32 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(BinaryExpressionImpl node) {
+ void resolve(BinaryExpressionImpl node, {required DartType? contextType}) {
var operator = node.operator.type;
if (operator == TokenType.AMPERSAND_AMPERSAND) {
- _resolveLogicalAnd(node);
+ _resolveLogicalAnd(node, contextType: contextType);
return;
}
if (operator == TokenType.BANG_EQ || operator == TokenType.EQ_EQ) {
- _resolveEqual(node, notEqual: operator == TokenType.BANG_EQ);
+ _resolveEqual(node,
+ notEqual: operator == TokenType.BANG_EQ, contextType: contextType);
return;
}
if (operator == TokenType.BAR_BAR) {
- _resolveLogicalOr(node);
+ _resolveLogicalOr(node, contextType: contextType);
return;
}
if (operator == TokenType.QUESTION_QUESTION) {
- _resolveIfNull(node);
+ _resolveIfNull(node, contextType: contextType);
return;
}
if (operator.isUserDefinableOperator && operator.isBinaryOperator) {
- _resolveUserDefinable(node);
+ _resolveUserDefinable(node, contextType: contextType);
return;
}
@@ -75,7 +76,7 @@
[operator.lexeme]);
}
- _resolveUnsupportedOperator(node);
+ _resolveUnsupportedOperator(node, contextType: contextType);
}
/// Set the static type of [node] to be the least upper bound of the static
@@ -83,12 +84,14 @@
///
/// TODO(scheglov) this is duplicate
void _analyzeLeastUpperBoundTypes(
- ExpressionImpl node, DartType staticType1, DartType staticType2) {
+ ExpressionImpl node, DartType staticType1, DartType staticType2,
+ {required DartType? contextType}) {
var staticType = _typeSystem.getLeastUpperBound(staticType1, staticType2);
staticType = _resolver.toLegacyTypeIfOptOut(staticType);
- _inferenceHelper.recordStaticType(node, staticType);
+ _inferenceHelper.recordStaticType(node, staticType,
+ contextType: contextType);
}
void _checkNonBoolOperand(Expression operand, String operator,
@@ -101,7 +104,8 @@
);
}
- void _resolveEqual(BinaryExpressionImpl node, {required bool notEqual}) {
+ void _resolveEqual(BinaryExpressionImpl node,
+ {required bool notEqual, required DartType? contextType}) {
var left = node.leftOperand;
left.accept(_resolver);
left = node.leftOperand;
@@ -126,64 +130,63 @@
TokenType.EQ_EQ.lexeme,
promoteLeftTypeToNonNull: true,
);
- _resolveUserDefinableType(node);
+ _resolveUserDefinableType(node, contextType: contextType);
_resolver.checkForArgumentTypeNotAssignableForArgument(node.rightOperand,
promoteParameterToNullable: true, whyNotPromoted: whyNotPromoted);
}
- void _resolveIfNull(BinaryExpressionImpl node) {
+ void _resolveIfNull(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
var left = node.leftOperand;
var right = node.rightOperand;
var flow = _resolver.flowAnalysis.flow;
- var leftContextType = InferenceContext.getContext(node);
+ var leftContextType = contextType;
if (leftContextType != null && _isNonNullableByDefault) {
leftContextType = _typeSystem.makeNullable(leftContextType);
}
- InferenceContext.setType(left, leftContextType);
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, leftContextType);
left = node.leftOperand;
var leftType = left.typeOrThrow;
- var rightContextType = InferenceContext.getContext(node);
+ var rightContextType = contextType;
if (rightContextType == null || rightContextType.isDynamic) {
rightContextType = leftType;
}
- InferenceContext.setType(right, rightContextType);
flow?.ifNullExpression_rightBegin(left, leftType);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, rightContextType);
right = node.rightOperand;
flow?.ifNullExpression_end();
var rightType = right.typeOrThrow;
if (_isNonNullableByDefault) {
var promotedLeftType = _typeSystem.promoteToNonNull(leftType);
- _analyzeLeastUpperBoundTypes(node, promotedLeftType, rightType);
+ _analyzeLeastUpperBoundTypes(node, promotedLeftType, rightType,
+ contextType: contextType);
} else {
- _analyzeLeastUpperBoundTypes(node, leftType, rightType);
+ _analyzeLeastUpperBoundTypes(node, leftType, rightType,
+ contextType: contextType);
}
_resolver.checkForArgumentTypeNotAssignableForArgument(right);
}
- void _resolveLogicalAnd(BinaryExpressionImpl node) {
+ void _resolveLogicalAnd(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
var left = node.leftOperand;
var right = node.rightOperand;
var flow = _resolver.flowAnalysis.flow;
- InferenceContext.setType(left, _typeProvider.boolType);
- InferenceContext.setType(right, _typeProvider.boolType);
-
flow?.logicalBinaryOp_begin();
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, _typeProvider.boolType);
left = node.leftOperand;
var leftWhyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(left);
flow?.logicalBinaryOp_rightBegin(left, node, isAnd: true);
_resolver.checkUnreachableNode(right);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, _typeProvider.boolType);
right = node.rightOperand;
var rightWhyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(right);
@@ -194,26 +197,25 @@
_checkNonBoolOperand(left, '&&', whyNotPromoted: leftWhyNotPromoted);
_checkNonBoolOperand(right, '&&', whyNotPromoted: rightWhyNotPromoted);
- _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+ _inferenceHelper.recordStaticType(node, _typeProvider.boolType,
+ contextType: contextType);
}
- void _resolveLogicalOr(BinaryExpressionImpl node) {
+ void _resolveLogicalOr(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
var left = node.leftOperand;
var right = node.rightOperand;
var flow = _resolver.flowAnalysis.flow;
- InferenceContext.setType(left, _typeProvider.boolType);
- InferenceContext.setType(right, _typeProvider.boolType);
-
flow?.logicalBinaryOp_begin();
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, _typeProvider.boolType);
left = node.leftOperand;
var leftWhyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(left);
flow?.logicalBinaryOp_rightBegin(left, node, isAnd: false);
_resolver.checkUnreachableNode(right);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, _typeProvider.boolType);
right = node.rightOperand;
var rightWhyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(right);
@@ -224,7 +226,8 @@
_checkNonBoolOperand(left, '||', whyNotPromoted: leftWhyNotPromoted);
_checkNonBoolOperand(right, '||', whyNotPromoted: rightWhyNotPromoted);
- _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+ _inferenceHelper.recordStaticType(node, _typeProvider.boolType,
+ contextType: contextType);
}
/// If the given [type] is a type parameter, resolve it to the type that should
@@ -234,13 +237,16 @@
DartType _resolveTypeParameter(DartType type) =>
type.resolveToBound(_typeProvider.objectType);
- void _resolveUnsupportedOperator(BinaryExpressionImpl node) {
+ void _resolveUnsupportedOperator(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
node.leftOperand.accept(_resolver);
node.rightOperand.accept(_resolver);
- _inferenceHelper.recordStaticType(node, DynamicTypeImpl.instance);
+ _inferenceHelper.recordStaticType(node, DynamicTypeImpl.instance,
+ contextType: contextType);
}
- void _resolveUserDefinable(BinaryExpressionImpl node) {
+ void _resolveUserDefinable(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
var left = node.leftOperand;
var right = node.rightOperand;
@@ -251,24 +257,20 @@
_resolveUserDefinableElement(node, operator.lexeme);
var invokeType = node.staticInvokeType;
+ DartType? rightContextType;
if (invokeType != null && invokeType.parameters.isNotEmpty) {
// If this is a user-defined operator, set the right operand context
// using the operator method's parameter type.
var rightParam = invokeType.parameters[0];
- InferenceContext.setType(
- right,
- _typeSystem.refineNumericInvocationContext(
- left.staticType,
- node.staticElement,
- InferenceContext.getContext(node),
- rightParam.type));
+ rightContextType = _typeSystem.refineNumericInvocationContext(
+ left.staticType, node.staticElement, contextType, rightParam.type);
}
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, rightContextType);
right = node.rightOperand;
var whyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(right);
- _resolveUserDefinableType(node);
+ _resolveUserDefinableType(node, contextType: contextType);
_resolver.checkForArgumentTypeNotAssignableForArgument(right,
whyNotPromoted: whyNotPromoted);
}
@@ -340,7 +342,8 @@
}
}
- void _resolveUserDefinableType(BinaryExpressionImpl node) {
+ void _resolveUserDefinableType(BinaryExpressionImpl node,
+ {required DartType? contextType}) {
var leftOperand = node.leftOperand;
DartType leftType;
@@ -352,7 +355,8 @@
}
if (identical(leftType, NeverTypeImpl.instance)) {
- _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
+ _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance,
+ contextType: contextType);
return;
}
@@ -367,6 +371,7 @@
node.staticElement,
);
}
- _inferenceHelper.recordStaticType(node, staticType);
+ _inferenceHelper.recordStaticType(node, staticType,
+ contextType: contextType);
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
index 4ef8323..db7e1df 100644
--- a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
@@ -18,9 +18,10 @@
ConstructorReferenceResolver(this._resolver);
- void resolve(ConstructorReferenceImpl node) {
+ void resolve(ConstructorReferenceImpl node,
+ {required DartType? contextType}) {
if (!_resolver.isConstructorTearoffsEnabled &&
- node.constructorName.type2.typeArguments == null) {
+ node.constructorName.type.typeArguments == null) {
// Only report this if [node] has no explicit type arguments; otherwise
// the parser has already reported an error.
_resolver.errorReporter.reportErrorForNode(
@@ -49,7 +50,7 @@
//
// Only report errors when the constructor tearoff feature is enabled,
// to avoid reporting redundant errors.
- var enclosingElement = node.constructorName.type2.name.staticElement;
+ var enclosingElement = node.constructorName.type.name.staticElement;
if (enclosingElement is TypeAliasElement) {
enclosingElement = enclosingElement.aliasedType.element;
}
@@ -79,10 +80,11 @@
}
}
}
- _inferArgumentTypes(node);
+ _inferArgumentTypes(node, contextType: contextType);
}
- void _inferArgumentTypes(ConstructorReferenceImpl node) {
+ void _inferArgumentTypes(ConstructorReferenceImpl node,
+ {required DartType? contextType}) {
var constructorName = node.constructorName;
var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
constructorName: constructorName,
@@ -95,7 +97,9 @@
//
// Otherwise we'll have a ConstructorElement, and we can skip inference
// because there's nothing to infer in a non-generic type.
- if (elementToInfer != null) {
+ if (elementToInfer != null &&
+ elementToInfer.typeParameters.isNotEmpty &&
+ constructorName.type.typeArguments == null) {
// TODO(leafp): Currently, we may re-infer types here, since we
// sometimes resolve multiple times. We should really check that we
// have not already inferred something. However, the obvious ways to
@@ -110,7 +114,8 @@
var constructorType = elementToInfer.asType;
var inferred = _resolver.inferenceHelper.inferTearOff(
- node, constructorName.name!, constructorType) as FunctionType?;
+ node, constructorName.name!, constructorType,
+ contextType: contextType) as FunctionType?;
if (inferred != null) {
var inferredReturnType = inferred.returnType as InterfaceType;
@@ -124,7 +129,7 @@
constructorName.name?.staticElement = constructorElement.declaration;
node.staticType = inferred;
// The NamedType child of `constructorName` doesn't have a static type.
- constructorName.type2.type = null;
+ constructorName.type.type = null;
}
} else {
var constructorElement = constructorName.staticElement;
@@ -134,7 +139,7 @@
node.staticType = constructorElement.type;
}
// The NamedType child of `constructorName` doesn't have a static type.
- constructorName.type2.type = null;
+ constructorName.type.type = null;
}
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index 517ff5c..15862ca 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -42,6 +42,41 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
+ /// Set the type context for the receiver of the override.
+ ///
+ /// The context of the invocation that is made through the override does
+ /// not affect the type inference of the override and the receiver.
+ DartType? computeOverrideReceiverContextType(ExtensionOverride node) {
+ var element = node.staticElement!;
+ var typeParameters = element.typeParameters;
+
+ var arguments = node.argumentList.arguments;
+ if (arguments.length != 1) {
+ return null;
+ }
+
+ List<DartType> typeArgumentTypes;
+ var typeArguments = node.typeArguments;
+ if (typeArguments != null) {
+ var arguments = typeArguments.arguments;
+ if (arguments.length == typeParameters.length) {
+ typeArgumentTypes = arguments.map((a) => a.typeOrThrow).toList();
+ } else {
+ typeArgumentTypes = _listOfDynamic(typeParameters);
+ }
+ } else {
+ typeArgumentTypes = List.filled(
+ typeParameters.length,
+ UnknownInferredType.instance,
+ );
+ }
+
+ return Substitution.fromPairs(
+ typeParameters,
+ typeArgumentTypes,
+ ).substituteType(element.extendedType);
+ }
+
/// Return the most specific extension in the current scope for this [type],
/// that defines the member with the given [name].
///
@@ -203,44 +238,6 @@
}
}
- /// Set the type context for the receiver of the override.
- ///
- /// The context of the invocation that is made through the override does
- /// not affect the type inference of the override and the receiver.
- void setOverrideReceiverContextType(ExtensionOverride node) {
- var element = node.staticElement!;
- var typeParameters = element.typeParameters;
-
- var arguments = node.argumentList.arguments;
- if (arguments.length != 1) {
- return;
- }
-
- List<DartType> typeArgumentTypes;
- var typeArguments = node.typeArguments;
- if (typeArguments != null) {
- var arguments = typeArguments.arguments;
- if (arguments.length == typeParameters.length) {
- typeArgumentTypes = arguments.map((a) => a.typeOrThrow).toList();
- } else {
- typeArgumentTypes = _listOfDynamic(typeParameters);
- }
- } else {
- typeArgumentTypes = List.filled(
- typeParameters.length,
- UnknownInferredType.instance,
- );
- }
-
- var extendedForDownward = Substitution.fromPairs(
- typeParameters,
- typeArgumentTypes,
- ).substituteType(element.extendedType);
-
- var receiver = arguments[0];
- InferenceContext.setType(receiver, extendedForDownward);
- }
-
void _checkTypeArgumentsMatchingBounds(
List<TypeParameterElement> typeParameters,
TypeArgumentList? typeArgumentList,
@@ -254,6 +251,7 @@
var parameterBound = parameter.bound;
if (parameterBound != null) {
parameterBound = substitution.substituteType(parameterBound);
+ parameterBound = _typeSystem.toLegacyTypeIfOptOut(parameterBound);
if (!_typeSystem.isSubtypeOf(argument, parameterBound)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index d243983..dceec2d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
+import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -21,12 +22,16 @@
required ResolverVisitor resolver,
}) : _resolver = resolver;
- void resolveElement(ForElementImpl node) {
+ void resolveElement(ForElementImpl node, CollectionLiteralContext? context) {
var forLoopParts = node.forLoopParts;
+ void visitBody() {
+ node.body.resolveElement(_resolver, context);
+ }
+
if (forLoopParts is ForPartsImpl) {
- _forParts(node, forLoopParts, node.body);
+ _forParts(node, forLoopParts, visitBody);
} else if (forLoopParts is ForEachPartsImpl) {
- _forEachParts(node, node.awaitKeyword != null, forLoopParts, node.body);
+ _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
}
}
@@ -34,10 +39,14 @@
_resolver.checkUnreachableNode(node);
var forLoopParts = node.forLoopParts;
+ void visitBody() {
+ node.body.accept(_resolver);
+ }
+
if (forLoopParts is ForPartsImpl) {
- _forParts(node, forLoopParts, node.body);
+ _forParts(node, forLoopParts, visitBody);
} else if (forLoopParts is ForEachPartsImpl) {
- _forEachParts(node, node.awaitKeyword != null, forLoopParts, node.body);
+ _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
}
}
@@ -66,12 +75,8 @@
}
}
- void _forEachParts(
- AstNode node,
- bool isAsync,
- ForEachParts forEachParts,
- AstNode body,
- ) {
+ void _forEachParts(AstNode node, bool isAsync, ForEachParts forEachParts,
+ void Function() visitBody) {
Expression iterable = forEachParts.iterable;
DeclaredIdentifier? loopVariable;
SimpleIdentifier? identifier;
@@ -104,14 +109,14 @@
}
}
}
+ InterfaceType? targetType;
if (valueType != null) {
- InterfaceType targetType = isAsync
+ targetType = isAsync
? _resolver.typeProvider.streamType(valueType)
: _resolver.typeProvider.iterableType(valueType);
- InferenceContext.setType(iterable, targetType);
}
- iterable.accept(_resolver);
+ _resolver.analyzeExpression(iterable, targetType);
iterable = forEachParts.iterable;
_resolver.nullableDereferenceVerifier.expression(
@@ -140,12 +145,12 @@
elementType ?? DynamicTypeImpl.instance, null);
}
- body.accept(_resolver);
+ visitBody();
_resolver.flowAnalysis.flow?.forEach_end();
}
- void _forParts(AstNode node, ForParts forParts, AstNode body) {
+ void _forParts(AstNode node, ForParts forParts, void Function() visitBody) {
if (forParts is ForPartsWithDeclarations) {
forParts.variables.accept(_resolver);
} else if (forParts is ForPartsWithExpression) {
@@ -156,8 +161,7 @@
var condition = forParts.condition;
if (condition != null) {
- InferenceContext.setType(condition, _resolver.typeProvider.boolType);
- condition.accept(_resolver);
+ _resolver.analyzeExpression(condition, _resolver.typeProvider.boolType);
condition = forParts.condition!;
var whyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(condition);
@@ -166,7 +170,7 @@
}
_resolver.flowAnalysis.for_bodyBegin(node, condition);
- body.accept(_resolver);
+ visitBody();
_resolver.flowAnalysis.flow?.for_updaterBegin();
forParts.updaters.accept(_resolver);
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 42070dc..ddbdfdb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
@@ -36,11 +37,13 @@
_resolver.nullableDereferenceVerifier;
void resolve(FunctionExpressionInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var function = node.function;
if (function is ExtensionOverrideImpl) {
- _resolveReceiverExtensionOverride(node, function, whyNotPromotedList);
+ _resolveReceiverExtensionOverride(node, function, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -51,12 +54,14 @@
// `_resolveReceiverInterfaceType` calls `TypePropertyResolver.resolve`,
// which does the necessary null checking.
_resolveReceiverInterfaceType(
- node, function, receiverType, whyNotPromotedList);
+ node, function, receiverType, whyNotPromotedList,
+ contextType: contextType);
return;
}
if (_checkForUseOfVoidResult(function, receiverType)) {
- _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -66,18 +71,21 @@
);
if (receiverType is FunctionType) {
- _resolve(node, receiverType, whyNotPromotedList);
+ _resolve(node, receiverType, whyNotPromotedList,
+ contextType: contextType);
return;
}
if (identical(receiverType, NeverTypeImpl.instance)) {
_errorReporter.reportErrorForNode(
HintCode.RECEIVER_OF_TYPE_NEVER, function);
- _unresolved(node, NeverTypeImpl.instance, whyNotPromotedList);
+ _unresolved(node, NeverTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
return;
}
- _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
}
/// Check for situations where the result of a method or function is used,
@@ -105,30 +113,24 @@
}
void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _inferenceHelper.resolveFunctionExpressionInvocation(
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
+ var returnType =
+ const FunctionExpressionInvocationInferrer().resolveInvocation(
+ resolver: _resolver,
node: node,
rawType: rawType,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
- var returnType = _inferenceHelper.computeInvokeReturnType(
- node.staticInvokeType,
- );
- _inferenceHelper.recordStaticType(node, returnType);
+ _inferenceHelper.recordStaticType(node, returnType,
+ contextType: contextType);
}
- void _resolveArguments(FunctionExpressionInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _resolver.visitArgumentList(node.argumentList,
- whyNotPromotedList: whyNotPromotedList);
- }
-
- void _resolveReceiverExtensionOverride(
- FunctionExpressionInvocationImpl node,
- ExtensionOverride function,
- List<WhyNotPromotedGetter> whyNotPromotedList,
- ) {
+ void _resolveReceiverExtensionOverride(FunctionExpressionInvocationImpl node,
+ ExtensionOverride function, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var result = _extensionResolver.getOverrideMember(
function,
FunctionElement.CALL_METHOD_NAME,
@@ -142,7 +144,8 @@
function,
[function.extensionName.name],
);
- return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+ return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
}
if (callElement.isStatic) {
@@ -153,15 +156,15 @@
}
var rawType = callElement.type;
- _resolve(node, rawType, whyNotPromotedList);
+ _resolve(node, rawType, whyNotPromotedList, contextType: contextType);
}
void _resolveReceiverInterfaceType(
- FunctionExpressionInvocationImpl node,
- Expression function,
- InterfaceType receiverType,
- List<WhyNotPromotedGetter> whyNotPromotedList,
- ) {
+ FunctionExpressionInvocationImpl node,
+ Expression function,
+ InterfaceType receiverType,
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var result = _typePropertyResolver.resolve(
receiver: function,
receiverType: receiverType,
@@ -178,7 +181,8 @@
function,
);
}
- _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -187,19 +191,26 @@
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
function,
);
- _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+ contextType: contextType);
return;
}
node.staticElement = callElement;
var rawType = callElement.type;
- _resolve(node, rawType, whyNotPromotedList);
+ _resolve(node, rawType, whyNotPromotedList, contextType: contextType);
}
void _unresolved(FunctionExpressionInvocationImpl node, DartType type,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
_setExplicitTypeArgumentTypes(node);
- _resolveArguments(node, whyNotPromotedList);
+ const FunctionExpressionInvocationInferrer().resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: null,
+ contextType: contextType,
+ whyNotPromotedList: whyNotPromotedList);
node.staticInvokeType = DynamicTypeImpl.instance;
node.staticType = type;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index 2558708..bcddf19 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -30,7 +30,7 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(FunctionExpressionImpl node) {
+ void resolve(FunctionExpressionImpl node, {required DartType? contextType}) {
var parent = node.parent;
// Note: `isFunctionDeclaration` must have an explicit type to work around
// https://github.com/dart-lang/language/issues/1785.
@@ -42,25 +42,32 @@
.executableDeclaration_enter(node, node.parameters, true);
}
- var contextType = InferenceContext.getContext(node);
- if (contextType is FunctionType) {
- contextType = _matchTypeParameters(
+ bool wasFunctionTypeSupplied = contextType is FunctionType;
+ node.wasFunctionTypeSupplied = wasFunctionTypeSupplied;
+ DartType? imposedType;
+ if (wasFunctionTypeSupplied) {
+ var instantiatedType = _matchTypeParameters(
node.typeParameters,
contextType,
);
- if (contextType is FunctionType) {
- _inferFormalParameters(node.parameters, contextType);
- InferenceContext.setType(body, contextType.returnType);
+ if (instantiatedType is FunctionType) {
+ _inferFormalParameters(node.parameters, instantiatedType);
+ var returnType = instantiatedType.returnType;
+ if (!returnType.isDynamic) {
+ imposedType = returnType;
+ }
}
}
- node.visitChildren(_resolver);
+ node.typeParameters?.accept(_resolver);
+ node.parameters?.accept(_resolver);
+ imposedType = node.body.resolve(_resolver, imposedType);
if (isFunctionDeclaration) {
// A side effect of visiting the children is that the parameters are now
// in scope, so we can visit the documentation comment now.
parent.documentationComment?.accept(_resolver);
}
- _resolve2(node);
+ _resolve2(node, imposedType, contextType: contextType);
if (_resolver.flowAnalysis.flow != null && !isFunctionDeclaration) {
_resolver.checkForBodyMayCompleteNormally(
@@ -135,13 +142,6 @@
}
}
- /// Infers the return type of a local function, either a lambda or
- /// (in strong mode) a local function declaration.
- DartType _inferLocalFunctionReturnType(FunctionExpression node) {
- var body = node.body;
- return InferenceContext.getContext(body) ?? DynamicTypeImpl.instance;
- }
-
/// Given the downward inference [type], return the function type expressed
/// in terms of the type parameters from [typeParameterList].
///
@@ -168,15 +168,16 @@
}).toList());
}
- void _resolve2(FunctionExpressionImpl node) {
+ void _resolve2(FunctionExpressionImpl node, DartType? imposedType,
+ {required DartType? contextType}) {
var functionElement = node.declaredElement as ExecutableElementImpl;
if (_shouldUpdateReturnType(node)) {
- var returnType = _inferLocalFunctionReturnType(node);
- functionElement.returnType = returnType;
+ functionElement.returnType = imposedType ?? DynamicTypeImpl.instance;
}
- _inferenceHelper.recordStaticType(node, functionElement.type);
+ _inferenceHelper.recordStaticType(node, functionElement.type,
+ contextType: contextType);
}
static bool _shouldUpdateReturnType(FunctionExpression node) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index dedb7b5..0aa5a1e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -65,7 +65,7 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
typeArguments,
[
- function.constructorName.type2.name.toSource(),
+ function.constructorName.type.name.toSource(),
function.constructorName.name!.name
],
);
@@ -453,22 +453,26 @@
return;
}
- var functionType = _resolveTypeProperty(
+ var propertyType = _resolveTypeProperty(
receiver: function.prefix,
name: function.identifier,
nameErrorEntity: function,
);
- if (functionType != null) {
- if (functionType is FunctionType) {
- function.staticType = functionType;
- _resolve(
- node: node,
- rawType: functionType,
- name: functionName,
- );
- return;
- }
+ var callMethod = _getCallMethod(node, propertyType);
+ if (callMethod is MethodElement) {
+ _resolveAsImplicitCallReference(node, callMethod);
+ return;
+ }
+
+ if (propertyType is FunctionType) {
+ function.staticType = propertyType;
+ _resolve(
+ node: node,
+ rawType: propertyType,
+ name: functionName,
+ );
+ return;
}
function.accept(_resolver);
@@ -521,23 +525,20 @@
nameErrorEntity: function,
);
- if (functionType == null) {
+ if (functionType is FunctionType) {
+ function.staticType = functionType;
+ _resolve(
+ node: node,
+ rawType: functionType,
+ name: function.propertyName.name,
+ );
+ } else {
// The target is known, but the method is not; [UNDEFINED_GETTER] is
// reported elsewhere.
node.staticType = DynamicTypeImpl.instance;
- return;
- } else {
- if (functionType is FunctionType) {
- function.staticType = functionType;
- _resolve(
- node: node,
- rawType: functionType,
- name: function.propertyName.name,
- );
- }
-
- return;
}
+
+ return;
}
var propertyElement = _resolver.typePropertyResolver
@@ -826,17 +827,13 @@
if (receiverElement is ClassElement) {
var element = _resolveStaticElement(receiverElement, name);
name.staticElement = element;
- // TODO(srawlins): Should this use referenceType? E.g. if `element`
- // is a function-typed static getter.
- return element?.type;
+ return element?.referenceType;
} else if (receiverElement is TypeAliasElement) {
var aliasedType = receiverElement.aliasedType;
if (aliasedType is InterfaceType) {
var element = _resolveStaticElement(aliasedType.element, name);
name.staticElement = element;
- // TODO(srawlins): Should this use referenceType? E.g. if `element`
- // is a function-typed static getter.
- return element?.type;
+ return element?.referenceType;
} else {
return null;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
index 625037b..bfdf73f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -5,7 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/generated/resolver.dart';
/// A resolver for [InstanceCreationExpression] nodes.
@@ -20,7 +20,8 @@
InstanceCreationExpressionResolver(this._resolver);
- void resolve(InstanceCreationExpressionImpl node) {
+ void resolve(InstanceCreationExpressionImpl node,
+ {required DartType? contextType}) {
// The parser can parse certain code as [InstanceCreationExpression] when it
// might be an invocation of a method on a [FunctionReference] or
// [ConstructorReference]. In such a case, it is this resolver's
@@ -36,92 +37,40 @@
// InstanceCreationExpression needs to be rewritten as a MethodInvocation
// with a target of `a.m<int>` (a FunctionReference) and a name of `apply`.
if (node.keyword == null) {
- var typeNameTypeArguments = node.constructorName.type2.typeArguments;
+ var typeNameTypeArguments = node.constructorName.type.typeArguments;
if (typeNameTypeArguments != null) {
// This could be a method call on a function reference or a constructor
// reference.
- _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments);
+ _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments,
+ contextType: contextType);
return;
}
}
- _resolveInstanceCreationExpression(node);
+ _resolveInstanceCreationExpression(node, contextType: contextType);
}
- void _inferArgumentTypes(covariant InstanceCreationExpressionImpl node) {
+ void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node,
+ {required DartType? contextType}) {
+ var whyNotPromotedList = <WhyNotPromotedGetter>[];
var constructorName = node.constructorName;
- var typeName = constructorName.type2;
- var typeArguments = typeName.typeArguments;
+ constructorName.accept(_resolver);
+ // Re-assign constructorName in case the node got replaced.
+ constructorName = node.constructorName;
+ _resolver.elementResolver.visitInstanceCreationExpression(node);
var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
constructorName: constructorName,
definingLibrary: _resolver.definingLibrary,
);
- FunctionType? inferred;
-
- // If the constructor is generic, we'll have a ConstructorMember that
- // substitutes in type arguments (possibly `dynamic`) from earlier in
- // resolution.
- //
- // Otherwise we'll have a ConstructorElement, and we can skip inference
- // because there's nothing to infer in a non-generic type.
- if (elementToInfer != null) {
- // TODO(leafp): Currently, we may re-infer types here, since we
- // sometimes resolve multiple times. We should really check that we
- // have not already inferred something. However, the obvious ways to
- // check this don't work, since we may have been instantiated
- // to bounds in an earlier phase, and we *do* want to do inference
- // in that case.
-
- // Get back to the uninstantiated generic constructor.
- // TODO(jmesserly): should we store this earlier in resolution?
- // Or look it up, instead of jumping backwards through the Member?
- var rawElement = elementToInfer.element;
- var constructorType = elementToInfer.asType;
-
- inferred = _resolver.inferenceHelper.inferArgumentTypesForGeneric(
- node, constructorType, typeArguments,
- isConst: node.isConst, errorNode: node.constructorName);
-
- if (inferred != null) {
- var arguments = node.argumentList;
- InferenceContext.setType(arguments, inferred);
- // Fix up the parameter elements based on inferred method.
- arguments.correspondingStaticParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- argumentList: arguments,
- parameters: inferred.parameters,
- );
-
- constructorName.type2.type = inferred.returnType;
-
- // Update the static element as well. This is used in some cases, such
- // as computing constant values. It is stored in two places.
- var constructorElement = ConstructorMember.from(
- rawElement,
- inferred.returnType as InterfaceType,
- );
- constructorName.staticElement = constructorElement;
- }
- }
-
- if (inferred == null) {
- var constructorElement = constructorName.staticElement;
- if (constructorElement != null) {
- var type = constructorElement.type;
- type = _resolver.toLegacyTypeIfOptOut(type) as FunctionType;
- InferenceContext.setType(node.argumentList, type);
- }
- }
- }
-
- void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node) {
- var whyNotPromotedList = <WhyNotPromotedGetter>[];
- node.constructorName.accept(_resolver);
- _inferArgumentTypes(node);
- _resolver.visitArgumentList(node.argumentList,
+ const InstanceCreationInferrer().resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: elementToInfer?.asType,
+ contextType: contextType,
whyNotPromotedList: whyNotPromotedList);
- _resolver.elementResolver.visitInstanceCreationExpression(node);
- _resolver.typeAnalyzer.visitInstanceCreationExpression(node);
+ _resolver.inferenceHelper.recordStaticType(
+ node, node.constructorName.type.type!,
+ contextType: contextType);
_resolver.checkForArgumentTypesNotAssignableInList(
node.argumentList, whyNotPromotedList);
}
@@ -132,23 +81,23 @@
/// The instance creation expression may actually be a method call on a
/// type-instantiated function reference or constructor reference.
void _resolveWithTypeNameWithTypeArguments(
- InstanceCreationExpressionImpl node,
- TypeArgumentListImpl typeNameTypeArguments,
- ) {
- var typeNameName = node.constructorName.type2.name;
+ InstanceCreationExpressionImpl node,
+ TypeArgumentListImpl typeNameTypeArguments,
+ {required DartType? contextType}) {
+ var typeNameName = node.constructorName.type.name;
if (typeNameName is SimpleIdentifierImpl) {
// TODO(srawlins): Lookup the name and potentially rewrite `node` as a
// [MethodInvocation].
- _resolveInstanceCreationExpression(node);
+ _resolveInstanceCreationExpression(node, contextType: contextType);
return;
} else if (typeNameName is PrefixedIdentifierImpl) {
// TODO(srawlins): Lookup the name and potentially rewrite `node` as a
// [MethodInvocation].
- _resolveInstanceCreationExpression(node);
+ _resolveInstanceCreationExpression(node, contextType: contextType);
} else {
assert(
false, 'Unexpected typeNameName type: ${typeNameName.runtimeType}');
- _resolveInstanceCreationExpression(node);
+ _resolveInstanceCreationExpression(node, contextType: contextType);
}
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 765d3d5..945c794 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -9,12 +9,10 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -46,12 +44,15 @@
/// For example given the type `class C<T> { C(T arg); }`, the generic
/// function type is `<T>(T) -> C<T>`.
FunctionType get asType {
- return FunctionTypeImpl(
- typeFormals: typeParameters,
- parameters: element.parameters,
- returnType: element.returnType,
- nullabilitySuffix: NullabilitySuffix.none,
- );
+ var typeParameters = this.typeParameters;
+ return typeParameters.isEmpty
+ ? element.type
+ : FunctionTypeImpl(
+ typeFormals: typeParameters,
+ parameters: element.parameters,
+ returnType: element.returnType,
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
}
}
@@ -62,9 +63,6 @@
final MigrationResolutionHooks? _migrationResolutionHooks;
final bool _genericMetadataIsEnabled;
- List<DartType>? _typeArgumentTypes;
- FunctionType? _invokeType;
-
InvocationInferenceHelper({
required ResolverVisitor resolver,
required ErrorReporter errorReporter,
@@ -77,16 +75,6 @@
_genericMetadataIsEnabled = resolver.definingLibrary.featureSet
.isEnabled(Feature.generic_metadata);
- /// Compute the return type of the method or function represented by the given
- /// type that is being invoked.
- DartType computeInvokeReturnType(DartType? type) {
- if (type is FunctionType) {
- return type.returnType;
- } else {
- return DynamicTypeImpl.instance;
- }
- }
-
/// If the constructor referenced by the [constructorName] is generic,
/// and the [constructorName] does not have explicit type arguments,
/// return the element and type parameters to infer. Otherwise return `null`.
@@ -94,169 +82,53 @@
required ConstructorName constructorName,
required LibraryElement definingLibrary,
}) {
- List<TypeParameterElement>? typeParameters;
+ List<TypeParameterElement> typeParameters;
ConstructorElement? rawElement;
- var typeName = constructorName.type2;
- var typeArguments = typeName.typeArguments;
+ var typeName = constructorName.type;
var typeElement = typeName.name.staticElement;
if (typeElement is ClassElement) {
typeParameters = typeElement.typeParameters;
- if (typeParameters.isNotEmpty && typeArguments == null) {
- var constructorIdentifier = constructorName.name;
- if (constructorIdentifier == null) {
- rawElement = typeElement.unnamedConstructor;
- } else {
- var name = constructorIdentifier.name;
- rawElement = typeElement.getNamedConstructor(name);
- if (rawElement != null &&
- !rawElement.isAccessibleIn(definingLibrary)) {
- rawElement = null;
- }
+ var constructorIdentifier = constructorName.name;
+ if (constructorIdentifier == null) {
+ rawElement = typeElement.unnamedConstructor;
+ } else {
+ var name = constructorIdentifier.name;
+ rawElement = typeElement.getNamedConstructor(name);
+ if (rawElement != null && !rawElement.isAccessibleIn(definingLibrary)) {
+ rawElement = null;
}
}
} else if (typeElement is TypeAliasElement) {
typeParameters = typeElement.typeParameters;
var aliasedType = typeElement.aliasedType;
if (aliasedType is InterfaceType) {
- if (typeParameters.isNotEmpty && typeArguments == null) {
- var constructorIdentifier = constructorName.name;
- rawElement = aliasedType.lookUpConstructor(
- constructorIdentifier?.name,
- definingLibrary,
- );
- }
+ var constructorIdentifier = constructorName.name;
+ rawElement = aliasedType.lookUpConstructor(
+ constructorIdentifier?.name,
+ definingLibrary,
+ );
}
+ } else {
+ return null;
}
- if (typeParameters == null || rawElement == null) {
+ if (rawElement == null) {
return null;
}
rawElement = _resolver.toLegacyElement(rawElement);
return ConstructorElementToInfer(typeParameters, rawElement);
}
- FunctionType? inferArgumentTypesForGeneric(AstNode inferenceNode,
- DartType? uninstantiatedType, TypeArgumentList? typeArguments,
- {AstNode? errorNode, bool isConst = false}) {
- errorNode ??= inferenceNode;
- uninstantiatedType = _getFreshType(uninstantiatedType);
- if (typeArguments == null &&
- uninstantiatedType is FunctionType &&
- uninstantiatedType.typeFormals.isNotEmpty) {
- var typeArguments = _typeSystem.inferGenericFunctionOrType(
- typeParameters: uninstantiatedType.typeFormals,
- parameters: const <ParameterElement>[],
- declaredReturnType: uninstantiatedType.returnType,
- argumentTypes: const <DartType>[],
- contextReturnType: InferenceContext.getContext(inferenceNode),
- downwards: true,
- isConst: isConst,
- errorReporter: _errorReporter,
- errorNode: errorNode,
- genericMetadataIsEnabled: _genericMetadataIsEnabled,
- );
- if (typeArguments != null) {
- return uninstantiatedType.instantiate(typeArguments);
- }
- }
- return null;
- }
-
- void inferArgumentTypesForInvocation(
- InvocationExpression node,
- DartType? type,
- ) {
- var inferred = inferArgumentTypesForGeneric(node, type, node.typeArguments);
- InferenceContext.setType(
- node.argumentList, inferred ?? node.staticInvokeType);
- }
-
- /// Given a possibly generic invocation like `o.m(args)` or `(f)(args)` try to
- /// infer the instantiated generic function type.
- ///
- /// This takes into account both the context type, as well as information from
- /// the argument types.
- void inferGenericInvocationExpression(
- InvocationExpressionImpl node,
- DartType? type,
- ) {
- var arguments = node.argumentList;
- var freshType = _getFreshType(type);
-
- var inferred = inferGenericInvoke(
- node, freshType, node.typeArguments, arguments, node.function);
- if (inferred != null && inferred != node.staticInvokeType) {
- // Fix up the parameter elements based on inferred method.
- arguments.correspondingStaticParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- argumentList: arguments,
- parameters: inferred.parameters,
- );
- node.staticInvokeType = inferred;
- }
- }
-
- /// Given a possibly generic invocation or instance creation, such as
- /// `o.m(args)` or `(f)(args)` or `new T(args)` try to infer the instantiated
- /// generic function type.
- ///
- /// This takes into account both the context type, as well as information from
- /// the argument types.
- FunctionType? inferGenericInvoke(
- AstNode node,
- DartType? fnType,
- TypeArgumentList? typeArguments,
- ArgumentList argumentList,
- AstNode errorNode,
- {bool isConst = false}) {
- if (typeArguments == null &&
- fnType is FunctionType &&
- fnType.typeFormals.isNotEmpty) {
- // Get the parameters that correspond to the uninstantiated generic.
- var typeArgs = _inferUpwards(
- rawType: fnType,
- argumentList: argumentList,
- contextType: InferenceContext.getContext(node),
- isConst: isConst,
- errorNode: errorNode,
- );
- if (node is InvocationExpressionImpl) {
- node.typeArgumentTypes = typeArgs;
- }
- if (typeArgs != null) {
- return fnType.instantiate(typeArgs);
- }
- return fnType;
- }
-
- // There is currently no other place where we set type arguments
- // for FunctionExpressionInvocation(s), so set it here, if not inferred.
- if (node is FunctionExpressionInvocationImpl) {
- if (typeArguments != null) {
- var typeArgs =
- typeArguments.arguments.map((n) => n.typeOrThrow).toList();
- node.typeArgumentTypes = typeArgs;
- } else {
- node.typeArgumentTypes = const <DartType>[];
- }
- }
-
- return null;
- }
-
/// Given an uninstantiated generic function type, referenced by the
/// [identifier] in the tear-off [expression], try to infer the instantiated
/// generic function type from the surrounding context.
- DartType inferTearOff(
- Expression expression,
- SimpleIdentifierImpl identifier,
- DartType tearOffType,
- ) {
- var context = InferenceContext.getContext(expression);
- if (context is FunctionType && tearOffType is FunctionType) {
+ DartType inferTearOff(Expression expression, SimpleIdentifierImpl identifier,
+ DartType tearOffType,
+ {required DartType? contextType}) {
+ if (contextType is FunctionType && tearOffType is FunctionType) {
var typeArguments = _typeSystem.inferFunctionTypeInstantiation(
- context,
+ contextType,
tearOffType,
errorReporter: _errorReporter,
errorNode: expression,
@@ -274,11 +146,11 @@
///
/// @param expression the node whose type is to be recorded
/// @param type the static type of the node
- void recordStaticType(ExpressionImpl expression, DartType type) {
+ void recordStaticType(ExpressionImpl expression, DartType type,
+ {required DartType? contextType}) {
var hooks = _migrationResolutionHooks;
if (hooks != null) {
- type = hooks.modifyExpressionType(
- expression, type, InferenceContext.getContext(expression));
+ type = hooks.modifyExpressionType(expression, type, contextType);
}
expression.staticType = type;
@@ -287,30 +159,6 @@
}
}
- /// Finish resolution of the [FunctionExpressionInvocation].
- ///
- /// We have already found the invoked [ExecutableElement], and the [rawType]
- /// is its not yet instantiated type. Here we perform downwards inference,
- /// resolution of arguments, and upwards inference.
- void resolveFunctionExpressionInvocation({
- required FunctionExpressionInvocationImpl node,
- required FunctionType rawType,
- required List<WhyNotPromotedGetter> whyNotPromotedList,
- }) {
- _resolveInvocation(
- rawType: rawType,
- typeArgumentList: node.typeArguments,
- argumentList: node.argumentList,
- contextType: InferenceContext.getContext(node),
- isConst: false,
- errorNode: node.function,
- whyNotPromotedList: whyNotPromotedList,
- );
-
- node.typeArgumentTypes = _typeArgumentTypes;
- node.staticInvokeType = _invokeType;
- }
-
/// Finish resolution of the [MethodInvocation].
///
/// We have already found the invoked [ExecutableElement], and the [rawType]
@@ -320,239 +168,16 @@
required MethodInvocationImpl node,
required FunctionType rawType,
required List<WhyNotPromotedGetter> whyNotPromotedList,
+ required DartType? contextType,
}) {
- _resolveInvocation(
+ var returnType = MethodInvocationInferrer.forNode(node).resolveInvocation(
+ resolver: _resolver,
+ node: node,
rawType: rawType,
- typeArgumentList: node.typeArguments,
- argumentList: node.argumentList,
- contextType: InferenceContext.getContext(node),
- isConst: false,
- errorNode: node.function,
+ contextType: contextType,
whyNotPromotedList: whyNotPromotedList,
);
- node.typeArgumentTypes = _typeArgumentTypes;
- node.staticInvokeType = _invokeType;
-
- var returnType = computeInvokeReturnType(_invokeType);
- var targetType = node.realTarget?.staticType;
- if (targetType != null) {
- returnType = _typeSystem.refineNumericInvocationType(
- targetType,
- node.methodName.staticElement,
- [
- for (var argument in node.argumentList.arguments) argument.typeOrThrow
- ],
- returnType,
- );
- }
- recordStaticType(node, returnType);
- }
-
- List<DartType>? _inferDownwards({
- required FunctionType rawType,
- required DartType? contextType,
- required bool isConst,
- required AstNode errorNode,
- }) {
- return _typeSystem.inferGenericFunctionOrType(
- typeParameters: rawType.typeFormals,
- parameters: const <ParameterElement>[],
- declaredReturnType: rawType.returnType,
- argumentTypes: const <DartType>[],
- contextReturnType: contextType,
- downwards: true,
- isConst: isConst,
- errorReporter: _errorReporter,
- errorNode: errorNode,
- genericMetadataIsEnabled: _genericMetadataIsEnabled,
- );
- }
-
- /// TODO(scheglov) Instead of [isConst] sanitize [contextType] before calling.
- List<DartType>? _inferUpwards({
- required FunctionType rawType,
- required DartType? contextType,
- required ArgumentList argumentList,
- required bool isConst,
- required AstNode errorNode,
- }) {
- rawType = _getFreshType(rawType) as FunctionType;
-
- // Get the parameters that correspond to the uninstantiated generic.
- List<ParameterElement?> rawParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- argumentList: argumentList,
- parameters: rawType.parameters,
- );
-
- List<ParameterElement> params = <ParameterElement>[];
- List<DartType> argTypes = <DartType>[];
- for (int i = 0, length = rawParameters.length; i < length; i++) {
- ParameterElement? parameter = rawParameters[i];
- if (parameter != null) {
- params.add(parameter);
- argTypes.add(argumentList.arguments[i].typeOrThrow);
- }
- }
- var typeArgs = _typeSystem.inferGenericFunctionOrType(
- typeParameters: rawType.typeFormals,
- parameters: params,
- declaredReturnType: rawType.returnType,
- argumentTypes: argTypes,
- contextReturnType: contextType,
- isConst: isConst,
- errorReporter: _errorReporter,
- errorNode: errorNode,
- genericMetadataIsEnabled: _genericMetadataIsEnabled,
- );
- return typeArgs;
- }
-
- bool _isCallToIdentical(AstNode? invocation) {
- if (invocation is MethodInvocation) {
- var invokedMethod = invocation.methodName.staticElement;
- return invokedMethod != null &&
- invokedMethod.name == 'identical' &&
- invokedMethod.library!.isDartCore;
- }
- return false;
- }
-
- void _resolveArguments(ArgumentList argumentList,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _resolver.visitArgumentList(argumentList,
- isIdentical: _isCallToIdentical(argumentList.parent),
- whyNotPromotedList: whyNotPromotedList);
- }
-
- void _resolveInvocation({
- required FunctionType rawType,
- required DartType? contextType,
- required TypeArgumentList? typeArgumentList,
- required ArgumentListImpl argumentList,
- required bool isConst,
- required AstNode errorNode,
- required List<WhyNotPromotedGetter> whyNotPromotedList,
- }) {
- if (typeArgumentList != null) {
- _resolveInvocationWithTypeArguments(
- rawType: rawType,
- typeArgumentList: typeArgumentList,
- argumentList: argumentList,
- whyNotPromotedList: whyNotPromotedList,
- );
- } else {
- _resolveInvocationWithoutTypeArguments(
- rawType: rawType,
- contextType: contextType,
- argumentList: argumentList,
- isConst: isConst,
- errorNode: errorNode,
- whyNotPromotedList: whyNotPromotedList,
- );
- }
- _setCorrespondingParameters(argumentList, _invokeType!);
- }
-
- void _resolveInvocationWithoutTypeArguments({
- required FunctionType rawType,
- required DartType? contextType,
- required ArgumentList argumentList,
- required bool isConst,
- required AstNode errorNode,
- required List<WhyNotPromotedGetter> whyNotPromotedList,
- }) {
- var typeParameters = rawType.typeFormals;
-
- if (typeParameters.isEmpty) {
- InferenceContext.setType(argumentList, rawType);
- _resolveArguments(argumentList, whyNotPromotedList);
-
- _typeArgumentTypes = const <DartType>[];
- _invokeType = rawType;
- } else {
- rawType = _getFreshType(rawType) as FunctionType;
-
- var downwardsTypeArguments = _inferDownwards(
- rawType: rawType,
- contextType: contextType,
- isConst: isConst,
- errorNode: errorNode,
- )!;
-
- var downwardsInvokeType = rawType.instantiate(downwardsTypeArguments);
- InferenceContext.setType(argumentList, downwardsInvokeType);
-
- _resolveArguments(argumentList, whyNotPromotedList);
-
- _typeArgumentTypes = _inferUpwards(
- rawType: rawType,
- argumentList: argumentList,
- contextType: contextType,
- isConst: isConst,
- errorNode: errorNode,
- );
- _invokeType = rawType.instantiate(_typeArgumentTypes!);
- }
- }
-
- void _resolveInvocationWithTypeArguments({
- required FunctionType rawType,
- required TypeArgumentList typeArgumentList,
- required ArgumentList argumentList,
- required List<WhyNotPromotedGetter> whyNotPromotedList,
- }) {
- var typeParameters = rawType.typeFormals;
-
- List<DartType> typeArguments;
- if (typeArgumentList.arguments.length != typeParameters.length) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
- typeArgumentList,
- [
- rawType,
- typeParameters.length,
- typeArgumentList.arguments.length,
- ],
- );
- typeArguments = List.filled(
- typeParameters.length,
- DynamicTypeImpl.instance,
- );
- } else {
- typeArguments = typeArgumentList.arguments
- .map((typeArgument) => typeArgument.typeOrThrow)
- .toList(growable: true);
- }
-
- var invokeType = rawType.instantiate(typeArguments);
- InferenceContext.setType(argumentList, invokeType);
-
- _resolveArguments(argumentList, whyNotPromotedList);
-
- _typeArgumentTypes = typeArguments;
- _invokeType = invokeType;
- }
-
- void _setCorrespondingParameters(
- ArgumentListImpl argumentList,
- FunctionType invokeType,
- ) {
- var parameters = ResolverVisitor.resolveArgumentsToParameters(
- argumentList: argumentList,
- parameters: invokeType.parameters,
- errorReporter: _errorReporter,
- );
- argumentList.correspondingStaticParameters = parameters;
- }
-
- static DartType? _getFreshType(DartType? type) {
- if (type is FunctionType) {
- var parameters = getFreshTypeParameters(type.typeFormals);
- return parameters.applyToFunctionType(type);
- } else {
- return type;
- }
+ recordStaticType(node, returnType, contextType: contextType);
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
new file mode 100644
index 0000000..c40a4ff
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
@@ -0,0 +1,545 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [Annotation] that resolve to a constructor invocation.
+class AnnotationInferrer extends FullInvocationInferrer<AnnotationImpl> {
+ /// The identifier pointing to the constructor that's being invoked, or `null`
+ /// if a constructor name couldn't be found (should only happen when
+ /// recovering from errors). If the constructor is generic, this identifier's
+ /// static element will be updated to point to a [ConstructorMember] with type
+ /// arguments filled in.
+ final SimpleIdentifierImpl? constructorName;
+
+ AnnotationInferrer({required this.constructorName}) : super._();
+
+ @override
+ bool get _needsTypeArgumentBoundsCheck => true;
+
+ @override
+ ErrorCode get _wrongNumberOfTypeArgumentsErrorCode =>
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
+
+ @override
+ ArgumentListImpl _getArgumentList(AnnotationImpl node) => node.arguments!;
+
+ @override
+ bool _getIsConst(AnnotationImpl node) => true;
+
+ @override
+ TypeArgumentListImpl? _getTypeArguments(AnnotationImpl node) =>
+ node.typeArguments;
+
+ @override
+ bool _isGenericInferenceDisabled(ResolverVisitor resolver) =>
+ !resolver.genericMetadataIsEnabled;
+
+ @override
+ List<ParameterElement>? _storeResult(AnnotationImpl node,
+ List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+ if (invokeType != null) {
+ var constructorElement = ConstructorMember.from(
+ node.element as ConstructorElement,
+ invokeType.returnType as InterfaceType,
+ );
+ constructorName?.staticElement = constructorElement;
+ node.element = constructorElement;
+ return constructorElement.parameters;
+ }
+ return null;
+ }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [ExtensionOverride].
+class ExtensionOverrideInferrer
+ extends InvocationInferrer<ExtensionOverrideImpl> {
+ const ExtensionOverrideInferrer() : super._();
+
+ @override
+ ArgumentListImpl _getArgumentList(ExtensionOverrideImpl node) =>
+ node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes that require full downward and upward inference.
+abstract class FullInvocationInferrer<Node extends AstNodeImpl>
+ extends InvocationInferrer<Node> {
+ const FullInvocationInferrer._() : super._();
+
+ bool get _needsTypeArgumentBoundsCheck => false;
+
+ ErrorCode get _wrongNumberOfTypeArgumentsErrorCode =>
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD;
+
+ @override
+ DartType resolveInvocation({
+ required ResolverVisitor resolver,
+ required Node node,
+ required FunctionType? rawType,
+ required DartType? contextType,
+ required List<WhyNotPromotedGetter> whyNotPromotedList,
+ }) {
+ var typeArgumentList = _getTypeArguments(node);
+
+ List<DartType>? typeArgumentTypes;
+ FunctionType? invokeType;
+ if (_isGenericInferenceDisabled(resolver)) {
+ if (rawType != null && rawType.typeFormals.isNotEmpty) {
+ typeArgumentTypes = List.filled(
+ rawType.typeFormals.length,
+ DynamicTypeImpl.instance,
+ );
+ } else {
+ typeArgumentTypes = const <DartType>[];
+ invokeType = rawType;
+ }
+
+ invokeType = rawType?.instantiate(typeArgumentTypes);
+ } else if (typeArgumentList != null) {
+ if (rawType != null &&
+ typeArgumentList.arguments.length != rawType.typeFormals.length) {
+ var typeParameters = rawType.typeFormals;
+ _reportWrongNumberOfTypeArguments(
+ resolver, typeArgumentList, rawType, typeParameters);
+ typeArgumentTypes = List.filled(
+ typeParameters.length,
+ DynamicTypeImpl.instance,
+ );
+ } else {
+ typeArgumentTypes = typeArgumentList.arguments
+ .map((typeArgument) => typeArgument.typeOrThrow)
+ .toList(growable: true);
+ if (rawType != null && _needsTypeArgumentBoundsCheck) {
+ var typeParameters = rawType.typeFormals;
+ var substitution = Substitution.fromPairs(
+ typeParameters,
+ typeArgumentTypes,
+ );
+ for (var i = 0; i < typeParameters.length; i++) {
+ var typeParameter = typeParameters[i];
+ var bound = typeParameter.bound;
+ if (bound != null) {
+ bound = resolver.definingLibrary.toLegacyTypeIfOptOut(bound);
+ bound = substitution.substituteType(bound);
+ var typeArgument = typeArgumentTypes[i];
+ if (!resolver.typeSystem.isSubtypeOf(typeArgument, bound)) {
+ resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+ typeArgumentList.arguments[i],
+ [typeArgument, typeParameter.name, bound],
+ );
+ }
+ }
+ }
+ }
+ }
+
+ invokeType = rawType?.instantiate(typeArgumentTypes);
+ } else if (rawType == null || rawType.typeFormals.isEmpty) {
+ typeArgumentTypes = const <DartType>[];
+ invokeType = rawType;
+ } else {
+ rawType = getFreshTypeParameters(rawType.typeFormals)
+ .applyToFunctionType(rawType);
+
+ var downwardsTypeArguments =
+ resolver.typeSystem.inferGenericFunctionOrType(
+ typeParameters: rawType.typeFormals,
+ parameters: const <ParameterElement>[],
+ declaredReturnType: rawType.returnType,
+ argumentTypes: const <DartType>[],
+ contextReturnType: contextType,
+ downwards: true,
+ isConst: _getIsConst(node),
+ errorReporter: resolver.errorReporter,
+ errorNode: _getErrorNode(node),
+ genericMetadataIsEnabled: resolver.genericMetadataIsEnabled,
+ )!;
+
+ invokeType = rawType.instantiate(downwardsTypeArguments);
+ }
+
+ super.resolveInvocation(
+ resolver: resolver,
+ node: node,
+ rawType: invokeType,
+ contextType: contextType,
+ whyNotPromotedList: whyNotPromotedList);
+
+ var argumentList = _getArgumentList(node);
+
+ if (typeArgumentTypes == null) {
+ if (rawType != null) {
+ // Get the parameters that correspond to the uninstantiated generic.
+ List<ParameterElement?> rawParameters =
+ ResolverVisitor.resolveArgumentsToParameters(
+ argumentList: argumentList,
+ parameters: rawType.parameters,
+ );
+
+ List<ParameterElement> params = <ParameterElement>[];
+ List<DartType> argTypes = <DartType>[];
+ for (int i = 0, length = rawParameters.length; i < length; i++) {
+ ParameterElement? parameter = rawParameters[i];
+ if (parameter != null) {
+ params.add(parameter);
+ argTypes.add(argumentList.arguments[i].typeOrThrow);
+ }
+ }
+ typeArgumentTypes = resolver.typeSystem.inferGenericFunctionOrType(
+ typeParameters: rawType.typeFormals,
+ parameters: params,
+ declaredReturnType: rawType.returnType,
+ argumentTypes: argTypes,
+ contextReturnType: contextType,
+ isConst: _getIsConst(node),
+ errorReporter: resolver.errorReporter,
+ errorNode: _getErrorNode(node),
+ genericMetadataIsEnabled: resolver.genericMetadataIsEnabled,
+ )!;
+ invokeType = rawType.instantiate(typeArgumentTypes);
+ } else {
+ typeArgumentTypes = const [];
+ }
+ }
+
+ var parameters = _storeResult(node, typeArgumentTypes, invokeType);
+ if (parameters != null) {
+ argumentList.correspondingStaticParameters =
+ ResolverVisitor.resolveArgumentsToParameters(
+ argumentList: argumentList,
+ parameters: parameters,
+ errorReporter: resolver.errorReporter,
+ );
+ }
+ var returnType = InvocationInferrer.computeInvokeReturnType(invokeType);
+ return _refineReturnType(resolver, node, returnType);
+ }
+
+ AstNode _getErrorNode(Node node) => node;
+
+ bool _getIsConst(Node node) => false;
+
+ TypeArgumentListImpl? _getTypeArguments(Node node);
+
+ bool _isGenericInferenceDisabled(ResolverVisitor resolver) => false;
+
+ DartType _refineReturnType(
+ ResolverVisitor resolver, Node node, DartType returnType) =>
+ returnType;
+
+ void _reportWrongNumberOfTypeArguments(
+ ResolverVisitor resolver,
+ TypeArgumentList typeArgumentList,
+ FunctionType rawType,
+ List<TypeParameterElement> typeParameters) {
+ resolver.errorReporter.reportErrorForNode(
+ _wrongNumberOfTypeArgumentsErrorCode,
+ typeArgumentList,
+ [
+ rawType,
+ typeParameters.length,
+ typeArgumentList.arguments.length,
+ ],
+ );
+ }
+
+ List<ParameterElement>? _storeResult(
+ Node node, List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+ return invokeType?.parameters;
+ }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [FunctionExpressionInvocation].
+class FunctionExpressionInvocationInferrer
+ extends InvocationExpressionInferrer<FunctionExpressionInvocationImpl> {
+ const FunctionExpressionInvocationInferrer() : super._();
+
+ @override
+ ExpressionImpl _getErrorNode(FunctionExpressionInvocationImpl node) =>
+ node.function;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [InstanceCreationExpression].
+class InstanceCreationInferrer
+ extends FullInvocationInferrer<InstanceCreationExpressionImpl> {
+ const InstanceCreationInferrer() : super._();
+
+ @override
+ bool get _needsTypeArgumentBoundsCheck => true;
+
+ @override
+ ArgumentListImpl _getArgumentList(InstanceCreationExpressionImpl node) =>
+ node.argumentList;
+
+ @override
+ ConstructorNameImpl _getErrorNode(InstanceCreationExpressionImpl node) =>
+ node.constructorName;
+
+ @override
+ bool _getIsConst(InstanceCreationExpressionImpl node) => node.isConst;
+
+ @override
+ TypeArgumentListImpl? _getTypeArguments(InstanceCreationExpressionImpl node) {
+ // For an instance creation expression the type arguments are on the
+ // constructor name.
+ return node.constructorName.type.typeArguments;
+ }
+
+ @override
+ void _reportWrongNumberOfTypeArguments(
+ ResolverVisitor resolver,
+ TypeArgumentList typeArgumentList,
+ FunctionType rawType,
+ List<TypeParameterElement> typeParameters) {
+ // Error reporting for instance creations is done elsewhere.
+ }
+
+ @override
+ List<ParameterElement>? _storeResult(InstanceCreationExpressionImpl node,
+ List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+ if (invokeType != null) {
+ var constructedType = invokeType.returnType;
+ node.constructorName.type.type = constructedType;
+ var constructorElement = ConstructorMember.from(
+ node.constructorName.staticElement!,
+ constructedType as InterfaceType,
+ );
+ node.constructorName.staticElement = constructorElement;
+ return constructorElement.parameters;
+ }
+ return null;
+ }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes derived from [InvocationExpression].
+abstract class InvocationExpressionInferrer<
+ Node extends InvocationExpressionImpl>
+ extends FullInvocationInferrer<Node> {
+ const InvocationExpressionInferrer._() : super._();
+
+ @override
+ ArgumentListImpl _getArgumentList(Node node) => node.argumentList;
+
+ @override
+ Expression _getErrorNode(Node node) => node.function;
+
+ @override
+ TypeArgumentListImpl? _getTypeArguments(Node node) => node.typeArguments;
+
+ @override
+ List<ParameterElement>? _storeResult(
+ Node node, List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+ node.typeArgumentTypes = typeArgumentTypes;
+ node.staticInvokeType = invokeType ?? DynamicTypeImpl.instance;
+ return super._storeResult(node, typeArgumentTypes, invokeType);
+ }
+}
+
+/// Base class containing functionality for performing type inference on AST
+/// nodes that invoke a method, function, or constructor.
+abstract class InvocationInferrer<Node extends AstNodeImpl> {
+ const InvocationInferrer._();
+
+ /// Performs type inference on an invocation expression of type [Node].
+ /// [rawType] should be the type of the function the invocation is resolved to
+ /// (with type arguments not applied yet).
+ void resolveInvocation({
+ required ResolverVisitor resolver,
+ required Node node,
+ required FunctionType? rawType,
+ required DartType? contextType,
+ required List<WhyNotPromotedGetter> whyNotPromotedList,
+ }) {
+ var parameters = rawType?.parameters;
+ var namedParameters = <String, ParameterElement>{};
+ if (parameters != null) {
+ for (var i = 0; i < parameters.length; i++) {
+ var parameter = parameters[i];
+ if (parameter.isNamed) {
+ namedParameters[parameter.name] = parameter;
+ }
+ }
+ }
+ var argumentList = _getArgumentList(node);
+ resolver.checkUnreachableNode(argumentList);
+ var flow = resolver.flowAnalysis.flow;
+ var positionalParameterIndex = 0;
+ for (var argument in _iterateArguments(resolver, argumentList)) {
+ ParameterElement? parameter;
+ if (argument is NamedExpression) {
+ parameter = namedParameters[argument.name.label.name];
+ } else if (parameters != null) {
+ while (positionalParameterIndex < parameters.length) {
+ parameter = parameters[positionalParameterIndex++];
+ if (!parameter.isNamed) {
+ break;
+ }
+ }
+ }
+ DartType? parameterContextType;
+ if (parameter != null) {
+ var parameterType = parameter.type;
+ parameterContextType = _computeContextForArgument(
+ resolver, node, parameterType, contextType);
+ }
+ resolver.analyzeExpression(argument, parameterContextType);
+ if (flow != null) {
+ whyNotPromotedList.add(flow.whyNotPromoted(argument));
+ }
+ }
+ }
+
+ /// Computes the type context that should be used when evaluating a particular
+ /// argument of the invocation. Usually this is just the type of the
+ /// corresponding parameter, but it can be different for certain primitive
+ /// numeric operations.
+ DartType? _computeContextForArgument(ResolverVisitor resolver, Node node,
+ DartType parameterType, DartType? methodInvocationContext) =>
+ parameterType;
+
+ /// Gets the argument list for the invocation. TODO(paulberry): remove?
+ ArgumentListImpl _getArgumentList(Node node);
+
+ /// Iterates through the argument list for the invocation. Usually this is
+ /// just a simple iteration through the arguments, but in certain cases, some
+ /// flow analysis methods need to be called in between visiting the various
+ /// arguments.
+ Iterable<Expression> _iterateArguments(
+ ResolverVisitor resolver, ArgumentList argumentList) =>
+ argumentList.arguments;
+
+ /// Computes the return type of the method or function represented by the
+ /// given type that is being invoked.
+ static DartType computeInvokeReturnType(DartType? type) {
+ if (type is FunctionType) {
+ return type.returnType;
+ } else {
+ return DynamicTypeImpl.instance;
+ }
+ }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [MethodInvocation].
+class MethodInvocationInferrer
+ extends InvocationExpressionInferrer<MethodInvocationImpl> {
+ /// Gets the appropriate instance of [MethodInvocation] for the given [node].
+ ///
+ /// This factory takes care of the fact that invocations of `identical` need
+ /// to have special integration with flow analysis.
+ factory MethodInvocationInferrer.forNode(MethodInvocationImpl node) {
+ var invokedMethod = node.methodName.staticElement;
+ if (invokedMethod != null &&
+ invokedMethod.name == 'identical' &&
+ invokedMethod.library!.isDartCore &&
+ node.argumentList.arguments.length == 2) {
+ return const _IdenticalInvocationInferrer._();
+ } else {
+ return const MethodInvocationInferrer._();
+ }
+ }
+
+ const MethodInvocationInferrer._() : super._();
+
+ @override
+ DartType? _computeContextForArgument(
+ ResolverVisitor resolver,
+ MethodInvocationImpl node,
+ DartType parameterType,
+ DartType? methodInvocationContext) {
+ var contextType = super._computeContextForArgument(
+ resolver, node, parameterType, methodInvocationContext);
+ var targetType = node.realTarget?.staticType;
+ if (targetType != null) {
+ contextType = resolver.typeSystem.refineNumericInvocationContext(
+ targetType,
+ node.methodName.staticElement,
+ methodInvocationContext,
+ parameterType);
+ }
+ return contextType;
+ }
+
+ @override
+ DartType _refineReturnType(ResolverVisitor resolver,
+ MethodInvocationImpl node, DartType returnType) {
+ var targetType = node.realTarget?.staticType;
+ if (targetType != null) {
+ returnType = resolver.typeSystem.refineNumericInvocationType(
+ targetType,
+ node.methodName.staticElement,
+ [
+ for (var argument in node.argumentList.arguments) argument.typeOrThrow
+ ],
+ returnType,
+ );
+ }
+ return returnType;
+ }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [RedirectingConstructorInvocation].
+class RedirectingConstructorInvocationInferrer
+ extends InvocationInferrer<RedirectingConstructorInvocationImpl> {
+ const RedirectingConstructorInvocationInferrer() : super._();
+
+ @override
+ ArgumentListImpl _getArgumentList(
+ RedirectingConstructorInvocationImpl node) =>
+ node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [SuperConstructorInvocation].
+class SuperConstructorInvocationInferrer
+ extends InvocationInferrer<SuperConstructorInvocationImpl> {
+ const SuperConstructorInvocationInferrer() : super._();
+
+ @override
+ ArgumentListImpl _getArgumentList(SuperConstructorInvocationImpl node) =>
+ node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [MethodInvocation] that resolve to the core function
+/// `identical`. (Such nodes need to be handled in a special way due to the
+/// interaction between `identical` and flow analysis).
+class _IdenticalInvocationInferrer extends MethodInvocationInferrer {
+ const _IdenticalInvocationInferrer._() : super._();
+
+ @override
+ Iterable<Expression> _iterateArguments(
+ ResolverVisitor resolver, ArgumentList argumentList) sync* {
+ var flow = resolver.flowAnalysis.flow;
+ var arguments = argumentList.arguments;
+ assert(arguments.length == 2);
+ var firstArg = arguments[0];
+ yield firstArg;
+ firstArg = arguments[0]; // In case it was rewritten
+ flow?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
+ var secondArg = arguments[1];
+ yield secondArg;
+ secondArg = arguments[1]; // In case it was rewritten
+ flow?.equalityOp_end(
+ argumentList.parent as Expression, secondArg, secondArg.typeOrThrow);
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 2c26796..724f3c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -15,6 +15,7 @@
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -76,8 +77,9 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(MethodInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ void resolve(
+ MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
_invocation = node;
var nameNode = node.methodName;
@@ -87,7 +89,8 @@
var receiver = node.realTarget;
if (receiver == null) {
- _resolveReceiverNull(node, nameNode, name, whyNotPromotedList);
+ _resolveReceiverNull(node, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -95,7 +98,8 @@
var receiverElement = receiver.staticElement;
if (receiverElement is PrefixElement) {
_resolveReceiverPrefix(
- node, receiverElement, nameNode, name, whyNotPromotedList);
+ node, receiverElement, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
}
@@ -103,20 +107,23 @@
if (receiver is IdentifierImpl) {
var receiverElement = receiver.staticElement;
if (receiverElement is ExtensionElement) {
- _resolveExtensionMember(node, receiver, receiverElement, nameNode, name,
- whyNotPromotedList);
+ _resolveExtensionMember(
+ node, receiver, receiverElement, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
}
if (receiver is SuperExpressionImpl) {
- _resolveReceiverSuper(node, receiver, nameNode, name, whyNotPromotedList);
+ _resolveReceiverSuper(node, receiver, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
if (receiver is ExtensionOverrideImpl) {
_resolveExtensionOverride(
- node, receiver, nameNode, name, whyNotPromotedList);
+ node, receiver, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -124,13 +131,15 @@
var element = receiver.staticElement;
if (element is ClassElement) {
_resolveReceiverTypeLiteral(
- node, element, nameNode, name, whyNotPromotedList);
+ node, element, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
} else if (element is TypeAliasElement) {
var aliasedType = element.aliasedType;
if (aliasedType is InterfaceType) {
_resolveReceiverTypeLiteral(
- node, aliasedType.element, nameNode, name, whyNotPromotedList);
+ node, aliasedType.element, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
}
@@ -139,17 +148,20 @@
DartType receiverType = receiver.typeOrThrow;
if (_typeSystem.isDynamicBounded(receiverType)) {
- _resolveReceiverDynamicBounded(node, whyNotPromotedList);
+ _resolveReceiverDynamicBounded(node, whyNotPromotedList,
+ contextType: contextType);
return;
}
if (receiverType is NeverTypeImpl) {
- _resolveReceiverNever(node, receiver, receiverType, whyNotPromotedList);
+ _resolveReceiverNever(node, receiver, receiverType, whyNotPromotedList,
+ contextType: contextType);
return;
}
if (receiverType is VoidType) {
- _reportUseOfVoidType(node, receiver, whyNotPromotedList);
+ _reportUseOfVoidType(node, receiver, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -160,7 +172,8 @@
if (_typeSystem.isFunctionBounded(receiverType)) {
_resolveReceiverFunctionBounded(
- node, receiver, receiverType, nameNode, name, whyNotPromotedList);
+ node, receiver, receiverType, nameNode, name, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -175,7 +188,8 @@
nameNode,
[name, receiver.type.name.name],
);
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
return;
}
@@ -187,6 +201,7 @@
name: name,
receiverErrorNode: receiver,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
}
@@ -244,10 +259,13 @@
}
}
- void _reportInvocationOfNonFunction(MethodInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ void _reportInvocationOfNonFunction(
+ MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
_setDynamicResolution(node,
- setNameTypeToDynamic: false, whyNotPromotedList: whyNotPromotedList);
+ setNameTypeToDynamic: false,
+ whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION,
node.methodName,
@@ -279,8 +297,10 @@
required String? prefix,
required String name,
required List<WhyNotPromotedGetter> whyNotPromotedList,
+ required DartType? contextType,
}) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
if (_definingLibrary.shouldIgnoreUndefined(prefix: prefix, name: name)) {
return;
@@ -294,41 +314,29 @@
}
void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.USE_OF_VOID_RESULT,
errorNode,
);
}
- /// [InvocationExpression.staticInvokeType] has been set for the [node].
- /// Use it to set context for arguments, and resolve them.
- void _resolveArguments(MethodInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- // TODO(scheglov) This is bad, don't write raw type, carry it
- _inferenceHelper.inferArgumentTypesForInvocation(
- node,
- node.methodName.staticType,
- );
- _resolver.visitArgumentList(node.argumentList,
+ void _resolveArguments_finishInference(
+ MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
+ var methodInvocationInferrer = MethodInvocationInferrer.forNode(node);
+ var rawType = node.methodName.staticType;
+ DartType staticStaticType = methodInvocationInferrer.resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: rawType is FunctionType ? rawType : null,
+ contextType: contextType,
whyNotPromotedList: whyNotPromotedList);
- }
-
- void _resolveArguments_finishInference(MethodInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _resolveArguments(node, whyNotPromotedList);
-
- // TODO(scheglov) This is bad, don't put / get raw FunctionType this way.
- _inferenceHelper.inferGenericInvocationExpression(
- node,
- node.methodName.staticType,
- );
-
- DartType staticStaticType = _inferenceHelper.computeInvokeReturnType(
- node.staticInvokeType,
- );
- _inferenceHelper.recordStaticType(node, staticStaticType);
+ _inferenceHelper.recordStaticType(node, staticStaticType,
+ contextType: contextType);
}
/// Given that we are accessing a property of the given [classElement] with the
@@ -355,13 +363,15 @@
ExtensionElement extension,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var getter = extension.getGetter(name);
if (getter != null) {
getter = _resolver.toLegacyElement(getter);
nameNode.staticElement = getter;
_reportStaticAccessToInstanceMember(getter, nameNode);
- _rewriteAsFunctionExpressionInvocation(node, getter.returnType);
+ _rewriteAsFunctionExpressionInvocation(node, getter.returnType,
+ contextType: contextType);
return;
}
@@ -370,11 +380,13 @@
method = _resolver.toLegacyElement(method);
nameNode.staticElement = method;
_reportStaticAccessToInstanceMember(method, nameNode);
- _setResolution(node, method.type, whyNotPromotedList);
+ _setResolution(node, method.type, whyNotPromotedList,
+ contextType: contextType);
return;
}
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
// This method is only called for named extensions, so we know that
// `extension.name` is non-`null`.
_resolver.errorReporter.reportErrorForNode(
@@ -389,12 +401,14 @@
ExtensionOverride override,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var result = _extensionResolver.getOverrideMember(override, name);
var member = _resolver.toLegacyElement(result.getter);
if (member == null) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
// Extension overrides always refer to named extensions, so we can safely
// assume `override.staticElement!.name` is non-`null`.
_resolver.errorReporter.reportErrorForNode(
@@ -423,53 +437,61 @@
nameNode.staticElement = member;
if (member is PropertyAccessorElement) {
- return _rewriteAsFunctionExpressionInvocation(node, member.returnType);
+ return _rewriteAsFunctionExpressionInvocation(node, member.returnType,
+ contextType: contextType);
}
- _setResolution(node, member.type, whyNotPromotedList);
+ _setResolution(node, member.type, whyNotPromotedList,
+ contextType: contextType);
}
- void _resolveReceiverDynamicBounded(MethodInvocationImpl node,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ void _resolveReceiverDynamicBounded(
+ MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var nameNode = node.methodName;
var objectElement = _typeSystem.typeProvider.objectElement;
var target = objectElement.getMethod(nameNode.name);
- var hasMatchingObjectMethod = false;
+ FunctionType? rawType;
if (target is MethodElement && !target.isStatic) {
var arguments = node.argumentList.arguments;
- hasMatchingObjectMethod = arguments.length == target.parameters.length &&
- !arguments.any((e) => e is NamedExpression);
+ var hasMatchingObjectMethod =
+ arguments.length == target.parameters.length &&
+ !arguments.any((e) => e is NamedExpression);
if (hasMatchingObjectMethod) {
target = _resolver.toLegacyElement(target);
nameNode.staticElement = target;
- node.staticInvokeType = target.type;
+ rawType = target.type;
node.staticType = target.returnType;
}
}
- if (!hasMatchingObjectMethod) {
+ if (rawType == null) {
nameNode.staticType = DynamicTypeImpl.instance;
- node.staticInvokeType = DynamicTypeImpl.instance;
node.staticType = DynamicTypeImpl.instance;
}
_setExplicitTypeArgumentTypes();
- _resolver.visitArgumentList(node.argumentList,
- whyNotPromotedList: whyNotPromotedList);
+ MethodInvocationInferrer.forNode(node).resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: rawType,
+ whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType);
}
void _resolveReceiverFunctionBounded(
- MethodInvocationImpl node,
- Expression receiver,
- DartType receiverType,
- SimpleIdentifierImpl nameNode,
- String name,
- List<WhyNotPromotedGetter> whyNotPromotedList,
- ) {
+ MethodInvocationImpl node,
+ Expression receiver,
+ DartType receiverType,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
if (name == FunctionElement.CALL_METHOD_NAME) {
- _setResolution(node, receiverType, whyNotPromotedList);
+ _setResolution(node, receiverType, whyNotPromotedList,
+ contextType: contextType);
// TODO(scheglov) Replace this with using FunctionType directly.
// Here was erase resolution that _setResolution() sets.
nameNode.staticElement = null;
@@ -485,15 +507,13 @@
name: name,
receiverErrorNode: nameNode,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
}
- void _resolveReceiverNever(
- MethodInvocationImpl node,
- Expression receiver,
- DartType receiverType,
- List<WhyNotPromotedGetter> whyNotPromotedList,
- ) {
+ void _resolveReceiverNever(MethodInvocationImpl node, Expression receiver,
+ DartType receiverType, List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
_setExplicitTypeArgumentTypes();
if (receiverType == NeverTypeImpl.instanceNullable) {
@@ -507,9 +527,11 @@
node,
objectMember.type,
whyNotPromotedList,
+ contextType: contextType,
);
} else {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
_resolver.nullableDereferenceVerifier.report(
CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
methodName,
@@ -524,7 +546,12 @@
node.staticInvokeType = _dynamicType;
node.staticType = NeverTypeImpl.instance;
- _resolveArguments(node, whyNotPromotedList);
+ MethodInvocationInferrer.forNode(node).resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: null,
+ contextType: contextType,
+ whyNotPromotedList: whyNotPromotedList);
_resolver.errorReporter.reportErrorForNode(
HintCode.RECEIVER_OF_TYPE_NEVER,
@@ -538,7 +565,12 @@
node.staticInvokeType = _dynamicType;
node.staticType = _dynamicType;
- _resolveArguments(node, whyNotPromotedList);
+ MethodInvocationInferrer.forNode(node).resolveInvocation(
+ resolver: _resolver,
+ node: node,
+ rawType: null,
+ contextType: contextType,
+ whyNotPromotedList: whyNotPromotedList);
return;
}
}
@@ -547,7 +579,8 @@
MethodInvocationImpl node,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var element = nameNode.scopeLookupResult!.getter;
if (element != null) {
element = _resolver.toLegacyElement(element);
@@ -557,23 +590,28 @@
element = multiply.conflictingElements[0];
}
if (element is PropertyAccessorElement) {
- return _rewriteAsFunctionExpressionInvocation(node, element.returnType);
+ return _rewriteAsFunctionExpressionInvocation(node, element.returnType,
+ contextType: contextType);
}
if (element is ExecutableElement) {
- return _setResolution(node, element.type, whyNotPromotedList);
+ return _setResolution(node, element.type, whyNotPromotedList,
+ contextType: contextType);
}
if (element is VariableElement) {
_resolver.checkReadOfNotAssignedLocalVariable(nameNode, element);
var targetType =
_localVariableTypeProvider.getType(nameNode, isRead: true);
- return _rewriteAsFunctionExpressionInvocation(node, targetType);
+ return _rewriteAsFunctionExpressionInvocation(node, targetType,
+ contextType: contextType);
}
// TODO(scheglov) This is a questionable distinction.
if (element is PrefixElement) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
return _reportPrefixIdentifierNotFollowedByDot(nameNode);
}
- return _reportInvocationOfNonFunction(node, whyNotPromotedList);
+ return _reportInvocationOfNonFunction(node, whyNotPromotedList,
+ contextType: contextType);
}
DartType receiverType;
@@ -587,6 +625,7 @@
prefix: null,
name: node.methodName.name,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
}
@@ -598,6 +637,7 @@
name: name,
receiverErrorNode: nameNode,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
}
@@ -606,7 +646,8 @@
PrefixElement prefix,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
// Note: prefix?.bar is reported as an error in ElementResolver.
if (name == FunctionElement.LOAD_LIBRARY_NAME) {
@@ -618,7 +659,8 @@
if (element is ExecutableElement) {
nameNode.staticElement = element;
return _setResolution(
- node, (element as ExecutableElement).type, whyNotPromotedList);
+ node, (element as ExecutableElement).type, whyNotPromotedList,
+ contextType: contextType);
}
}
}
@@ -633,11 +675,13 @@
}
if (element is PropertyAccessorElement) {
- return _rewriteAsFunctionExpressionInvocation(node, element.returnType);
+ return _rewriteAsFunctionExpressionInvocation(node, element.returnType,
+ contextType: contextType);
}
if (element is ExecutableElement) {
- return _setResolution(node, element.type, whyNotPromotedList);
+ return _setResolution(node, element.type, whyNotPromotedList,
+ contextType: contextType);
}
_reportUndefinedFunction(
@@ -645,6 +689,7 @@
prefix: prefix.name,
name: name,
whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType,
);
}
@@ -653,10 +698,12 @@
SuperExpression receiver,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var enclosingClass = _resolver.enclosingClass;
if (SuperContext.of(receiver) != SuperContext.valid) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
return;
}
@@ -671,9 +718,11 @@
if (target != null) {
nameNode.staticElement = target;
if (target is PropertyAccessorElement) {
- return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
+ return _rewriteAsFunctionExpressionInvocation(node, target.returnType,
+ contextType: contextType);
}
- _setResolution(node, target.type, whyNotPromotedList);
+ _setResolution(node, target.type, whyNotPromotedList,
+ contextType: contextType);
return;
}
@@ -683,7 +732,8 @@
target = _inheritance.getInherited2(enclosingClass, _currentName!);
if (target != null) {
nameNode.staticElement = target;
- _setResolution(node, target.type, whyNotPromotedList);
+ _setResolution(node, target.type, whyNotPromotedList,
+ contextType: contextType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
@@ -693,7 +743,8 @@
}
// Nothing help, there is no target at all.
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_SUPER_METHOD,
nameNode,
@@ -708,6 +759,7 @@
required String name,
required Expression receiverErrorNode,
required List<WhyNotPromotedGetter> whyNotPromotedList,
+ required DartType? contextType,
}) {
var result = _resolver.typePropertyResolver.resolve(
receiver: receiver,
@@ -730,12 +782,15 @@
}
if (target is PropertyAccessorElement) {
- return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
+ return _rewriteAsFunctionExpressionInvocation(node, target.returnType,
+ contextType: contextType);
}
- return _setResolution(node, target.type, whyNotPromotedList);
+ return _setResolution(node, target.type, whyNotPromotedList,
+ contextType: contextType);
}
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
if (!result.needsGetterError) {
return;
@@ -762,7 +817,8 @@
ClassElement receiver,
SimpleIdentifierImpl nameNode,
String name,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
if (node.isCascaded) {
receiver = _typeType.element;
}
@@ -774,16 +830,20 @@
nameNode.staticElement = element;
if (element is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(
- node, element.returnType);
+ node, element.returnType,
+ contextType: contextType);
}
- _setResolution(node, element.type, whyNotPromotedList);
+ _setResolution(node, element.type, whyNotPromotedList,
+ contextType: contextType);
} else {
- _reportInvocationOfNonFunction(node, whyNotPromotedList);
+ _reportInvocationOfNonFunction(node, whyNotPromotedList,
+ contextType: contextType);
}
return;
}
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ _setDynamicResolution(node,
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
if (nameNode.name == 'new') {
// Attempting to invoke the unnamed constructor via `C.new(`.
if (_resolver.isConstructorTearoffsEnabled) {
@@ -820,11 +880,11 @@
/// an [InterfaceType]. So, it should be represented as instead as a
/// [FunctionExpressionInvocation].
void _rewriteAsFunctionExpressionInvocation(
- MethodInvocationImpl node,
- DartType getterReturnType,
- ) {
+ MethodInvocationImpl node, DartType getterReturnType,
+ {required DartType? contextType}) {
var targetType = _resolveTypeParameter(getterReturnType);
- _inferenceHelper.recordStaticType(node.methodName, targetType);
+ _inferenceHelper.recordStaticType(node.methodName, targetType,
+ contextType: contextType);
ExpressionImpl functionExpression;
var target = node.target;
@@ -861,20 +921,21 @@
);
NodeReplacer.replace(node, invocation);
node.setProperty(_rewriteResultKey, invocation);
- InferenceContext.setTypeFromNode(invocation, node);
_resolver.flowAnalysis.transferTestData(node, invocation);
}
void _setDynamicResolution(MethodInvocationImpl node,
{bool setNameTypeToDynamic = true,
- required List<WhyNotPromotedGetter> whyNotPromotedList}) {
+ required List<WhyNotPromotedGetter> whyNotPromotedList,
+ required DartType? contextType}) {
if (setNameTypeToDynamic) {
node.methodName.staticType = _dynamicType;
}
node.staticInvokeType = _dynamicType;
node.staticType = _dynamicType;
_setExplicitTypeArgumentTypes();
- _resolveArguments_finishInference(node, whyNotPromotedList);
+ _resolveArguments_finishInference(node, whyNotPromotedList,
+ contextType: contextType);
}
/// Set explicitly specified type argument types, or empty if not specified.
@@ -894,28 +955,36 @@
}
void _setResolution(MethodInvocationImpl node, DartType type,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
// TODO(scheglov) We need this for StaticTypeAnalyzer to run inference.
// But it seems weird. Do we need to know the raw type of a function?!
node.methodName.staticType = type;
if (type == _dynamicType || _isCoreFunction(type)) {
_setDynamicResolution(node,
- setNameTypeToDynamic: false, whyNotPromotedList: whyNotPromotedList);
+ setNameTypeToDynamic: false,
+ whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType);
return;
}
if (type is FunctionType) {
_inferenceHelper.resolveMethodInvocation(
- node: node, rawType: type, whyNotPromotedList: whyNotPromotedList);
+ node: node,
+ rawType: type,
+ whyNotPromotedList: whyNotPromotedList,
+ contextType: contextType);
return;
}
if (type is VoidType) {
- return _reportUseOfVoidType(node, node.methodName, whyNotPromotedList);
+ return _reportUseOfVoidType(node, node.methodName, whyNotPromotedList,
+ contextType: contextType);
}
- _reportInvocationOfNonFunction(node, whyNotPromotedList);
+ _reportInvocationOfNonFunction(node, whyNotPromotedList,
+ contextType: contextType);
}
/// Resolver visitor is separated from the elements resolver, which calls
diff --git a/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart
index 969d189..5063c86 100644
--- a/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart
@@ -213,7 +213,7 @@
typeArguments: typeArguments,
nullabilitySuffix: nullability,
);
- type = typeSystem.toLegacyType(type);
+ type = typeSystem.toLegacyTypeIfOptOut(type);
return _verifyTypeAliasForContext(node, element, type);
} else if (_isInstanceCreation(node)) {
_ErrorHelper(errorReporter).reportNewWithNonType(node);
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 376a9d7..9667c37f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -40,9 +41,9 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(PostfixExpressionImpl node) {
+ void resolve(PostfixExpressionImpl node, {required DartType? contextType}) {
if (node.operator.type == TokenType.BANG) {
- _resolveNullCheck(node);
+ _resolveNullCheck(node, contextType: contextType);
return;
}
@@ -65,7 +66,7 @@
var receiverType = node.readType!;
_resolve1(node, receiverType);
- _resolve2(node, receiverType);
+ _resolve2(node, receiverType, contextType: contextType);
}
/// Check that the result [type] of a prefix or postfix `++` or `--`
@@ -97,11 +98,11 @@
// We are invoking a getter and then invoking the returned function.
//
FunctionType propertyType = element.type;
- return _resolver.inferenceHelper.computeInvokeReturnType(
+ return InvocationInferrer.computeInvokeReturnType(
propertyType.returnType,
);
} else if (element is ExecutableElement) {
- return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
+ return InvocationInferrer.computeInvokeReturnType(element.type);
}
return DynamicTypeImpl.instance;
}
@@ -155,11 +156,13 @@
}
}
- void _resolve2(PostfixExpressionImpl node, DartType receiverType) {
+ void _resolve2(PostfixExpressionImpl node, DartType receiverType,
+ {required DartType? contextType}) {
Expression operand = node.operand;
if (identical(receiverType, NeverTypeImpl.instance)) {
- _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
+ _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance,
+ contextType: contextType);
} else {
DartType operatorReturnType;
if (receiverType.isDartCoreInt) {
@@ -179,11 +182,13 @@
}
}
- _inferenceHelper.recordStaticType(node, receiverType);
+ _inferenceHelper.recordStaticType(node, receiverType,
+ contextType: contextType);
_resolver.nullShortingTermination(node);
}
- void _resolveNullCheck(PostfixExpressionImpl node) {
+ void _resolveNullCheck(PostfixExpressionImpl node,
+ {required DartType? contextType}) {
var operand = node.operand;
if (operand is SuperExpression) {
@@ -191,26 +196,24 @@
ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR,
node,
);
- _inferenceHelper.recordStaticType(operand, DynamicTypeImpl.instance);
- _inferenceHelper.recordStaticType(node, DynamicTypeImpl.instance);
+ _inferenceHelper.recordStaticType(operand, DynamicTypeImpl.instance,
+ contextType: contextType);
+ _inferenceHelper.recordStaticType(node, DynamicTypeImpl.instance,
+ contextType: contextType);
return;
}
- var contextType = InferenceContext.getContext(node);
- if (contextType != null) {
- if (_isNonNullableByDefault) {
- contextType = _typeSystem.makeNullable(contextType);
- }
- InferenceContext.setType(operand, contextType);
+ if (contextType != null && _isNonNullableByDefault) {
+ contextType = _typeSystem.makeNullable(contextType);
}
- operand.accept(_resolver);
+ _resolver.analyzeExpression(operand, contextType);
operand = node.operand;
var operandType = operand.typeOrThrow;
var type = _typeSystem.promoteToNonNull(operandType);
- _inferenceHelper.recordStaticType(node, type);
+ _inferenceHelper.recordStaticType(node, type, contextType: contextType);
_resolver.nullShortingTermination(node);
_resolver.flowAnalysis.flow?.nonNullAssert_end(operand);
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index a108a8b..fc71e4f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -40,14 +41,15 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(PrefixExpressionImpl node) {
+ void resolve(PrefixExpressionImpl node, {required DartType? contextType}) {
var operator = node.operator.type;
if (operator == TokenType.BANG) {
- _resolveNegation(node);
+ _resolveNegation(node, contextType: contextType);
return;
}
+ var operand = node.operand;
if (operator.isIncrementOperator) {
var operandResolution = _resolver.resolveForWrite(
node: node.operand,
@@ -57,7 +59,6 @@
var readElement = operandResolution.readElement;
var writeElement = operandResolution.writeElement;
- var operand = node.operand;
_resolver.setReadElement(operand, readElement);
_resolver.setWriteElement(operand, writeElement);
_resolver.migrationResolutionHooks
@@ -65,11 +66,18 @@
_assignmentShared.checkFinalAlreadyAssigned(node.operand);
} else {
- node.operand.accept(_resolver);
+ DartType? innerContextType;
+ if (operator == TokenType.MINUS && operand is IntegerLiteralImpl) {
+ // Negated integer literals should undergo int->double conversion in the
+ // same circumstances as non-negated integer literals, so pass the
+ // context type through.
+ innerContextType = contextType;
+ }
+ _resolver.analyzeExpression(operand, innerContextType);
}
_resolve1(node);
- _resolve2(node);
+ _resolve2(node, contextType: contextType);
}
/// Check that the result [type] of a prefix or postfix `++` or `--`
@@ -101,11 +109,11 @@
// We are invoking a getter and then invoking the returned function.
//
var propertyType = element.type;
- return _resolver.inferenceHelper.computeInvokeReturnType(
+ return InvocationInferrer.computeInvokeReturnType(
propertyType.returnType,
);
} else if (element is ExecutableElement) {
- return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
+ return InvocationInferrer.computeInvokeReturnType(element.type);
}
return DynamicTypeImpl.instance;
}
@@ -182,10 +190,11 @@
}
}
- void _resolve2(PrefixExpressionImpl node) {
+ void _resolve2(PrefixExpressionImpl node, {required DartType? contextType}) {
TokenType operator = node.operator.type;
if (identical(node.readType, NeverTypeImpl.instance)) {
- _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
+ _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance,
+ contextType: contextType);
} else {
// The other cases are equivalent to invoking a method.
var staticMethodElement = node.staticElement;
@@ -206,23 +215,25 @@
}
}
}
- _inferenceHelper.recordStaticType(node, staticType);
+ _inferenceHelper.recordStaticType(node, staticType,
+ contextType: contextType);
}
_resolver.nullShortingTermination(node);
}
- void _resolveNegation(PrefixExpressionImpl node) {
+ void _resolveNegation(PrefixExpressionImpl node,
+ {required DartType? contextType}) {
var operand = node.operand;
- InferenceContext.setType(operand, _typeProvider.boolType);
- operand.accept(_resolver);
+ _resolver.analyzeExpression(operand, _typeProvider.boolType);
operand = node.operand;
var whyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(operand);
_resolver.boolExpressionVerifier.checkForNonBoolNegationExpression(operand,
whyNotPromoted: whyNotPromoted);
- _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+ _inferenceHelper.recordStaticType(node, _typeProvider.boolType,
+ contextType: contextType);
_resolver.flowAnalysis.flow?.logicalNot_end(node, operand);
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
index 4a1e23d..08996d4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -23,7 +23,7 @@
TypeProviderImpl get _typeProvider => _resolver.typeProvider;
- void resolve(PrefixedIdentifierImpl node) {
+ void resolve(PrefixedIdentifierImpl node, {required DartType? contextType}) {
node.prefix.accept(_resolver);
var resolver = PropertyElementResolver(_resolver);
@@ -44,13 +44,19 @@
}
if (identical(node.prefix.staticType, NeverTypeImpl.instance)) {
- _inferenceHelper.recordStaticType(identifier, NeverTypeImpl.instance);
- _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
+ _inferenceHelper.recordStaticType(identifier, NeverTypeImpl.instance,
+ contextType: contextType);
+ _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance,
+ contextType: contextType);
return;
}
DartType type = DynamicTypeImpl.instance;
- if (element is ClassElement) {
+ if (result.readElementRequested == null &&
+ result.readElementRecovery != null) {
+ // Since the element came from error recovery logic, its type isn't
+ // trustworthy; leave it as `dynamic`.
+ } else if (element is ClassElement) {
if (_isExpressionIdentifier(node)) {
var type = _typeProvider.typeType;
node.staticType = type;
@@ -90,10 +96,11 @@
// sites.
// TODO(srawlins): Switch all resolution to use the latter method, in a
// breaking change release.
- type = _inferenceHelper.inferTearOff(node, identifier, type);
+ type = _inferenceHelper.inferTearOff(node, identifier, type,
+ contextType: contextType);
}
- _inferenceHelper.recordStaticType(identifier, type);
- _inferenceHelper.recordStaticType(node, type);
+ _inferenceHelper.recordStaticType(identifier, type, contextType: null);
+ _inferenceHelper.recordStaticType(node, type, contextType: contextType);
}
/// Return the type that should be recorded for a node that resolved to the given accessor.
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index d0f35da..8e8bce1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -253,17 +253,20 @@
}
/// If the [element] is not static, report the error on the [identifier].
- void _checkForStaticAccessToInstanceMember(
+ ///
+ /// Returns `true` if an error was reported.
+ bool _checkForStaticAccessToInstanceMember(
SimpleIdentifier identifier,
ExecutableElement element,
) {
- if (element.isStatic) return;
+ if (element.isStatic) return false;
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
identifier,
[identifier.name],
);
+ return true;
}
void _checkForStaticMember(
@@ -494,6 +497,7 @@
}
ExecutableElement? readElement;
+ ExecutableElement? readElementRecovery;
if (hasRead) {
readElement = typeReference.getGetter(propertyName.name);
if (readElement != null && !_isAccessible(readElement)) {
@@ -509,7 +513,10 @@
if (readElement != null) {
readElement = _resolver.toLegacyElement(readElement);
- _checkForStaticAccessToInstanceMember(propertyName, readElement);
+ if (_checkForStaticAccessToInstanceMember(propertyName, readElement)) {
+ readElementRecovery = readElement;
+ readElement = null;
+ }
} else {
var code = typeReference.isEnum
? CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT
@@ -535,7 +542,10 @@
[propertyName.name],
);
}
- _checkForStaticAccessToInstanceMember(propertyName, writeElement);
+ if (_checkForStaticAccessToInstanceMember(propertyName, writeElement)) {
+ writeElementRecovery = writeElement;
+ writeElement = null;
+ }
} else {
// Recovery, try to use getter.
writeElementRecovery = typeReference.getGetter(propertyName.name);
@@ -550,6 +560,7 @@
return PropertyElementResolverResult(
readElementRequested: readElement,
+ readElementRecovery: readElementRecovery,
writeElementRequested: writeElement,
writeElementRecovery: writeElementRecovery,
);
@@ -564,6 +575,7 @@
var memberName = propertyName.name;
ExecutableElement? readElement;
+ ExecutableElement? readElementRecovery;
if (hasRead) {
readElement ??= extension.getGetter(memberName);
readElement ??= extension.getMethod(memberName);
@@ -579,11 +591,15 @@
);
} else {
readElement = _resolver.toLegacyElement(readElement);
- _checkForStaticAccessToInstanceMember(propertyName, readElement);
+ if (_checkForStaticAccessToInstanceMember(propertyName, readElement)) {
+ readElementRecovery = readElement;
+ readElement = null;
+ }
}
}
ExecutableElement? writeElement;
+ ExecutableElement? writeElementRecovery;
if (hasWrite) {
writeElement = extension.getSetter(memberName);
@@ -598,13 +614,18 @@
);
} else {
writeElement = _resolver.toLegacyElement(writeElement);
- _checkForStaticAccessToInstanceMember(propertyName, writeElement);
+ if (_checkForStaticAccessToInstanceMember(propertyName, writeElement)) {
+ writeElementRecovery = writeElement;
+ writeElement = null;
+ }
}
}
return PropertyElementResolverResult(
readElementRequested: readElement,
+ readElementRecovery: readElementRecovery,
writeElementRequested: writeElement,
+ writeElementRecovery: writeElementRecovery,
);
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 7145bd0..0cef5e5 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -235,7 +235,7 @@
ErrorCode errorCode = withClause == null
? CompileTimeErrorCode.EXTENDS_NON_CLASS
: CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS;
- _resolveType(extendsClause.superclass2, errorCode, asClass: true);
+ _resolveType(extendsClause.superclass, errorCode, asClass: true);
}
_resolveWithClause(withClause);
@@ -265,7 +265,7 @@
node.typeParameters?.accept(this);
_resolveType(
- node.superclass2,
+ node.superclass,
CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS,
asClass: true,
);
@@ -409,6 +409,7 @@
void visitEnumDeclaration(covariant EnumDeclarationImpl node) {
EnumElementImpl element = _elementWalker!.getEnum();
node.name.staticElement = element;
+ _namedTypeResolver.enclosingClass = element;
node.metadata.accept(this);
_setElementAnnotations(node.metadata, element.metadata);
@@ -418,12 +419,17 @@
_buildTypeParameterElements(node.typeParameters);
node.typeParameters?.accept(this);
+ _resolveWithClause(node.withClause);
+ _resolveImplementsClause(node.implementsClause);
+
_defineElements(element.accessors);
_defineElements(element.methods);
node.constants.accept(this);
node.members.accept(this);
});
});
+
+ _namedTypeResolver.enclosingClass = null;
}
@override
@@ -774,7 +780,7 @@
void visitInstanceCreationExpression(InstanceCreationExpression node) {
var newNode = _astRewriter.instanceCreationExpression(_nameScope, node);
if (newNode != node) {
- if (node.constructorName.type2.typeArguments != null &&
+ if (node.constructorName.type.typeArguments != null &&
newNode is MethodInvocation &&
newNode.target is FunctionReference &&
!_libraryElement.featureSet.isEnabled(Feature.constructor_tearoffs)) {
@@ -1287,7 +1293,7 @@
if (clause == null) return;
_resolveTypes(
- clause.interfaces2,
+ clause.interfaces,
CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
);
}
@@ -1296,7 +1302,7 @@
if (clause == null) return;
_resolveTypes(
- clause.superclassConstraints2,
+ clause.superclassConstraints,
CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE,
);
}
@@ -1305,7 +1311,7 @@
var redirectedConstructor = node.redirectedConstructor;
if (redirectedConstructor == null) return;
- var namedType = redirectedConstructor.type2;
+ var namedType = redirectedConstructor.type;
_namedTypeResolver.redirectedConstructor_namedType = namedType;
redirectedConstructor.accept(this);
@@ -1366,7 +1372,7 @@
void _resolveWithClause(WithClause? clause) {
if (clause == null) return;
- for (var namedType in clause.mixinTypes2) {
+ for (var namedType in clause.mixinTypes) {
_namedTypeResolver.withClause_namedType = namedType;
_resolveType(
namedType as NamedTypeImpl,
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index 16c0251..35266a2 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -28,7 +28,7 @@
TypeProviderImpl get _typeProvider => _resolver.typeProvider;
- void resolve(SimpleIdentifierImpl node) {
+ void resolve(SimpleIdentifierImpl node, {required DartType? contextType}) {
if (node.inDeclarationContext()) {
return;
}
@@ -38,7 +38,7 @@
_resolver.checkReadOfNotAssignedLocalVariable(node, node.staticElement);
_resolve1(node);
- _resolve2(node);
+ _resolve2(node, contextType: contextType);
}
/// Return the type that should be recorded for a node that resolved to the given accessor.
@@ -189,7 +189,7 @@
node.staticElement = element;
}
- void _resolve2(SimpleIdentifierImpl node) {
+ void _resolve2(SimpleIdentifierImpl node, {required DartType? contextType}) {
var element = node.staticElement;
if (element is ExtensionElement) {
@@ -242,10 +242,11 @@
// sites.
// TODO(srawlins): Switch all resolution to use the latter method, in a
// breaking change release.
- staticType =
- _resolver.inferenceHelper.inferTearOff(node, node, staticType);
+ staticType = _resolver.inferenceHelper
+ .inferTearOff(node, node, staticType, contextType: contextType);
}
- _inferenceHelper.recordStaticType(node, staticType);
+ _inferenceHelper.recordStaticType(node, staticType,
+ contextType: contextType);
}
/// TODO(scheglov) this is duplicate
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index bb7a033..660a6eb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -20,6 +20,28 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
+/// Context for inferring the types of elements of a collection literal.
+class CollectionLiteralContext {
+ /// The type context for ordinary collection elements, if this is a list or
+ /// set literal. Otherwise `null`.
+ final DartType? elementType;
+
+ /// The type context for spread expressions.
+ final DartType iterableType;
+
+ /// The type context for keys, if this is a map literal. Otherwise `null`.
+ final DartType? keyType;
+
+ /// The type context for values, if this is a map literal. Otherwise `null`.
+ final DartType? valueType;
+
+ CollectionLiteralContext(
+ {this.elementType,
+ required this.iterableType,
+ this.keyType,
+ this.valueType});
+}
+
/// Helper for resolving [ListLiteral]s and [SetOrMapLiteral]s.
class TypedLiteralResolver {
final ResolverVisitor _resolver;
@@ -73,7 +95,8 @@
: NullabilitySuffix.star;
}
- void resolveListLiteral(ListLiteralImpl node) {
+ void resolveListLiteral(ListLiteralImpl node,
+ {required DartType? contextType}) {
InterfaceType? listType;
var typeArguments = node.typeArguments?.arguments;
@@ -85,29 +108,30 @@
}
}
} else {
- listType = _inferListType(node, downwards: true);
+ listType =
+ _inferListType(node, downwards: true, contextType: contextType);
}
+ CollectionLiteralContext? context;
if (listType != null) {
DartType elementType = listType.typeArguments[0];
DartType iterableType = _typeProvider.iterableType(elementType);
- _pushCollectionTypesDownToAll(_getListElements(node),
+ context = CollectionLiteralContext(
elementType: elementType, iterableType: iterableType);
- InferenceContext.setType(node, listType);
- } else {
- InferenceContext.clearType(node);
}
- node.visitChildren(_resolver);
- _insertImplicitCallReferences(node);
- _resolveListLiteral2(node);
+ node.typeArguments?.accept(_resolver);
+ _resolveElements(node.elements, context);
+ _resolveListLiteral2(node, contextType: contextType);
}
- void resolveSetOrMapLiteral(SetOrMapLiteral node) {
+ void resolveSetOrMapLiteral(SetOrMapLiteral node,
+ {required DartType? contextType}) {
(node as SetOrMapLiteralImpl).becomeUnresolved();
var typeArguments = node.typeArguments?.arguments;
InterfaceType? literalType;
- var literalResolution = _computeSetOrMapResolution(node);
+ var literalResolution =
+ _computeSetOrMapResolution(node, contextType: contextType);
if (literalResolution.kind == _LiteralResolutionKind.set) {
if (typeArguments != null && typeArguments.length == 1) {
var elementType = typeArguments[0].typeOrThrow;
@@ -129,15 +153,17 @@
assert(literalResolution.kind == _LiteralResolutionKind.ambiguous);
literalType = null;
}
+ var elements = _getSetOrMapElements(node);
+ CollectionLiteralContext? context;
if (literalType is InterfaceType) {
List<DartType> typeArguments = literalType.typeArguments;
if (typeArguments.length == 1) {
DartType elementType = literalType.typeArguments[0];
DartType iterableType = _typeProvider.iterableType(elementType);
- _pushCollectionTypesDownToAll(_getSetOrMapElements(node),
+ context = CollectionLiteralContext(
elementType: elementType, iterableType: iterableType);
if (!_uiAsCodeEnabled &&
- _getSetOrMapElements(node).isEmpty &&
+ elements.isEmpty &&
node.typeArguments == null &&
node.isMap) {
// The node is really an empty set literal with no type arguments.
@@ -146,7 +172,7 @@
} else if (typeArguments.length == 2) {
DartType keyType = typeArguments[0];
DartType valueType = typeArguments[1];
- _pushCollectionTypesDownToAll(_getSetOrMapElements(node),
+ context = CollectionLiteralContext(
iterableType: literalType, keyType: keyType, valueType: valueType);
}
node.contextType = literalType;
@@ -154,9 +180,9 @@
node.contextType = null;
}
- node.visitChildren(_resolver);
- _insertImplicitCallReferences(node);
- _resolveSetOrMapLiteral2(node);
+ node.typeArguments?.accept(_resolver);
+ _resolveElements(node.elements, context);
+ _resolveSetOrMapLiteral2(node, contextType: contextType);
}
DartType _computeElementType(CollectionElement element) {
@@ -218,10 +244,10 @@
}
/// Compute the context type for the given set or map [literal].
- _LiteralResolution _computeSetOrMapResolution(SetOrMapLiteral literal) {
+ _LiteralResolution _computeSetOrMapResolution(SetOrMapLiteral literal,
+ {required DartType? contextType}) {
_LiteralResolution typeArgumentsResolution =
_fromTypeArguments(literal.typeArguments?.arguments);
- var contextType = InferenceContext.getContext(literal);
_LiteralResolution contextResolution = _fromContextType(contextType);
_LeafElements elementCounts = _LeafElements(_getSetOrMapElements(literal));
_LiteralResolution elementResolution = elementCounts.resolution;
@@ -424,9 +450,8 @@
}
}
- InterfaceType? _inferListType(ListLiteral node, {bool downwards = false}) {
- var contextType = InferenceContext.getContext(node);
-
+ InterfaceType? _inferListType(ListLiteral node,
+ {bool downwards = false, required DartType? contextType}) {
var element = _typeProvider.listElement;
var typeParameters = element.typeParameters;
var genericElementType = typeParameters[0].instantiate(
@@ -599,84 +624,15 @@
);
}
- void _insertImplicitCallReference(CollectionElement? node) {
- if (node is Expression) {
- _resolver.insertImplicitCallReference(node);
- } else if (node is MapLiteralEntry) {
- _insertImplicitCallReference(node.key);
- _insertImplicitCallReference(node.value);
- } else if (node is IfElement) {
- _insertImplicitCallReference(node.thenElement);
- _insertImplicitCallReference(node.elseElement);
- } else if (node is ForElement) {
- _insertImplicitCallReference(node.body);
- }
- // Nothing to do for [SpreadElement] as analyzer does not desugar this
- // element.
- }
-
- void _insertImplicitCallReferences(TypedLiteral node) {
- if (node is ListLiteral) {
- for (var element in node.elements) {
- _insertImplicitCallReference(element);
- }
- } else if (node is SetOrMapLiteral) {
- for (var element in node.elements) {
- _insertImplicitCallReference(element);
- }
+ void _resolveElements(
+ List<CollectionElement> elements, CollectionLiteralContext? context) {
+ for (var element in elements) {
+ (element as CollectionElementImpl).resolveElement(_resolver, context);
}
}
- void _pushCollectionTypesDown(CollectionElement? element,
- {DartType? elementType,
- required DartType iterableType,
- DartType? keyType,
- DartType? valueType}) {
- if (element is Expression) {
- InferenceContext.setType(element, elementType);
- } else if (element is ForElement) {
- _pushCollectionTypesDown(element.body,
- elementType: elementType,
- iterableType: iterableType,
- keyType: keyType,
- valueType: valueType);
- } else if (element is IfElement) {
- _pushCollectionTypesDown(element.thenElement,
- elementType: elementType,
- iterableType: iterableType,
- keyType: keyType,
- valueType: valueType);
- _pushCollectionTypesDown(element.elseElement,
- elementType: elementType,
- iterableType: iterableType,
- keyType: keyType,
- valueType: valueType);
- } else if (element is MapLiteralEntry) {
- InferenceContext.setType(element.key, keyType);
- InferenceContext.setType(element.value, valueType);
- } else if (element is SpreadElement) {
- if (_isNonNullableByDefault && element.isNullAware) {
- iterableType = _typeSystem.makeNullable(iterableType);
- }
- InferenceContext.setType(element.expression, iterableType);
- }
- }
-
- void _pushCollectionTypesDownToAll(List<CollectionElement> elements,
- {DartType? elementType,
- required DartType iterableType,
- DartType? keyType,
- DartType? valueType}) {
- for (CollectionElement element in elements) {
- _pushCollectionTypesDown(element,
- elementType: elementType,
- iterableType: iterableType,
- keyType: keyType,
- valueType: valueType);
- }
- }
-
- void _resolveListLiteral2(ListLiteralImpl node) {
+ void _resolveListLiteral2(ListLiteralImpl node,
+ {required DartType? contextType}) {
var typeArguments = node.typeArguments?.arguments;
// If we have explicit arguments, use them.
@@ -695,7 +651,7 @@
DartType listDynamicType = _typeProvider.listType(_dynamicType);
// If there are no type arguments, try to infer some arguments.
- var inferred = _inferListType(node);
+ var inferred = _inferListType(node, contextType: contextType);
if (inferred != listDynamicType) {
// TODO(brianwilkerson) Determine whether we need to make the inferred
@@ -708,7 +664,8 @@
node.staticType = listDynamicType;
}
- void _resolveSetOrMapLiteral2(SetOrMapLiteralImpl node) {
+ void _resolveSetOrMapLiteral2(SetOrMapLiteralImpl node,
+ {required DartType? contextType}) {
var typeArguments = node.typeArguments?.arguments;
// If we have type arguments, use them.
@@ -748,7 +705,7 @@
}
if (_strictInference &&
_getSetOrMapElements(node).isEmpty &&
- InferenceContext.getContext(node) == null) {
+ contextType == null) {
// We cannot infer the type of a collection literal with no elements, and
// no context type. If there are any elements, inference has not failed,
// as the types of those elements are considered resolved.
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index ca56632..17d7f04 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -43,14 +43,13 @@
var isTopLevel =
element is FieldElement || element is TopLevelVariableElement;
- InferenceContext.setTypeFromNode(initializer, node);
if (isTopLevel) {
_resolver.flowAnalysis.topLevelDeclaration_enter(node, null);
} else if (element.isLate) {
_resolver.flowAnalysis.flow?.lateInitializer_begin(node);
}
- initializer.accept(_resolver);
+ _resolver.analyzeExpression(initializer, element.type);
initializer = node.initializer!;
var whyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(initializer);
@@ -65,8 +64,6 @@
_resolver.flowAnalysis.flow?.lateInitializer_end();
}
- initializer = _resolver.insertImplicitCallReference(initializer);
-
// Initializers of top-level variables and fields are already included
// into elements during linking.
if (element is ConstLocalVariableElementImpl) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
index 0016d66..c8c5504 100644
--- a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
@@ -133,13 +133,30 @@
}
}
+ DartType? _computeContextType(
+ BodyInferenceContext bodyContext,
+ YieldStatement node,
+ ) {
+ var elementType = bodyContext.contextType;
+ if (elementType != null) {
+ var contextType = elementType;
+ if (node.star != null) {
+ contextType = bodyContext.isSynchronous
+ ? _typeProvider.iterableType(elementType)
+ : _typeProvider.streamType(elementType);
+ }
+ return contextType;
+ } else {
+ return null;
+ }
+ }
+
void _resolve_generator(
BodyInferenceContext bodyContext,
YieldStatement node,
) {
- _setContextType(bodyContext, node);
-
- node.expression.accept(_resolver);
+ _resolver.analyzeExpression(
+ node.expression, _computeContextType(bodyContext, node));
if (node.star != null) {
_resolver.nullableDereferenceVerifier.expression(
@@ -167,20 +184,4 @@
_checkForUseOfVoidResult(node.expression);
}
-
- void _setContextType(
- BodyInferenceContext bodyContext,
- YieldStatement node,
- ) {
- var elementType = bodyContext.contextType;
- if (elementType != null) {
- var contextType = elementType;
- if (node.star != null) {
- contextType = bodyContext.isSynchronous
- ? _typeProvider.iterableType(elementType)
- : _typeProvider.streamType(elementType);
- }
- InferenceContext.setType(node.expression, contextType);
- }
- }
}
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 45dce24..a151c37 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -32,7 +32,6 @@
import 'package:analyzer/src/error/null_safe_api_verifier.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:analyzer/src/workspace/workspace.dart';
@@ -529,8 +528,7 @@
if (node.parent is! FunctionDeclaration) {
_checkForMissingReturn(node.body, node);
}
- var functionType = InferenceContext.getContext(node);
- if (functionType is! FunctionType) {
+ if (!(node as FunctionExpressionImpl).wasFunctionTypeSupplied) {
_checkStrictInferenceInParameters(node.parameters, body: node.body);
}
super.visitFunctionExpression(node);
@@ -1199,7 +1197,7 @@
// TODO(jwren) We should modify ConstructorElement.getDisplayName(), or
// have the logic centralized elsewhere, instead of doing this logic
// here.
- String fullConstructorName = constructorName.type2.name.name;
+ String fullConstructorName = constructorName.type.name.name;
if (constructorName.name != null) {
fullConstructorName = '$fullConstructorName.${constructorName.name}';
}
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index edeba68..10bbfb6 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
import "package:analyzer/src/error/analyzer_error_code.dart";
@@ -1605,6 +1605,14 @@
uniqueName: 'CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER',
);
+ static const CompileTimeErrorCode CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE =
+ CompileTimeErrorCode(
+ 'CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE',
+ "Concrete classes can't have 'Enum' as a superinterface.",
+ correctionMessage:
+ "Try specifying a different interface, or remove it from the list.",
+ );
+
/**
* Parameters:
* 0: the name of the abstract method
@@ -1886,6 +1894,20 @@
* Parameters:
* 0: the name of the type variable
*/
+ static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_ENUM =
+ CompileTimeErrorCode(
+ 'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
+ "'{0}' can't be used to name both a type variable and the enum in which "
+ "the type variable is defined.",
+ correctionMessage: "Try renaming either the type variable or the enum.",
+ hasPublishedDocs: true,
+ uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_ENUM',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the type variable
+ */
static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_EXTENSION =
CompileTimeErrorCode(
'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
@@ -1941,6 +1963,20 @@
* Parameters:
* 0: the name of the type variable
*/
+ static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM =
+ CompileTimeErrorCode(
+ 'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
+ "'{0}' can't be used to name both a type variable and a member in this "
+ "enum.",
+ correctionMessage: "Try renaming either the type variable or the member.",
+ hasPublishedDocs: true,
+ uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the type variable
+ */
static const CompileTimeErrorCode
CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION = CompileTimeErrorCode(
'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
@@ -3040,10 +3076,35 @@
correctionMessage: "Try calling a different constructor.",
);
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the label in a `continue`
+ // statement resolves to a label on a `switch` statement.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the label `l`, used to
+ // label a `switch` statement, is used in the `continue` statement:
+ //
+ // ```dart
+ // void f(int i) {
+ // l: switch (i) {
+ // case 0:
+ // continue [!l!];
+ // }
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Find a different way to achieve the control flow you need; for example, by
+ // introducing a loop that re-executes the `switch` statement.
static const CompileTimeErrorCode CONTINUE_LABEL_ON_SWITCH =
CompileTimeErrorCode(
'CONTINUE_LABEL_ON_SWITCH',
- "A continue label resolves to switch, must be loop or switch member",
+ "A `continue` label resolves to a `switch` statement, but the label must "
+ "be on a loop or a switch member.",
+ hasPublishedDocs: true,
);
/**
@@ -3337,14 +3398,50 @@
/**
* No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an expression with a value that
+ // is anything other than one of the allowed kinds of values is followed by
+ // type arguments. The allowed kinds of values are:
+ // - generic types,
+ // - generic constructors, and
+ // - generic functions, including top-level functions, static and instance
+ // members, and local functions.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `i` is a top-level
+ // variable, which isn't one of the allowed cases:
+ //
+ // ```dart
+ // int i = 1;
+ //
+ // void f() {
+ // print([!i!]<int>);
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the referenced value is correct, then remove the type arguments:
+ //
+ // ```dart
+ // int i = 1;
+ //
+ // void f() {
+ // print(i);
+ // }
+ // ```
static const CompileTimeErrorCode DISALLOWED_TYPE_INSTANTIATION_EXPRESSION =
CompileTimeErrorCode(
'DISALLOWED_TYPE_INSTANTIATION_EXPRESSION',
"Only a generic type, generic function, generic instance method, or "
- "generic constructor can be type instantiated.",
+ "generic constructor can have type arguments.",
correctionMessage:
- "Try instantiating the type(s) of a generic type, generic function, "
- "generic instance method, or generic constructor.",
+ "Try removing the type arguments, or instantiating the type(s) of a "
+ "generic type, generic function, generic instance method, or generic "
+ "constructor.",
+ hasPublishedDocs: true,
);
/**
@@ -3629,11 +3726,85 @@
hasPublishedDocs: true,
);
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an enum constant has the same
+ // name as the enum in which it's declared.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the enum constant `E`
+ // has the same name as the enclosing enum `E`:
+ //
+ // ```dart
+ // enum E {
+ // [!E!]
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the name of the enum is correct, then rename the constant:
+ //
+ // ```dart
+ // enum E {
+ // e
+ // }
+ // ```
+ //
+ // If the name of the constant is correct, then rename the enum:
+ //
+ // ```dart
+ // enum F {
+ // E
+ // }
+ // ```
static const CompileTimeErrorCode ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING =
CompileTimeErrorCode(
'ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING',
"The name of the enum constant can't be the same as the enum's name.",
correctionMessage: "Try renaming the constant.",
+ hasPublishedDocs: true,
+ );
+
+ static const CompileTimeErrorCode ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR =
+ CompileTimeErrorCode(
+ 'ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR',
+ "The invoked constructor isn't a const constructor.",
+ correctionMessage: "Try invoking a const generative constructor.",
+ );
+
+ static const CompileTimeErrorCode
+ ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED = CompileTimeErrorCode(
+ 'ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED',
+ "The result of instantiating the enum to bounds is not well-bounded.",
+ correctionMessage: "Try using different bounds for type parameters.",
+ );
+
+ static const CompileTimeErrorCode ENUM_MIXIN_WITH_INSTANCE_VARIABLE =
+ CompileTimeErrorCode(
+ 'ENUM_MIXIN_WITH_INSTANCE_VARIABLE',
+ "Mixins applied to enums can't have instance variables.",
+ correctionMessage: "Try replacing the instance variables with getters.",
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the abstract method
+ * 1: the name of the enclosing enum
+ */
+ static const CompileTimeErrorCode ENUM_WITH_ABSTRACT_MEMBER =
+ CompileTimeErrorCode(
+ 'ENUM_WITH_ABSTRACT_MEMBER',
+ "'{0}' must have a method body because '{1}' is an enum.",
+ correctionMessage: "Try adding a body to '{0}'.",
+ );
+
+ static const CompileTimeErrorCode ENUM_WITH_NAME_VALUES =
+ CompileTimeErrorCode(
+ 'ENUM_WITH_NAME_VALUES',
+ "The name 'values' is not a valid name for an enum.",
+ correctionMessage: "Try using a different name.",
);
/**
@@ -4520,6 +4691,49 @@
hasPublishedDocs: true,
);
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a field or variable marked with
+ // the keyword `external` has an initializer, or when an external field is
+ // initialized in a constructor.
+ //
+ // #### Examples
+ //
+ // The following code produces this diagnostic because the external field `x`
+ // is assigned a value in an initializer:
+ //
+ // ```dart
+ // class C {
+ // external int x;
+ // C() : [!x!] = 0;
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because the external field `x`
+ // has an initializer:
+ //
+ // ```dart
+ // class C {
+ // external final int [!x!] = 0;
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because the external top level
+ // variable `x` has an initializer:
+ //
+ // ```dart
+ // external final int [!x!] = 0;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the initializer:
+ //
+ // ```dart
+ // class C {
+ // external final int x;
+ // }
+ // ```
static const CompileTimeErrorCode EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER =
CompileTimeErrorCode(
'EXTERNAL_WITH_INITIALIZER',
@@ -4527,6 +4741,7 @@
correctionMessage:
"Try removing the field initializer or the 'external' keyword from the "
"field declaration.",
+ hasPublishedDocs: true,
uniqueName: 'EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER',
);
@@ -4536,6 +4751,7 @@
"External fields can't have initializers.",
correctionMessage:
"Try removing the initializer or the 'external' keyword.",
+ hasPublishedDocs: true,
uniqueName: 'EXTERNAL_FIELD_INITIALIZER',
);
@@ -4545,6 +4761,7 @@
"External variables can't have initializers.",
correctionMessage:
"Try removing the initializer or the 'external' keyword.",
+ hasPublishedDocs: true,
uniqueName: 'EXTERNAL_VARIABLE_INITIALIZER',
);
@@ -4902,15 +5119,47 @@
);
/**
- * 7.6.1 Generative Constructors: It is a compile-time error if an
- * initializing formal is used by a function other than a non-redirecting
- * generative constructor.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an initializing formal
+ // parameter is used in the parameter list for anything other than a
+ // constructor.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the initializing
+ // formal parameter `this.x` is being used in the method `m`:
+ //
+ // ```dart
+ // class A {
+ // int x = 0;
+ //
+ // m([[!this.x!] = 0]) {}
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Replace the initializing formal parameter with a normal parameter and
+ // assign the field within the body of the method:
+ //
+ // ```dart
+ // class A {
+ // int x = 0;
+ //
+ // m([int x = 0]) {
+ // this.x = x;
+ // }
+ // }
+ // ```
static const CompileTimeErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR =
CompileTimeErrorCode(
'FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR',
"Initializing formal parameters can only be used in constructors.",
correctionMessage: "Try using a normal parameter.",
+ hasPublishedDocs: true,
);
/**
@@ -5691,6 +5940,63 @@
);
/**
+ * Parameters:
+ * 0: the name of member that cannot be declared
+ */
+ static const CompileTimeErrorCode ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION =
+ CompileTimeErrorCode(
+ 'ILLEGAL_CONCRETE_ENUM_MEMBER',
+ "A concrete instance member named '{0}' can't be declared in a class that "
+ "implements 'Enum'.",
+ correctionMessage: "Try using a different name.",
+ uniqueName: 'ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of member that cannot be inherited
+ * 1: the name of the class that declares the member
+ */
+ static const CompileTimeErrorCode ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE =
+ CompileTimeErrorCode(
+ 'ILLEGAL_CONCRETE_ENUM_MEMBER',
+ "A concrete instance member named '{0}' can't be inherited from '{1}' in a "
+ "class that implements 'Enum'.",
+ correctionMessage: "Try using a different name.",
+ uniqueName: 'ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE',
+ );
+
+ static const CompileTimeErrorCode ILLEGAL_ENUM_VALUES_DECLARATION =
+ CompileTimeErrorCode(
+ 'ILLEGAL_ENUM_VALUES',
+ "An instance member named 'values' can't be declared in a class that "
+ "implements 'Enum'.",
+ correctionMessage: "Try using a different name.",
+ uniqueName: 'ILLEGAL_ENUM_VALUES_DECLARATION',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the class that declares 'values'
+ */
+ static const CompileTimeErrorCode ILLEGAL_ENUM_VALUES_INHERITANCE =
+ CompileTimeErrorCode(
+ 'ILLEGAL_ENUM_VALUES',
+ "An instance member named 'values' can't be inherited from '{0}' in a "
+ "class that implements 'Enum'.",
+ correctionMessage: "Try using a different name.",
+ uniqueName: 'ILLEGAL_ENUM_VALUES_INHERITANCE',
+ );
+
+ static const CompileTimeErrorCode ILLEGAL_LANGUAGE_VERSION_OVERRIDE =
+ CompileTimeErrorCode(
+ 'ILLEGAL_LANGUAGE_VERSION_OVERRIDE',
+ "The language version must be {0}.",
+ correctionMessage:
+ "Try removing the language version override and migrating the code.",
+ );
+
+ /**
* No parameters.
*/
// #### Description
@@ -5901,6 +6207,19 @@
/**
* Parameters:
+ * 0: the name of the superclass
+ */
+ static const CompileTimeErrorCode
+ IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS = CompileTimeErrorCode(
+ 'IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS',
+ "The implicitly invoked unnamed constructor from '{0}' has required "
+ "parameters.",
+ correctionMessage:
+ "Try adding an explicit super initializer with the required arguments.",
+ );
+
+ /**
+ * Parameters:
* 0: the name of the instance member
*/
// #### Description
@@ -5959,28 +6278,6 @@
hasPublishedDocs: true,
);
- static const CompileTimeErrorCode
- IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT =
- CompileTimeErrorCode(
- 'IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT',
- "The named parameter '{0}' is required in the implicitly invoked unnamed "
- "constructor of '{1}'.",
- correctionMessage:
- "Try declaring corresponding named super-parameter, or explicitly "
- "invoking a different constructor.",
- );
-
- static const CompileTimeErrorCode
- IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS =
- CompileTimeErrorCode(
- 'IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS',
- "The implicitly invoked unnamed constructor of '{0}' expects {1} "
- "positional arguments, but {2} found.",
- correctionMessage:
- "Try declaring positional super-parameters, or explicitly invoking a "
- "different constructor.",
- );
-
/**
* Parameters:
* 0: the uri pointing to a library
@@ -6010,17 +6307,46 @@
);
/**
- * 14.1 Imports: It is a compile-time error if the specified URI of an
- * immediate import does not refer to a library declaration.
- *
* Parameters:
* 0: the uri pointing to a non-library declaration
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a [part file][] is imported
+ // into a library.
+ //
+ // #### Example
+ //
+ // Given a [part file][] named `part.dart` containing the following:
+ //
+ // ```dart
+ // %uri="lib/part.dart"
+ // part of lib;
+ //
+ // class C{}
+ // ```
+ //
+ // The following code produces this diagnostic because imported files can't
+ // have a part-of directive:
+ //
+ // ```dart
+ // library lib;
+ //
+ // import [!'part.dart'!];
+ //
+ // C c = C();
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Import the library that contains the [part file][] rather than the
+ // [part file][] itself.
static const CompileTimeErrorCode IMPORT_OF_NON_LIBRARY =
CompileTimeErrorCode(
'IMPORT_OF_NON_LIBRARY',
"The imported library '{0}' can't have a part-of directive.",
correctionMessage: "Try importing the library that the part is a part of.",
+ hasPublishedDocs: true,
);
/**
@@ -6121,18 +6447,51 @@
);
/**
- * It is a compile-time error if a part file has a different language version
- * override than its library.
- *
- * https://github.com/dart-lang/language/blob/master/accepted/
- * future-releases/language-versioning/feature-specification.md
- * #individual-library-language-version-override
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a [part file][] has a language
+ // version override comment that specifies a different language version than
+ // the one being used for the library to which the part belongs.
+ //
+ // #### Example
+ //
+ // Given a [part file][] named `part.dart` that contains the following:
+ //
+ // ```dart
+ // %uri="lib/part.dart"
+ // // @dart = 2.6
+ // part of 'test.dart';
+ // ```
+ //
+ // The following code produces this diagnostic because the parts of a library
+ // must have the same language version as the defining compilation unit:
+ //
+ // ```dart
+ // // @dart = 2.5
+ // part [!'part.dart'!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the language version override from the [part file][], so that it
+ // implicitly uses the same version as the defining compilation unit:
+ //
+ // ```dart
+ // part of 'test.dart';
+ // ```
+ //
+ // If necessary, either adjust the language version override in the defining
+ // compilation unit to be appropriate for the code in the part, or migrate
+ // the code in the [part file][] to be consistent with the new language
+ // version.
static const CompileTimeErrorCode INCONSISTENT_LANGUAGE_VERSION_OVERRIDE =
CompileTimeErrorCode(
'INCONSISTENT_LANGUAGE_VERSION_OVERRIDE',
"Parts must have exactly the same language version override as the "
"library.",
+ hasPublishedDocs: true,
);
/**
@@ -6568,6 +6927,7 @@
// instantiated:
//
// ```dart
+ // // @dart = 2.16
// enum E {a}
//
// var e = [!E!]();
@@ -6579,6 +6939,7 @@
// constants defined in the enum:
//
// ```dart
+ // // @dart = 2.16
// enum E {a}
//
// var e = E.a;
@@ -7499,6 +7860,13 @@
hasPublishedDocs: true,
);
+ static const CompileTimeErrorCode
+ INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR = CompileTimeErrorCode(
+ 'INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR',
+ "Generative enum constructors can only be used as targets of redirection.",
+ correctionMessage: "Try using a factory constructor, or an enum constant.",
+ );
+
/**
* No parameters.
*/
@@ -9154,14 +9522,43 @@
);
/**
- * 7.6.1 Generative Constructors: A generative constructor may be redirecting,
- * in which case its only action is to invoke another generative constructor.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a constructor redirects to more
+ // than one other constructor in the same class (using `this`).
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the unnamed
+ // constructor in `C` is redirecting to both `this.a` and `this.b`:
+ //
+ // ```dart
+ // class C {
+ // C() : this.a(), [!this.b()!];
+ // C.a();
+ // C.b();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove all but one of the redirections:
+ //
+ // ```dart
+ // class C {
+ // C() : this.a();
+ // C.a();
+ // C.b();
+ // }
+ // ```
static const CompileTimeErrorCode
MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS = CompileTimeErrorCode(
'MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS',
- "Constructors can have at most one 'this' redirection.",
+ "Constructors can have only one 'this' redirection, at most.",
correctionMessage: "Try removing all but one of the redirections.",
+ hasPublishedDocs: true,
);
/**
@@ -10141,7 +10538,7 @@
//
// #### Example
//
- // The following code produces this diagnostic beause `a` isn't a constant:
+ // The following code produces this diagnostic because `a` isn't a constant:
//
// ```dart
// var a = 'a';
@@ -10285,6 +10682,13 @@
hasPublishedDocs: true,
);
+ static const CompileTimeErrorCode NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR =
+ CompileTimeErrorCode(
+ 'NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR',
+ "Generative enum constructors must be 'const'.",
+ correctionMessage: "Try adding the keyword 'const'.",
+ );
+
/**
* 13.2 Expression Statements: It is a compile-time error if a non-constant
* map literal that has no explicit type arguments appears in a place where a
@@ -10298,6 +10702,16 @@
);
/**
+ * No parameters.
+ */
+ static const CompileTimeErrorCode NON_FINAL_FIELD_IN_ENUM =
+ CompileTimeErrorCode(
+ 'NON_FINAL_FIELD_IN_ENUM',
+ "Enum can only declare final fields.",
+ correctionMessage: "Try making the field final.",
+ );
+
+ /**
* Parameters:
* 0: the non-generative constructor
*/
@@ -10352,15 +10766,75 @@
);
/**
- * An error code for when a class has no explicit constructor, and therefore
- * a constructor is implicitly defined which uses a factory as a
- * superinitializer. See [NON_GENERATIVE_CONSTRUCTOR].
- *
* Parameters:
* 0: the name of the superclass
* 1: the name of the current class
* 2: the implicitly called factory constructor of the superclass
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a class has an implicit
+ // generative constructor and the superclass has an explicit unnamed factory
+ // constructor. The implicit constructor in the subclass implicitly invokes
+ // the unnamed constructor in the superclass, but generative constructors can
+ // only invoke another generative constructor, not a factory constructor.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the implicit
+ // constructor in `B` invokes the unnamed constructor in `A`, but the
+ // constructor in `A` is a factory constructor, when a generative constructor
+ // is required:
+ //
+ // ```dart
+ // class A {
+ // factory A() => throw 0;
+ // A.named();
+ // }
+ //
+ // class [!B!] extends A {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the unnamed constructor in the superclass can be a generative
+ // constructor, then change it to be a generative constructor:
+ //
+ // ```dart
+ // class A {
+ // A();
+ // A.named();
+ // }
+ //
+ // class B extends A { }
+ // ```
+ //
+ // If the unnamed constructor can't be a generative constructor and there are
+ // other generative constructors in the superclass, then explicitly invoke
+ // one of them:
+ //
+ // ```dart
+ // class A {
+ // factory A() => throw 0;
+ // A.named();
+ // }
+ //
+ // class B extends A {
+ // B() : super.named();
+ // }
+ // ```
+ //
+ // If there are no generative constructors that can be used and none can be
+ // added, then implement the superclass rather than extending it:
+ //
+ // ```dart
+ // class A {
+ // factory A() => throw 0;
+ // A.named();
+ // }
+ //
+ // class B implements A {}
+ // ```
static const CompileTimeErrorCode NON_GENERATIVE_IMPLICIT_CONSTRUCTOR =
CompileTimeErrorCode(
'NON_GENERATIVE_IMPLICIT_CONSTRUCTOR',
@@ -10371,6 +10845,7 @@
"Try adding an explicit constructor that has a different "
"superinitializer or changing the superclass constructor '{2}' to not "
"be a factory constructor.",
+ hasPublishedDocs: true,
);
/**
@@ -11201,24 +11676,80 @@
);
/**
- * User friendly specialized error for [NON_GENERATIVE_CONSTRUCTOR]. This
- * handles the case of `class E extends Exception` which will never work
- * because [Exception] has no generative constructors.
- *
* Parameters:
* 0: the name of the subclass
* 1: the name of the superclass
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a class that has at least one
+ // generative constructor (whether explicit or implicit) has a superclass
+ // that doesn't have any generative constructors. Every generative
+ // constructor, except the one defined in `Object`, invokes, either
+ // explicitly or implicitly, one of the generative constructors from its
+ // superclass.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the class `B` has an
+ // implicit generative constructor that can't invoke a generative constructor
+ // from `A` because `A` doesn't have any generative constructors:
+ //
+ // ```dart
+ // class A {
+ // factory A.none() => throw '';
+ // }
+ //
+ // class B extends [!A!] {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the superclass should have a generative constructor, then add one:
+ //
+ // ```dart
+ // class A {
+ // A();
+ // factory A.none() => throw '';
+ // }
+ //
+ // class B extends A {}
+ // ```
+ //
+ // If the subclass shouldn't have a generative constructor, then remove it by
+ // adding a factory constructor:
+ //
+ // ```dart
+ // class A {
+ // factory A.none() => throw '';
+ // }
+ //
+ // class B extends A {
+ // factory B.none() => throw '';
+ // }
+ // ```
+ //
+ // If the subclass must have a generative constructor but the superclass
+ // can't have one, then implement the superclass instead:
+ //
+ // ```dart
+ // class A {
+ // factory A.none() => throw '';
+ // }
+ //
+ // class B implements A {}
+ // ```
static const CompileTimeErrorCode NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS =
CompileTimeErrorCode(
'NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS',
- "The class '{0}' cannot extend '{1}' because '{1}' only has factory "
+ "The class '{0}' can't extend '{1}' because '{1}' only has factory "
"constructors (no generative constructors), and '{0}' has at least one "
"generative constructor.",
correctionMessage:
"Try implementing the class instead, adding a generative (not factory) "
- "constructor to the superclass {0}, or a factory constructor to the "
+ "constructor to the superclass '{1}', or a factory constructor to the "
"subclass.",
+ hasPublishedDocs: true,
);
/**
@@ -11520,8 +12051,8 @@
// If the library should be using a different file as a part, then change the
// URI in the part directive to be the URI of the other file.
//
- // If the part file should be a part of this library, then update the URI (or
- // library name) in the part-of directive to be the URI (or name) of the
+ // If the [part file][] should be a part of this library, then update the URI
+ // (or library name) in the part-of directive to be the URI (or name) of the
// correct library.
static const CompileTimeErrorCode PART_OF_DIFFERENT_LIBRARY =
CompileTimeErrorCode(
@@ -11590,13 +12121,14 @@
// #### Description
//
// The analyzer produces this diagnostic when a library that doesn't have a
- // `library` directive (and hence has no name) contains a `part` directive and
- // the `part of` directive in the part file uses a name to specify the library
- // that it's a part of.
+ // `library` directive (and hence has no name) contains a `part` directive
+ // and the `part of` directive in the [part file][] uses a name to specify
+ // the library that it's a part of.
//
// #### Example
//
- // Given a part file named `part_file.dart` containing the following code:
+ // Given a [part file][] named `part_file.dart` containing the following
+ // code:
//
// ```dart
// %uri="lib/part_file.dart"
@@ -11604,8 +12136,8 @@
// ```
//
// The following code produces this diagnostic because the library including
- // the part file doesn't have a name even though the part file uses a name to
- // specify which library it's a part of:
+ // the [part file][] doesn't have a name even though the [part file][] uses a
+ // name to specify which library it's a part of:
//
// ```dart
// part [!'part_file.dart'!];
@@ -11613,8 +12145,8 @@
//
// #### Common fixes
//
- // Change the `part of` directive in the part file to specify its library by
- // URI:
+ // Change the `part of` directive in the [part file][] to specify its library
+ // by URI:
//
// ```dart
// part of 'test.dart';
@@ -11742,22 +12274,61 @@
);
/**
- * From the `Static Types` section of the spec:
- *
- * A type T is malformed if:
- * - T has the form id or the form prefix.id, and in the enclosing lexical
- * scope, the name id (respectively prefix.id) does not denote a type.
- *
- * In particular, this means that if an import prefix is shadowed by a local
- * declaration, it is an error to try to use it as a prefix for a type name.
+ * Parameters:
+ * 0: the prefix being shadowed
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an import prefix is used in a
+ // context where it isn't visible because it was shadowed by a local
+ // declaration.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the prefix `a` is
+ // being used to access the class `Future`, but isn't visible because it's
+ // shadowed by the parameter `a`:
+ //
+ // ```dart
+ // import 'dart:async' as a;
+ //
+ // a.Future? f(int a) {
+ // [!a!].Future? x;
+ // return x;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Rename either the prefix:
+ //
+ // ```dart
+ // import 'dart:async' as p;
+ //
+ // p.Future? f(int a) {
+ // p.Future? x;
+ // return x;
+ // }
+ // ```
+ //
+ // Or rename the local variable:
+ //
+ // ```dart
+ // import 'dart:async' as a;
+ //
+ // a.Future? f(int p) {
+ // a.Future? x;
+ // return x;
+ // }
+ // ```
static const CompileTimeErrorCode PREFIX_SHADOWED_BY_LOCAL_DECLARATION =
CompileTimeErrorCode(
'PREFIX_SHADOWED_BY_LOCAL_DECLARATION',
- "The prefix '{0}' can't be used here because it is shadowed by a local "
+ "The prefix '{0}' can't be used here because it's shadowed by a local "
"declaration.",
correctionMessage:
"Try renaming either the prefix or the local declaration.",
+ hasPublishedDocs: true,
);
/**
@@ -11853,20 +12424,97 @@
hasPublishedDocs: true,
);
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a private setter is used in a
+ // library where it isn't visible.
+ //
+ // #### Example
+ //
+ // Given a file named `a.dart` that contains the following:
+ //
+ // ```dart
+ // %uri="lib/a.dart"
+ // class A {
+ // static int _f = 0;
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because it references the
+ // private setter `_f` even though the setter isn't visible:
+ //
+ // ```dart
+ // import 'a.dart';
+ //
+ // void f() {
+ // A.[!_f!] = 0;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you're able to make the setter public, then do so:
+ //
+ // ```dart
+ // %uri="lib/a.dart"
+ // class A {
+ // static int f = 0;
+ // }
+ // ```
+ //
+ // If you aren't able to make the setter public, then find a different way to
+ // implement the code.
static const CompileTimeErrorCode PRIVATE_SETTER = CompileTimeErrorCode(
'PRIVATE_SETTER',
- "The setter '{0}' is private and can't be accessed outside of the library "
+ "The setter '{0}' is private and can't be accessed outside the library "
"that declares it.",
correctionMessage: "Try making it public.",
+ hasPublishedDocs: true,
);
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a final local variable that
+ // isn't initialized at the declaration site is read at a point where the
+ // compiler can't prove that the variable is always initialized before it's
+ // referenced.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the final local
+ // variable `x` is read (on line 3) when it's possible that it hasn't yet
+ // been initialized:
+ //
+ // ```dart
+ // int f() {
+ // final int x;
+ // return [!x!];
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Ensure that the variable has been initialized before it's read:
+ //
+ // ```dart
+ // int f(bool b) {
+ // final int x;
+ // if (b) {
+ // x = 0;
+ // } else {
+ // x = 1;
+ // }
+ // return x;
+ // }
+ // ```
static const CompileTimeErrorCode READ_POTENTIALLY_UNASSIGNED_FINAL =
CompileTimeErrorCode(
'READ_POTENTIALLY_UNASSIGNED_FINAL',
- "The final variable '{0}' can't be read because it is potentially "
+ "The final variable '{0}' can't be read because it's potentially "
"unassigned at this point.",
correctionMessage:
"Ensure that it is assigned on necessary execution paths.",
+ hasPublishedDocs: true,
);
/**
@@ -12222,15 +12870,51 @@
);
/**
- * A factory constructor can't redirect to a non-generative constructor of an
- * abstract class.
+ * Parameters:
+ * 0: the name of the redirecting constructor
+ * 1: the name of the abstract class defining the constructor being redirected to
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a constructor redirects to a
+ // constructor in an abstract class.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the factory
+ // constructor in `A` redirects to a constructor in `B`, but `B` is an
+ // abstract class:
+ //
+ // ```dart
+ // class A {
+ // factory A() = [!B!];
+ // }
+ //
+ // abstract class B implements A {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the code redirects to the correct constructor, then change the class so
+ // that it isn't abstract:
+ //
+ // ```dart
+ // class A {
+ // factory A() = B;
+ // }
+ //
+ // class B implements A {}
+ // ```
+ //
+ // Otherwise, change the factory constructor so that it either redirects to a
+ // constructor in a concrete class, or has a concrete implementation.
static const CompileTimeErrorCode REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR =
CompileTimeErrorCode(
'REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR',
"The redirecting constructor '{0}' can't redirect to a constructor of the "
"abstract class '{1}'.",
correctionMessage: "Try redirecting to a constructor of a different class.",
+ hasPublishedDocs: true,
);
/**
@@ -12377,9 +13061,57 @@
);
/**
- * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with
- * the const modifier but <i>k'</i> is not a constant constructor.
+ * Parameters:
+ * 0: the name of the constructor
+ * 1: the name of the class containing the constructor
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a constructor redirects to a
+ // constructor that doesn't exist.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the factory
+ // constructor in `A` redirects to a constructor in `B` that doesn't exist:
+ //
+ // ```dart
+ // class A {
+ // factory A() = [!B.name!];
+ // }
+ //
+ // class B implements A {
+ // B();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the constructor being redirected to is correct, then define the
+ // constructor:
+ //
+ // ```dart
+ // class A {
+ // factory A() = B.name;
+ // }
+ //
+ // class B implements A {
+ // B();
+ // B.name();
+ // }
+ // ```
+ //
+ // If a different constructor should be invoked, then update the redirect:
+ //
+ // ```dart
+ // class A {
+ // factory A() = B;
+ // }
+ //
+ // class B implements A {
+ // B();
+ // }
+ // ```
static const CompileTimeErrorCode REDIRECT_TO_MISSING_CONSTRUCTOR =
CompileTimeErrorCode(
'REDIRECT_TO_MISSING_CONSTRUCTOR',
@@ -12387,6 +13119,7 @@
correctionMessage:
"Try redirecting to a different constructor, or define the constructor "
"named '{0}'.",
+ hasPublishedDocs: true,
);
/**
@@ -13190,6 +13923,13 @@
hasPublishedDocs: true,
);
+ static const CompileTimeErrorCode SUPER_IN_ENUM_CONSTRUCTOR =
+ CompileTimeErrorCode(
+ 'SUPER_IN_ENUM_CONSTRUCTOR',
+ "The enum constructor can't have a 'super' initializer.",
+ correctionMessage: "Try removing the 'super' invocation.",
+ );
+
/**
* No parameters.
*/
@@ -13295,17 +14035,46 @@
);
/**
- * It is an error if any case of a switch statement except the last case (the
- * default case if present) may complete normally. The previous syntactic
- * restriction requiring the last statement of each case to be one of an
- * enumerated list of statements (break, continue, return, throw, or rethrow)
- * is removed.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the statements following a
+ // `case` label in a `switch` statement could fall through to the next `case`
+ // or `default` label.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the `case` label with
+ // a value of zero (`0`) falls through to the `default` statements:
+ //
+ // ```dart
+ // void f(int a) {
+ // switch (a) {
+ // [!case!] 0:
+ // print(0);
+ // default:
+ // return;
+ // }
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Change the flow of control so that the `case` won't fall through. There
+ // are several ways that this can be done, including adding one of the
+ // following at the end of the current list of statements:
+ // - a `return` statement,
+ // - a `throw` expression,
+ // - a `break` statement,
+ // - a `continue`, or
+ // - an invocation of a function or method whose return type is `Never`.
static const CompileTimeErrorCode SWITCH_CASE_COMPLETES_NORMALLY =
CompileTimeErrorCode(
'SWITCH_CASE_COMPLETES_NORMALLY',
- "The 'case' should not complete normally.",
- correctionMessage: "Try adding 'break', or 'return', etc.",
+ "The 'case' shouldn't complete normally.",
+ correctionMessage: "Try adding 'break', 'return', or 'throw'.",
+ hasPublishedDocs: true,
);
/**
@@ -14169,8 +14938,8 @@
/**
* Parameters:
- * 0: the name of the enumeration constant that is not defined
- * 1: the name of the enumeration used to access the constant
+ * 0: the name of the enum constant that is not defined
+ * 1: the name of the enum used to access the constant
*/
// #### Description
//
@@ -14220,6 +14989,30 @@
/**
* Parameters:
+ * 0: the name of the constructor that is undefined
+ */
+ static const CompileTimeErrorCode UNDEFINED_ENUM_CONSTRUCTOR_NAMED =
+ CompileTimeErrorCode(
+ 'UNDEFINED_ENUM_CONSTRUCTOR',
+ "The enum doesn't have a constructor named '{0}'.",
+ correctionMessage:
+ "Try correcting the name to the name of an existing constructor, or "
+ "defining constructor with the name '{0}'.",
+ uniqueName: 'UNDEFINED_ENUM_CONSTRUCTOR_NAMED',
+ );
+
+ static const CompileTimeErrorCode UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED =
+ CompileTimeErrorCode(
+ 'UNDEFINED_ENUM_CONSTRUCTOR',
+ "The enum doesn't have an unnamed constructor.",
+ correctionMessage:
+ "Try adding the name of an existing constructor, or defining an "
+ "unnamed constructor.",
+ uniqueName: 'UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED',
+ );
+
+ /**
+ * Parameters:
* 0: the name of the getter that is undefined
* 1: the name of the extension that was explicitly specified
*/
@@ -15447,6 +16240,13 @@
hasPublishedDocs: true,
);
+ static const CompileTimeErrorCode VALUES_DECLARATION_IN_ENUM =
+ CompileTimeErrorCode(
+ 'VALUES_DECLARATION_IN_ENUM',
+ "A member named 'values' can't be declared in an enum.",
+ correctionMessage: "Try using a different name.",
+ );
+
/**
* Parameters:
* 0: the type of the object being assigned.
@@ -15759,6 +16559,19 @@
/**
* Parameters:
+ * 0: the number of type parameters that were declared
+ * 1: the number of type arguments provided
+ */
+ static const CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM =
+ CompileTimeErrorCode(
+ 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM',
+ "The enum is declared with {0} type parameters, but {1} type arguments "
+ "were given.",
+ correctionMessage: "Try adjusting the number of type arguments.",
+ );
+
+ /**
+ * Parameters:
* 0: the name of the extension being referenced
* 1: the number of type parameters that were declared
* 2: the number of type arguments provided
@@ -16404,7 +17217,7 @@
// #### Description
//
// The analyzer produces this diagnostic when a `switch` statement for an enum
- // doesn't include an option for one of the values in the enumeration.
+ // doesn't include an option for one of the values in the enum.
//
// Note that `null` is always a possible value for an enum and therefore also
// must be handled.
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index 2978a39..496f77d 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -17,7 +17,7 @@
bool _isInNativeClass = false;
/// When a new class or mixin is entered, [_initFieldsMap] initializes this
- /// map, and [leaveClassOrMixin] resets it.
+ /// map, and [leaveClass] resets it.
///
/// [_InitState.notInit] or [_InitState.initInDeclaration] is set for each
/// field. Later [verify] is called to verify each constructor of the class.
@@ -35,9 +35,17 @@
}) : _typeSystem = typeSystem,
_errorReporter = errorReporter;
- void enterClass(ClassDeclaration node) {
+ void enterClass(ClassDeclaration node, ClassElementImpl element) {
_isInNativeClass = node.nativeClause != null;
- _initFieldsMap(node.declaredElement!);
+ _initFieldsMap(element.fields);
+ }
+
+ void enterEnum(EnumDeclaration node, EnumElementImpl element) {
+ _isInNativeClass = false;
+ _initFieldsMap(
+ element.fields,
+ enumConstants: element.constants,
+ );
}
void leaveClass() {
@@ -55,7 +63,7 @@
return;
}
- if (node.parent is! ClassDeclaration) {
+ if (!(node.parent is ClassDeclaration || node.parent is EnumDeclaration)) {
return;
}
@@ -93,13 +101,27 @@
_reportNotInitializedNonNullable(node, notInitNonNullableFields);
}
- void _initFieldsMap(ClassElement element) {
+ void _initFieldsMap(
+ List<FieldElement> fields, {
+ List<FieldElement>? enumConstants,
+ }) {
_initialFieldMap = <FieldElement, _InitState>{};
- for (var field in element.fields) {
- if (!field.isSynthetic) {
- _initialFieldMap![field] = field.hasInitializer
- ? _InitState.initInDeclaration
- : _InitState.notInit;
+
+ for (var field in fields) {
+ if (field.isSynthetic) {
+ continue;
+ }
+ if (enumConstants != null && field.name == 'index') {
+ continue;
+ }
+ _initialFieldMap![field] = field.hasInitializer
+ ? _InitState.initInDeclaration
+ : _InitState.notInit;
+ }
+
+ if (enumConstants != null) {
+ for (var field in enumConstants) {
+ _initialFieldMap![field] = _InitState.initInDeclaration;
}
}
}
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 113dae0..623f429 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -8,21 +8,20 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/error/codes.dart';
class DuplicateDefinitionVerifier {
- static final Set<String> _enumInstanceMembers = {
- 'hashCode',
- 'index',
- FunctionElement.NO_SUCH_METHOD_METHOD_NAME,
- 'runtimeType',
- 'toString',
- };
-
+ final InheritanceManager3 _inheritanceManager;
final LibraryElement _currentLibrary;
final ErrorReporter _errorReporter;
- DuplicateDefinitionVerifier(this._currentLibrary, this._errorReporter);
+ DuplicateDefinitionVerifier(
+ this._inheritanceManager,
+ this._currentLibrary,
+ this._errorReporter,
+ );
/// Check that the exception and stack trace parameters have different names.
void checkCatchClause(CatchClause node) {
@@ -45,31 +44,132 @@
/// Check that there are no members with the same name.
void checkEnum(EnumDeclaration node) {
- ClassElement element = node.declaredElement!;
+ var enumElement = node.declaredElement as EnumElementImpl;
+ var enumName = enumElement.name;
- Map<String, Element> staticGetters = {
- 'values': element.getGetter('values')!
- };
+ var constructorNames = <String>{};
+ var instanceGetters = <String, Element>{};
+ var instanceSetters = <String, Element>{};
+ var staticGetters = <String, Element>{};
+ var staticSetters = <String, Element>{};
for (EnumConstantDeclaration constant in node.constants) {
_checkDuplicateIdentifier(staticGetters, constant.name);
+ _checkValuesDeclarationInEnum(constant.name);
}
- String enumName = element.name;
- for (EnumConstantDeclaration constant in node.constants) {
- SimpleIdentifier identifier = constant.name;
- String name = identifier.name;
- if (name == enumName) {
+ for (var member in node.members) {
+ if (member is ConstructorDeclaration) {
+ if (member.returnType.name == enumElement.name) {
+ var name = member.declaredElement!.name;
+ if (!constructorNames.add(name)) {
+ if (name.isEmpty) {
+ _errorReporter.reportErrorForName(
+ CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
+ member,
+ );
+ } else {
+ _errorReporter.reportErrorForName(
+ CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
+ member,
+ arguments: [name],
+ );
+ }
+ }
+ }
+ } else if (member is FieldDeclaration) {
+ for (var field in member.fields.variables) {
+ var identifier = field.name;
+ _checkDuplicateIdentifier(
+ member.isStatic ? staticGetters : instanceGetters,
+ identifier,
+ setterScope: member.isStatic ? staticSetters : instanceSetters,
+ );
+ _checkValuesDeclarationInEnum(identifier);
+ }
+ } else if (member is MethodDeclaration) {
+ _checkDuplicateIdentifier(
+ member.isStatic ? staticGetters : instanceGetters,
+ member.name,
+ setterScope: member.isStatic ? staticSetters : instanceSetters,
+ );
+ _checkValuesDeclarationInEnum(member.name);
+ }
+ }
+
+ if (enumName == 'values') {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ENUM_WITH_NAME_VALUES,
+ node.name,
+ );
+ }
+
+ for (var constant in node.constants) {
+ if (constant.name.name == enumName) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
- identifier,
+ constant.name,
);
- } else if (_enumInstanceMembers.contains(name)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
- identifier,
- [enumName, name, enumName],
- );
+ }
+ }
+
+ _checkConflictingConstructorAndStatic(
+ classElement: enumElement,
+ staticGetters: staticGetters,
+ staticSetters: staticSetters,
+ );
+
+ for (var accessor in enumElement.accessors) {
+ var baseName = accessor.displayName;
+ if (accessor.isStatic) {
+ var instance = _getInterfaceMember(enumElement, baseName);
+ if (instance != null && baseName != 'values') {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
+ accessor,
+ [enumName, baseName, enumName],
+ );
+ }
+ } else {
+ var inherited = _getInheritedMember(enumElement, baseName);
+ if (inherited is MethodElement) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD,
+ accessor,
+ [
+ enumElement.displayName,
+ baseName,
+ inherited.enclosingElement.displayName,
+ ],
+ );
+ }
+ }
+ }
+
+ for (var method in enumElement.methods) {
+ var baseName = method.displayName;
+ if (method.isStatic) {
+ var instance = _getInterfaceMember(enumElement, baseName);
+ if (instance != null) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
+ method,
+ [enumName, baseName, enumName],
+ );
+ }
+ } else {
+ var inherited = _getInheritedMember(enumElement, baseName);
+ if (inherited is PropertyAccessorElement) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
+ method,
+ [
+ enumElement.displayName,
+ baseName,
+ inherited.enclosingElement.displayName,
+ ],
+ );
+ }
}
}
}
@@ -297,37 +397,17 @@
}
}
+ _checkConflictingConstructorAndStatic(
+ classElement: element,
+ staticGetters: staticGetters,
+ staticSetters: staticSetters,
+ );
+
// Check for local static members conflicting with local instance members.
+ // TODO(scheglov) This code is duplicated for enums. But for classes it is
+ // separated also into ErrorVerifier - where we check inherited.
for (ClassMember member in members) {
- if (member is ConstructorDeclaration) {
- var nameNode = member.name;
- if (nameNode != null) {
- String name = nameNode.name;
- var staticMember = staticGetters[name] ?? staticSetters[name];
- if (staticMember != null) {
- if (staticMember is PropertyAccessorElement) {
- CompileTimeErrorCode errorCode;
- if (staticMember.isSynthetic) {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD;
- } else if (staticMember.isGetter) {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER;
- } else {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER;
- }
- _errorReporter.reportErrorForNode(errorCode, nameNode, [name]);
- } else {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
- nameNode,
- [name],
- );
- }
- }
- }
- } else if (member is FieldDeclaration) {
+ if (member is FieldDeclaration) {
if (member.isStatic) {
for (VariableDeclaration field in member.fields.variables) {
SimpleIdentifier identifier = field.name;
@@ -359,6 +439,37 @@
}
}
+ void _checkConflictingConstructorAndStatic({
+ required ClassElement classElement,
+ required Map<String, Element> staticGetters,
+ required Map<String, Element> staticSetters,
+ }) {
+ for (var constructor in classElement.constructors) {
+ var name = constructor.name;
+ var staticMember = staticGetters[name] ?? staticSetters[name];
+ if (staticMember is PropertyAccessorElement) {
+ CompileTimeErrorCode errorCode;
+ if (staticMember.isSynthetic) {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD;
+ } else if (staticMember.isGetter) {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER;
+ } else {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER;
+ }
+ _errorReporter.reportErrorForElement(errorCode, constructor, [name]);
+ } else if (staticMember is MethodElement) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
+ constructor,
+ [name],
+ );
+ }
+ }
+ }
+
/// Check whether the given [element] defined by the [identifier] is already
/// in one of the scopes - [getterScope] or [setterScope], and produce an
/// error if it is.
@@ -425,6 +536,43 @@
}
}
+ void _checkValuesDeclarationInEnum(SimpleIdentifier name) {
+ if (name.name == 'values') {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM,
+ name,
+ );
+ }
+ }
+
+ ExecutableElement? _getInheritedMember(
+ ClassElement element, String baseName) {
+ var libraryUri = _currentLibrary.source.uri;
+
+ var getterName = Name(libraryUri, baseName);
+ var getter = _inheritanceManager.getInherited2(element, getterName);
+ if (getter != null) {
+ return getter;
+ }
+
+ var setterName = Name(libraryUri, '$baseName=');
+ return _inheritanceManager.getInherited2(element, setterName);
+ }
+
+ ExecutableElement? _getInterfaceMember(
+ ClassElement element, String baseName) {
+ var libraryUri = _currentLibrary.source.uri;
+
+ var getterName = Name(libraryUri, baseName);
+ var getter = _inheritanceManager.getMember2(element, getterName);
+ if (getter != null) {
+ return getter;
+ }
+
+ var setterName = Name(libraryUri, '$baseName=');
+ return _inheritanceManager.getMember2(element, setterName);
+ }
+
static bool _isGetterSetterPair(Element a, Element b) {
if (a is PropertyAccessorElement && b is PropertyAccessorElement) {
return a.isGetter && b.isSetter || a.isSetter && b.isGetter;
diff --git a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
index 76860af..f835414 100644
--- a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
+++ b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
@@ -32,42 +31,14 @@
bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
- void checkExtension(ExtensionDeclaration node) {
- for (var getterNode in node.members) {
- if (getterNode is MethodDeclaration && getterNode.isGetter) {
- checkGetter(getterNode.name,
- getterNode.declaredElement as PropertyAccessorElement);
+ void checkExtension(ExtensionElement element) {
+ for (var getter in element.accessors) {
+ if (getter.isGetter) {
+ _checkLocalGetter(getter);
}
}
}
- void checkGetter(
- SimpleIdentifier nameNode,
- PropertyAccessorElement getter,
- ) {
- assert(getter.isGetter);
-
- var setter = getter.correspondingSetter;
- if (setter == null) {
- return;
- }
-
- var getterType = _getGetterType(getter);
- var setterType = _getSetterType(setter);
- if (setterType == null) {
- return;
- }
-
- if (!_match(getterType, setterType)) {
- var name = nameNode.name;
- _errorReporter.reportErrorForNode(
- _errorCode,
- nameNode,
- [name, getterType, setterType, name],
- );
- }
- }
-
void checkInterface(ClassElement classElement, Interface interface) {
var libraryUri = classElement.library.source.uri;
@@ -113,6 +84,33 @@
}
}
+ void checkStaticAccessors(List<PropertyAccessorElement> accessors) {
+ for (var getter in accessors) {
+ if (getter.isStatic && getter.isGetter) {
+ _checkLocalGetter(getter);
+ }
+ }
+ }
+
+ void _checkLocalGetter(PropertyAccessorElement getter) {
+ assert(getter.isGetter);
+ var setter = getter.correspondingSetter;
+ if (setter != null) {
+ var getterType = _getGetterType(getter);
+ var setterType = _getSetterType(setter);
+ if (setterType != null) {
+ if (!_match(getterType, setterType)) {
+ var name = getter.name;
+ _errorReporter.reportErrorForElement(
+ _errorCode,
+ getter,
+ [name, getterType, setterType, name],
+ );
+ }
+ }
+ }
+ }
+
bool _match(DartType getterType, DartType setterType) {
return _isNonNullableByDefault
? _typeSystem.isSubtypeOf(getterType, setterType)
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index b6d1951..0e38986 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -45,7 +45,7 @@
classNameNode: declaration.name,
implementsClause: declaration.implementsClause,
members: declaration.members,
- superclass: declaration.extendsClause?.superclass2,
+ superclass: declaration.extendsClause?.superclass,
withClause: declaration.withClause,
).verify();
} else if (declaration is ClassTypeAlias) {
@@ -58,7 +58,20 @@
library: library,
classNameNode: declaration.name,
implementsClause: declaration.implementsClause,
- superclass: declaration.superclass2,
+ superclass: declaration.superclass,
+ withClause: declaration.withClause,
+ ).verify();
+ } else if (declaration is EnumDeclaration) {
+ _ClassVerifier(
+ typeSystem: _typeSystem,
+ typeProvider: _typeProvider,
+ inheritance: _inheritance,
+ reporter: _reporter,
+ featureSet: unit.featureSet,
+ library: library,
+ classNameNode: declaration.name,
+ implementsClause: declaration.implementsClause,
+ members: declaration.members,
withClause: declaration.withClause,
).verify();
} else if (declaration is MixinDeclaration) {
@@ -94,7 +107,7 @@
final FeatureSet featureSet;
final LibraryElementImpl library;
final Uri libraryUri;
- final ClassElementImpl classElement;
+ final AbstractClassElementImpl classElement;
final SimpleIdentifier classNameNode;
final List<ClassMember> members;
@@ -105,6 +118,9 @@
final List<InterfaceType> directSuperInterfaces = [];
+ late final implementsDartCoreEnum =
+ classElement.allSupertypes.any((e) => e.isDartCoreEnum);
+
_ClassVerifier({
required this.typeSystem,
required this.typeProvider,
@@ -119,7 +135,7 @@
this.superclass,
this.withClause,
}) : libraryUri = library.source.uri,
- classElement = classNameNode.staticElement as ClassElementImpl;
+ classElement = classNameNode.staticElement as AbstractClassElementImpl;
bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
@@ -128,6 +144,16 @@
return;
}
+ if (!classElement.isEnum &&
+ !classElement.isAbstract &&
+ implementsDartCoreEnum) {
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE,
+ classNameNode,
+ );
+ return;
+ }
+
if (_checkForRecursiveInterfaceInheritance(classElement)) {
return;
}
@@ -152,7 +178,7 @@
// class C extends S&M2 { ...members of C... }
// So, we need to check members of each mixin against superinterfaces
// of `S`, and superinterfaces of all previous mixins.
- var mixinNodes = withClause?.mixinTypes2;
+ var mixinNodes = withClause?.mixinTypes;
var mixinTypes = classElement.mixins;
for (var i = 0; i < mixinTypes.length; i++) {
var mixinType = mixinTypes[i];
@@ -171,6 +197,12 @@
var fieldElement = field.declaredElement as FieldElement;
_checkDeclaredMember(field.name, libraryUri, fieldElement.getter);
_checkDeclaredMember(field.name, libraryUri, fieldElement.setter);
+ if (!member.isStatic && !classElement.isEnum) {
+ _checkIllegalEnumValuesDeclaration(field.name);
+ }
+ if (!member.isStatic) {
+ _checkIllegalConcreteEnumMemberDeclaration(field.name);
+ }
}
} else if (member is MethodDeclaration) {
var hasError = _reportNoCombinedSuperSignature(member);
@@ -180,9 +212,18 @@
_checkDeclaredMember(member.name, libraryUri, member.declaredElement,
methodParameterNodes: member.parameters?.parameters);
+ if (!(member.isStatic || member.isAbstract || member.isSetter)) {
+ _checkIllegalConcreteEnumMemberDeclaration(member.name);
+ }
+ if (!member.isStatic && !classElement.isEnum) {
+ _checkIllegalEnumValuesDeclaration(member.name);
+ }
}
}
+ _checkIllegalConcreteEnumMemberInheritance();
+ _checkIllegalEnumValuesInheritance();
+
GetterSetterTypesVerifier(
typeSystem: typeSystem,
errorReporter: reporter,
@@ -201,10 +242,16 @@
// No concrete implementation of the name.
if (concreteElement == null) {
- if (!_reportConcreteClassWithAbstractMember(name.name)) {
- inheritedAbstract ??= [];
- inheritedAbstract.add(interfaceElement);
+ if (_reportConcreteClassWithAbstractMember(name.name)) {
+ continue;
}
+ // We already reported ILLEGAL_ENUM_VALUES_INHERITANCE.
+ if (classElement.isEnum &&
+ const {'values', 'values='}.contains(name.name)) {
+ continue;
+ }
+ inheritedAbstract ??= [];
+ inheritedAbstract.add(interfaceElement);
continue;
}
@@ -332,8 +379,25 @@
}
DartType type = namedType.typeOrThrow;
- if (type is InterfaceType &&
- typeProvider.isNonSubtypableClass(type.element)) {
+ if (type is! InterfaceType) {
+ return false;
+ }
+
+ var interfaceElement = type.element;
+
+ if (interfaceElement.isDartCoreEnum &&
+ library.featureSet.isEnabled(Feature.enhanced_enums)) {
+ if (classElement.isAbstract || classElement.isEnum) {
+ return false;
+ }
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE,
+ namedType,
+ );
+ return true;
+ }
+
+ if (typeProvider.isNonSubtypableClass(interfaceElement)) {
reporter.reportErrorForNode(errorCode, namedType, [type]);
return true;
}
@@ -347,7 +411,7 @@
bool _checkDirectSuperTypes() {
var hasError = false;
if (implementsClause != null) {
- for (var namedType in implementsClause!.interfaces2) {
+ for (var namedType in implementsClause!.interfaces) {
if (_checkDirectSuperType(
namedType,
CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
@@ -357,7 +421,7 @@
}
}
if (onClause != null) {
- for (var namedType in onClause!.superclassConstraints2) {
+ for (var namedType in onClause!.superclassConstraints) {
if (_checkDirectSuperType(
namedType,
CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
@@ -375,18 +439,43 @@
}
}
if (withClause != null) {
- for (var namedType in withClause!.mixinTypes2) {
+ for (var namedType in withClause!.mixinTypes) {
if (_checkDirectSuperType(
namedType,
CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
)) {
hasError = true;
}
+ if (classElement.isEnum && _checkEnumMixin(namedType)) {
+ hasError = true;
+ }
}
}
return hasError;
}
+ bool _checkEnumMixin(NamedType namedType) {
+ DartType type = namedType.typeOrThrow;
+ if (type is! InterfaceType) {
+ return false;
+ }
+
+ var interfaceElement = type.element;
+ if (interfaceElement.isEnum) {
+ return false;
+ }
+
+ if (interfaceElement.fields.every((e) => e.isStatic || e.isSynthetic)) {
+ return false;
+ }
+
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.ENUM_MIXIN_WITH_INSTANCE_VARIABLE,
+ namedType,
+ );
+ return true;
+ }
+
void _checkForOptionalParametersDifferentDefaultValues(
MethodElement baseExecutable,
MethodElement derivedExecutable,
@@ -557,6 +646,81 @@
return false;
}
+ void _checkIllegalConcreteEnumMemberDeclaration(SimpleIdentifier name) {
+ if (implementsDartCoreEnum &&
+ const {'index', 'hashCode', '=='}.contains(name.name)) {
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION,
+ name,
+ [name.name],
+ );
+ }
+ }
+
+ void _checkIllegalConcreteEnumMemberInheritance() {
+ // We ignore mixins because they don't inherit and members.
+ // But to support `super.foo()` invocations we put members from superclass
+ // constraints into the `superImplemented` bucket, the same we look below.
+ if (classElement.isMixin) {
+ return;
+ }
+
+ if (implementsDartCoreEnum) {
+ var concreteMap = inheritance.getInheritedConcreteMap2(classElement);
+
+ void checkSingle(
+ String memberName,
+ bool Function(ClassElement enclosingClass) filter,
+ ) {
+ var member = concreteMap[Name(libraryUri, memberName)];
+ if (member != null) {
+ var enclosingClass = member.enclosingElement;
+ if (enclosingClass is ClassElement && filter(enclosingClass)) {
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE,
+ classNameNode,
+ [memberName, enclosingClass.name],
+ );
+ }
+ }
+ }
+
+ checkSingle('hashCode', (e) => !e.isDartCoreObject);
+ checkSingle('==', (e) => !e.isDartCoreObject);
+ checkSingle('index', (e) => !e.isDartCoreEnum);
+ }
+ }
+
+ void _checkIllegalEnumValuesDeclaration(SimpleIdentifier name) {
+ if (implementsDartCoreEnum && name.name == 'values') {
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION,
+ name,
+ );
+ }
+ }
+
+ void _checkIllegalEnumValuesInheritance() {
+ if (implementsDartCoreEnum) {
+ var getter = inheritance.getInherited2(
+ classElement,
+ Name(libraryUri, 'values'),
+ );
+ var setter = inheritance.getInherited2(
+ classElement,
+ Name(libraryUri, 'values='),
+ );
+ var inherited = getter ?? setter;
+ if (inherited != null) {
+ reporter.reportErrorForNode(
+ CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE,
+ classNameNode,
+ [inherited.enclosingElement.name!],
+ );
+ }
+ }
+ }
+
/// Return the error code that should be used when the given class [element]
/// references itself directly.
ErrorCode _getRecursiveErrorCode(ClassElement element) {
@@ -587,9 +751,12 @@
bool checkMemberNameCombo(ClassMember member, String memberName) {
if (memberName == name) {
reporter.reportErrorForNode(
- CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
- member,
- [name, classElement.name]);
+ classElement.isEnum
+ ? CompileTimeErrorCode.ENUM_WITH_ABSTRACT_MEMBER
+ : CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
+ member,
+ [name, classElement.name],
+ );
return true;
} else {
return false;
diff --git a/pkg/analyzer/lib/src/error/override_verifier.dart b/pkg/analyzer/lib/src/error/override_verifier.dart
index 795a093..5a87250 100644
--- a/pkg/analyzer/lib/src/error/override_verifier.dart
+++ b/pkg/analyzer/lib/src/error/override_verifier.dart
@@ -37,6 +37,13 @@
}
@override
+ void visitEnumDeclaration(EnumDeclaration node) {
+ _currentClass = node.declaredElement;
+ super.visitEnumDeclaration(node);
+ _currentClass = null;
+ }
+
+ @override
void visitFieldDeclaration(FieldDeclaration node) {
for (VariableDeclaration field in node.fields.variables) {
var fieldElement = field.declaredElement as FieldElement;
diff --git a/pkg/analyzer/lib/src/error/required_parameters_verifier.dart b/pkg/analyzer/lib/src/error/required_parameters_verifier.dart
index 19ca635..0e553d3 100644
--- a/pkg/analyzer/lib/src/error/required_parameters_verifier.dart
+++ b/pkg/analyzer/lib/src/error/required_parameters_verifier.dart
@@ -18,13 +18,22 @@
RequiredParametersVerifier(this._errorReporter);
@override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ _check(
+ parameters: node.constructorElement?.parameters,
+ arguments: node.arguments?.argumentList.arguments ?? <Expression>[],
+ errorNode: node.name,
+ );
+ }
+
+ @override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
var type = node.staticInvokeType;
if (type is FunctionType) {
_check(
- type.parameters,
- node.argumentList,
- node,
+ parameters: type.parameters,
+ arguments: node.argumentList.arguments,
+ errorNode: node,
);
}
}
@@ -32,9 +41,9 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
_check(
- node.constructorName.staticElement?.parameters,
- node.argumentList,
- node.constructorName,
+ parameters: node.constructorName.staticElement?.parameters,
+ arguments: node.argumentList.arguments,
+ errorNode: node.constructorName,
);
}
@@ -43,15 +52,19 @@
if (node.methodName.name == FunctionElement.CALL_METHOD_NAME) {
var targetType = node.realTarget?.staticType;
if (targetType is FunctionType) {
- _check(targetType.parameters, node.argumentList, node.argumentList);
+ _check(
+ parameters: targetType.parameters,
+ arguments: node.argumentList.arguments,
+ errorNode: node.argumentList,
+ );
return;
}
}
_check(
- _executableElement(node.methodName.staticElement)?.parameters,
- node.argumentList,
- node.methodName,
+ parameters: _executableElement(node.methodName.staticElement)?.parameters,
+ arguments: node.argumentList.arguments,
+ errorNode: node.methodName,
);
}
@@ -59,26 +72,31 @@
void visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node) {
_check(
- _executableElement(node.staticElement)?.parameters,
- node.argumentList,
- node,
+ parameters: _executableElement(node.staticElement)?.parameters,
+ arguments: node.argumentList.arguments,
+ errorNode: node,
);
}
@override
- void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ void visitSuperConstructorInvocation(
+ SuperConstructorInvocation node, {
+ ConstructorElement? enclosingConstructor,
+ }) {
_check(
- _executableElement(node.staticElement)?.parameters,
- node.argumentList,
- node,
+ parameters: _executableElement(node.staticElement)?.parameters,
+ enclosingConstructor: enclosingConstructor,
+ arguments: node.argumentList.arguments,
+ errorNode: node,
);
}
- void _check(
- List<ParameterElement>? parameters,
- ArgumentList argumentList,
- AstNode node,
- ) {
+ void _check({
+ required List<ParameterElement>? parameters,
+ ConstructorElement? enclosingConstructor,
+ required List<Expression> arguments,
+ required AstNode errorNode,
+ }) {
if (parameters == null) {
return;
}
@@ -86,10 +104,11 @@
for (ParameterElement parameter in parameters) {
if (parameter.isRequiredNamed) {
String parameterName = parameter.name;
- if (!_containsNamedExpression(argumentList, parameterName)) {
+ if (!_containsNamedExpression(
+ enclosingConstructor, arguments, parameterName)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT,
- node,
+ errorNode,
[parameterName],
);
}
@@ -98,18 +117,19 @@
var annotation = _requiredAnnotation(parameter);
if (annotation != null) {
String parameterName = parameter.name;
- if (!_containsNamedExpression(argumentList, parameterName)) {
+ if (!_containsNamedExpression(
+ enclosingConstructor, arguments, parameterName)) {
var reason = annotation.reason;
if (reason != null) {
_errorReporter.reportErrorForNode(
HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS,
- node,
+ errorNode,
[parameterName, reason],
);
} else {
_errorReporter.reportErrorForNode(
HintCode.MISSING_REQUIRED_PARAM,
- node,
+ errorNode,
[parameterName],
);
}
@@ -119,8 +139,11 @@
}
}
- static bool _containsNamedExpression(ArgumentList args, String name) {
- NodeList<Expression> arguments = args.arguments;
+ static bool _containsNamedExpression(
+ ConstructorElement? enclosingConstructor,
+ List<Expression> arguments,
+ String name,
+ ) {
for (int i = arguments.length - 1; i >= 0; i--) {
Expression expression = arguments[i];
if (expression is NamedExpression) {
@@ -129,6 +152,12 @@
}
}
}
+
+ if (enclosingConstructor != null) {
+ return enclosingConstructor.parameters.any((e) =>
+ e is SuperFormalParameterElement && e.isNamed && e.name == name);
+ }
+
return false;
}
diff --git a/pkg/analyzer/lib/src/error/todo_finder.dart b/pkg/analyzer/lib/src/error/todo_finder.dart
index e6a4df3..b3d3b24 100644
--- a/pkg/analyzer/lib/src/error/todo_finder.dart
+++ b/pkg/analyzer/lib/src/error/todo_finder.dart
@@ -34,7 +34,7 @@
///
/// @param unit the compilation unit containing the to-do comments
void findIn(CompilationUnit unit) {
- _gatherTodoComments(unit.beginToken, unit.lineInfo!);
+ _gatherTodoComments(unit.beginToken, unit.lineInfo);
}
/// Search the comment tokens reachable from the given token and create errors
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 1488253..aadad6e 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -33,7 +33,7 @@
_libraryElement.typeSystem as TypeSystemImpl;
void checkConstructorReference(ConstructorReference node) {
- var classElement = node.constructorName.type2.name.staticElement;
+ var classElement = node.constructorName.type.name.staticElement;
List<TypeParameterElement> typeParameters;
if (classElement is TypeAliasElement) {
typeParameters = classElement.typeParameters;
@@ -46,7 +46,7 @@
if (typeParameters.isEmpty) {
return;
}
- var typeArgumentList = node.constructorName.type2.typeArguments;
+ var typeArgumentList = node.constructorName.type.typeArguments;
if (typeArgumentList == null) {
return;
}
@@ -91,6 +91,55 @@
}
}
+ void checkEnumConstantDeclaration(EnumConstantDeclaration node) {
+ var constructorElement = node.constructorElement;
+ if (constructorElement == null) {
+ return;
+ }
+
+ var enumElement = constructorElement.enclosingElement;
+ var typeParameters = enumElement.typeParameters;
+
+ var typeArgumentList = node.arguments?.typeArguments;
+ var typeArgumentNodes = typeArgumentList?.arguments;
+ if (typeArgumentList != null &&
+ typeArgumentNodes != null &&
+ typeArgumentNodes.length != typeParameters.length) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM,
+ typeArgumentList,
+ [typeParameters.length, typeArgumentNodes.length],
+ );
+ }
+
+ if (typeParameters.isEmpty) {
+ return;
+ }
+
+ // Check that type arguments are regular-bounded.
+ var typeArguments = constructorElement.returnType.typeArguments;
+ var substitution = Substitution.fromPairs(typeParameters, typeArguments);
+ for (var i = 0; i < typeArguments.length; i++) {
+ var typeParameter = typeParameters[i];
+ var typeArgument = typeArguments[i];
+
+ var bound = typeParameter.bound;
+ if (bound == null) {
+ continue;
+ }
+
+ bound = substitution.substituteType(bound);
+
+ if (!_typeSystem.isSubtypeOf(typeArgument, bound)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+ typeArgumentNodes?[i] ?? node.name,
+ [typeArgument, typeParameter.name, bound],
+ );
+ }
+ }
+ }
+
void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
_checkInvocationTypeArguments(
node.typeArguments?.arguments,
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index e9d4b77..dcac77f 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -101,6 +101,18 @@
}
@override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ usedElements.addElement(node.constructorElement?.declaration);
+
+ var argumentList = node.arguments?.argumentList;
+ if (argumentList != null) {
+ _addParametersForArguments(argumentList);
+ }
+
+ super.visitEnumConstantDeclaration(node);
+ }
+
+ @override
void visitFunctionDeclaration(FunctionDeclaration node) {
var enclosingExecOld = _enclosingExec;
try {
@@ -134,10 +146,7 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
- for (var argument in node.argumentList.arguments) {
- var parameter = argument.staticParameterElement;
- usedElements.addElement(parameter);
- }
+ _addParametersForArguments(node.argumentList);
super.visitInstanceCreationExpression(node);
}
@@ -168,10 +177,7 @@
void visitMethodInvocation(MethodInvocation node) {
var function = node.methodName.staticElement;
if (function is FunctionElement || function is MethodElement) {
- for (var argument in node.argumentList.arguments) {
- var parameter = argument.staticParameterElement;
- usedElements.addElement(parameter);
- }
+ _addParametersForArguments(node.argumentList);
}
super.visitMethodInvocation(node);
}
@@ -251,8 +257,10 @@
element.name == 'values') {
// If the 'values' static accessor of the enum is accessed, then all of
// the enum values have been read.
- for (var value in enclosingElement.fields) {
- usedElements.readMembers.add(value.getter!);
+ for (var field in enclosingElement.fields) {
+ if (field.isEnumConstant) {
+ usedElements.readMembers.add(field.getter!);
+ }
}
} else if ((enclosingElement is ClassElement ||
enclosingElement is ExtensionElement) &&
@@ -289,6 +297,13 @@
}
}
+ void _addParametersForArguments(ArgumentList argumentList) {
+ for (var argument in argumentList.arguments) {
+ var parameter = argument.staticParameterElement;
+ usedElements.addElement(parameter);
+ }
+ }
+
/// Marks the [element] of [node] as used in the library.
void _useIdentifierElement(
Identifier node,
@@ -492,14 +507,24 @@
return false;
}
var enclosingElement = element.enclosingElement;
- if (enclosingElement is ClassElement &&
- enclosingElement.isPrivate &&
- (element.isStatic || element is ConstructorElement)) {
- return false;
- } else if (enclosingElement is ExtensionElement &&
- enclosingElement.isPrivate) {
- return false;
+
+ if (enclosingElement is ClassElement) {
+ if (enclosingElement.isEnum) {
+ if (element is ConstructorElement && element.isGenerative) {
+ return false;
+ }
+ }
+ if (enclosingElement.isPrivate) {
+ if (element.isStatic || element is ConstructorElement) {
+ return false;
+ }
+ }
}
+
+ if (enclosingElement is ExtensionElement) {
+ return enclosingElement.isPublic;
+ }
+
return true;
}
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index db03646..9526d94 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -58,14 +58,16 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart'
show
+ ArgumentListImpl,
ClassDeclarationImpl,
CompilationUnitImpl,
ConstructorNameImpl,
- EnumConstantArgumentsImpl,
ConstructorSelectorImpl,
+ EnumConstantArgumentsImpl,
EnumConstantDeclarationImpl,
EnumDeclarationImpl,
ExtensionDeclarationImpl,
@@ -76,6 +78,7 @@
TypeArgumentListImpl,
TypeParameterImpl;
import 'package:analyzer/src/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/fasta/error_converter.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
@@ -170,8 +173,10 @@
final FeatureSet _featureSet;
+ final LineInfo _lineInfo;
+
AstBuilder(ErrorReporter? errorReporter, this.fileUri, this.isFullAst,
- this._featureSet,
+ this._featureSet, this._lineInfo,
[Uri? uri])
: errorReporter = FastaErrorReporter(errorReporter),
enableNonNullable = _featureSet.isEnabled(Feature.non_nullable),
@@ -248,25 +253,28 @@
}
@override
- void beginClassDeclaration(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {
+ void beginClassDeclaration(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
assert(classDeclaration == null &&
mixinDeclaration == null &&
extensionDeclaration == null);
push(_Modifiers()..abstractKeyword = abstractToken);
- if (macroToken != null && !enableMacros) {
- var feature = ExperimentalFeatures.macros;
- handleRecoverableError(
- templateExperimentNotEnabled.withArguments(
- feature.enableString,
- _versionAsString(ExperimentStatus.currentVersion),
- ),
- macroToken,
- macroToken);
- // Pretend that 'macro' didn't occur while this feature is incomplete.
- macroToken = null;
+ if (!enableMacros) {
+ if (macroToken != null) {
+ var feature = ExperimentalFeatures.macros;
+ handleRecoverableError(
+ templateExperimentNotEnabled.withArguments(
+ feature.enableString,
+ _versionAsString(ExperimentStatus.currentVersion),
+ ),
+ macroToken,
+ macroToken);
+ // Pretend that 'macro' didn't occur while this feature is incomplete.
+ macroToken = null;
+ }
}
push(macroToken ?? NullValue.Token);
+ push(augmentToken ?? NullValue.Token);
}
@override
@@ -359,6 +367,7 @@
@override
void beginMethod(
DeclarationKind declarationKind,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -366,6 +375,10 @@
Token? getOrSet,
Token name) {
_Modifiers modifiers = _Modifiers();
+ if (augmentToken != null) {
+ assert(augmentToken.isModifier);
+ modifiers.augmentKeyword = augmentToken;
+ }
if (externalToken != null) {
assert(externalToken.isModifier);
modifiers.externalKeyword = externalToken;
@@ -389,34 +402,42 @@
}
@override
- void beginMixinDeclaration(Token mixinKeyword, Token name) {
+ void beginMixinDeclaration(
+ Token? augmentToken, Token mixinKeyword, Token name) {
assert(classDeclaration == null &&
mixinDeclaration == null &&
extensionDeclaration == null);
+ push(augmentToken ?? NullValue.Token);
}
@override
- void beginNamedMixinApplication(
- Token begin, Token? abstractToken, Token? macroToken, Token name) {
+ void beginNamedMixinApplication(Token begin, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
push(_Modifiers()..abstractKeyword = abstractToken);
- if (macroToken != null && !enableMacros) {
- var feature = ExperimentalFeatures.macros;
- handleRecoverableError(
- templateExperimentNotEnabled.withArguments(
- feature.enableString,
- _versionAsString(ExperimentStatus.currentVersion),
- ),
- macroToken,
- macroToken);
- // Pretend that 'macro' didn't occur while this feature is incomplete.
- macroToken = null;
+ if (!enableMacros) {
+ if (macroToken != null) {
+ var feature = ExperimentalFeatures.macros;
+ handleRecoverableError(
+ templateExperimentNotEnabled.withArguments(
+ feature.enableString,
+ _versionAsString(ExperimentStatus.currentVersion),
+ ),
+ macroToken,
+ macroToken);
+ // Pretend that 'macro' didn't occur while this feature is incomplete.
+ macroToken = null;
+ }
}
push(macroToken ?? NullValue.Token);
+ push(augmentToken ?? NullValue.Token);
}
@override
- void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
- push(_Modifiers()..externalKeyword = externalToken);
+ void beginTopLevelMethod(
+ Token lastConsumed, Token? augmentToken, Token? externalToken) {
+ push(_Modifiers()
+ ..augmentKeyword = augmentToken
+ ..externalKeyword = externalToken);
}
@override
@@ -943,6 +964,7 @@
@override
void endClassFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -994,6 +1016,7 @@
comment: comment,
metadata: metadata,
abstractKeyword: abstractToken,
+ augmentKeyword: augmentToken,
covariantKeyword: covariantKeyword,
externalKeyword: externalToken,
staticKeyword: staticToken,
@@ -1109,7 +1132,8 @@
directives: directives,
declarations: declarations,
endToken: endToken,
- featureSet: _featureSet);
+ featureSet: _featureSet,
+ lineInfo: _lineInfo);
push(unit);
}
@@ -1370,6 +1394,7 @@
@override
void endExtensionFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -1384,8 +1409,17 @@
// an error at this point, but we include them in order to get navigation,
// search, etc.
}
- endClassFields(abstractToken, externalToken, staticToken, covariantToken,
- lateToken, varFinalOrConst, count, beginToken, endToken);
+ endClassFields(
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ count,
+ beginToken,
+ endToken);
}
@override
@@ -1776,7 +1810,7 @@
}
@override
- void endImport(Token importKeyword, Token? semicolon) {
+ void endImport(Token importKeyword, Token? augmentToken, Token? semicolon) {
assert(optional('import', importKeyword));
assert(optionalOrNull(';', semicolon));
debugEvent("Import");
@@ -1790,6 +1824,21 @@
var metadata = pop() as List<Annotation>?;
var comment = _findComment(metadata, importKeyword);
+ if (!enableMacros) {
+ if (augmentToken != null) {
+ var feature = ExperimentalFeatures.macros;
+ handleRecoverableError(
+ templateExperimentNotEnabled.withArguments(
+ feature.enableString,
+ _versionAsString(ExperimentStatus.currentVersion),
+ ),
+ augmentToken,
+ augmentToken);
+ // Pretend that 'augment' didn't occur while this feature is incomplete.
+ augmentToken = null;
+ }
+ }
+
directives.add(ast.importDirective(
comment,
metadata,
@@ -1800,7 +1849,8 @@
asKeyword,
prefix,
combinators,
- semicolon ?? Tokens.semicolon()));
+ semicolon ?? Tokens.semicolon(),
+ augmentKeyword: augmentToken));
}
@override
@@ -1960,7 +2010,7 @@
FunctionExpression functionExpression =
ast.functionExpression(typeParameters, parameters, body);
var functionDeclaration = ast.functionDeclaration(
- null, metadata, null, returnType, null, name, functionExpression);
+ null, metadata, null, null, returnType, null, name, functionExpression);
push(ast.functionDeclarationStatement(functionDeclaration));
}
@@ -2036,6 +2086,7 @@
@override
void endMixinFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -2044,8 +2095,17 @@
int count,
Token beginToken,
Token endToken) {
- endClassFields(abstractToken, externalToken, staticToken, covariantToken,
- lateToken, varFinalOrConst, count, beginToken, endToken);
+ endClassFields(
+ abstractToken,
+ augmentToken,
+ externalToken,
+ staticToken,
+ covariantToken,
+ lateToken,
+ varFinalOrConst,
+ count,
+ beginToken,
+ endToken);
}
@override
@@ -2088,6 +2148,7 @@
var withClause = pop(NullValue.WithClause) as WithClause;
var superclass = pop() as NamedType;
var macroKeyword = pop(NullValue.Token) as Token?;
+ var augmentKeyword = pop(NullValue.Token) as Token?;
var modifiers = pop() as _Modifiers?;
var typeParameters = pop() as TypeParameterList?;
var name = pop() as SimpleIdentifier;
@@ -2103,6 +2164,7 @@
equalsToken,
abstractKeyword,
macroKeyword,
+ augmentKeyword,
superclass,
withClause,
implementsClause,
@@ -2367,12 +2429,14 @@
var name = pop() as SimpleIdentifier;
var returnType = pop() as TypeAnnotation?;
var modifiers = pop() as _Modifiers?;
+ var augmentKeyword = modifiers?.augmentKeyword;
var externalKeyword = modifiers?.externalKeyword;
var metadata = pop() as List<Annotation>?;
var comment = _findComment(metadata, beginToken);
declarations.add(ast.functionDeclaration(
comment,
metadata,
+ augmentKeyword,
externalKeyword,
returnType,
getOrSet,
@@ -2688,6 +2752,7 @@
var withClause = pop(NullValue.WithClause) as WithClause?;
var extendsClause = pop(NullValue.ExtendsClause) as ExtendsClause?;
var macroKeyword = pop(NullValue.Token) as Token?;
+ var augmentKeyword = pop(NullValue.Token) as Token?;
var modifiers = pop() as _Modifiers?;
var typeParameters = pop() as TypeParameterList?;
var name = pop() as SimpleIdentifier;
@@ -2701,6 +2766,7 @@
metadata,
abstractKeyword,
macroKeyword,
+ augmentKeyword,
classKeyword,
name,
typeParameters,
@@ -2814,11 +2880,12 @@
debugEvent("EnumElement");
var tmpArguments = pop() as MethodInvocationImpl?;
var tmpConstructor = pop() as ConstructorNameImpl?;
+ var constant = pop() as EnumConstantDeclarationImpl;
if (!enableEnhancedEnums &&
(tmpArguments != null ||
tmpConstructor != null &&
- (tmpConstructor.type2.typeArguments != null ||
+ (tmpConstructor.type.typeArguments != null ||
tmpConstructor.name != null))) {
Token token = tmpArguments != null
? tmpArguments.argumentList.beginToken
@@ -2834,31 +2901,44 @@
);
}
- var constant = pop() as EnumConstantDeclarationImpl;
+ var argumentList = tmpArguments?.argumentList;
+
+ TypeArgumentListImpl? typeArguments;
+ ConstructorSelectorImpl? constructorSelector;
+ if (tmpConstructor != null) {
+ typeArguments = tmpConstructor.type.typeArguments;
+ var constructorNamePeriod = tmpConstructor.period;
+ var constructorNameId = tmpConstructor.name;
+ if (constructorNamePeriod != null && constructorNameId != null) {
+ constructorSelector = ConstructorSelectorImpl(
+ period: constructorNamePeriod,
+ name: constructorNameId,
+ );
+ }
+ // enum E { v<int> }
+ if (typeArguments != null && argumentList == null) {
+ errorReporter.errorReporter?.reportErrorForNode(
+ ParserErrorCode.ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS,
+ typeArguments,
+ );
+ argumentList = _syntheticArgumentList(typeArguments.endToken);
+ }
+ // enum E { v.^ }
+ if (constructorSelector != null) {
+ argumentList ??= _syntheticArgumentList(constructorSelector.endToken);
+ }
+ }
// Replace the constant to include arguments.
- if (tmpArguments != null) {
- TypeArgumentListImpl? typeArguments;
- ConstructorSelectorImpl? constructorName;
- if (tmpConstructor != null) {
- typeArguments = tmpConstructor.type2.typeArguments;
- var constructorNamePeriod = tmpConstructor.period;
- var constructorNameId = tmpConstructor.name;
- if (constructorNamePeriod != null && constructorNameId != null) {
- constructorName = ConstructorSelectorImpl(
- period: constructorNamePeriod,
- name: constructorNameId,
- );
- }
- }
+ if (argumentList != null) {
constant = EnumConstantDeclarationImpl(
documentationComment: constant.documentationComment,
metadata: constant.metadata,
name: constant.name,
arguments: EnumConstantArgumentsImpl(
typeArguments: typeArguments,
- constructorSelector: constructorName,
- argumentList: tmpArguments.argumentList,
+ constructorSelector: constructorSelector,
+ argumentList: argumentList,
),
);
}
@@ -2873,6 +2953,10 @@
var constants = popTypedList2<EnumConstantDeclaration>(elementsCount);
enumDeclaration!.constants.addAll(constants);
+ if (optional(';', elementsEndToken)) {
+ enumDeclaration!.semicolon = elementsEndToken;
+ }
+
if (!enableEnhancedEnums && optional(';', elementsEndToken)) {
var feature = ExperimentalFeatures.enhanced_enums;
handleRecoverableError(
@@ -2930,6 +3014,7 @@
implementsClause: implementsClause,
leftBracket: leftBrace,
constants: [],
+ semicolon: null,
members: [],
rightBracket: leftBrace.endGroup!,
),
@@ -3509,6 +3594,7 @@
var implementsClause = pop(NullValue.IdentifierList) as ImplementsClause?;
var onClause = pop(NullValue.IdentifierList) as OnClause?;
+ var augmentKeyword = pop(NullValue.Token) as Token?;
var typeParameters = pop() as TypeParameterList?;
var name = pop() as SimpleIdentifier;
var metadata = pop() as List<Annotation>?;
@@ -3517,6 +3603,7 @@
mixinDeclaration = ast.mixinDeclaration(
comment,
metadata,
+ augmentKeyword,
mixinKeyword,
name,
typeParameters,
@@ -3723,7 +3810,7 @@
var extendsClause = pop(NullValue.ExtendsClause) as ExtendsClause?;
var declaration = declarations.last as ClassDeclarationImpl;
if (extendsClause != null) {
- if (declaration.extendsClause?.superclass2 == null) {
+ if (declaration.extendsClause?.superclass == null) {
declaration.extendsClause = extendsClause;
}
}
@@ -3731,15 +3818,15 @@
if (declaration.withClause == null) {
declaration.withClause = withClause;
} else {
- declaration.withClause!.mixinTypes2.addAll(withClause.mixinTypes2);
+ declaration.withClause!.mixinTypes.addAll(withClause.mixinTypes);
}
}
if (implementsClause != null) {
if (declaration.implementsClause == null) {
declaration.implementsClause = implementsClause;
} else {
- declaration.implementsClause!.interfaces2
- .addAll(implementsClause.interfaces2);
+ declaration.implementsClause!.interfaces
+ .addAll(implementsClause.interfaces);
}
}
}
@@ -3781,16 +3868,16 @@
if (mixinDeclaration!.onClause == null) {
mixinDeclaration!.onClause = onClause;
} else {
- mixinDeclaration!.onClause!.superclassConstraints2
- .addAll(onClause.superclassConstraints2);
+ mixinDeclaration!.onClause!.superclassConstraints
+ .addAll(onClause.superclassConstraints);
}
}
if (implementsClause != null) {
if (mixinDeclaration!.implementsClause == null) {
mixinDeclaration!.implementsClause = implementsClause;
} else {
- mixinDeclaration!.implementsClause!.interfaces2
- .addAll(implementsClause.interfaces2);
+ mixinDeclaration!.implementsClause!.interfaces
+ .addAll(implementsClause.interfaces);
}
}
}
@@ -4257,12 +4344,13 @@
return ast.variableDeclaration(name, equals, initializer);
}
- ArgumentList _syntheticArgumentList(Token precedingToken) {
- int syntheticOffset = precedingToken.end;
- return ast.argumentList(
- SyntheticToken(TokenType.OPEN_PAREN, syntheticOffset),
- [],
- SyntheticToken(TokenType.CLOSE_PAREN, syntheticOffset));
+ ArgumentListImpl _syntheticArgumentList(Token precedingToken) {
+ var syntheticOffset = precedingToken.end;
+ var left = SyntheticToken(TokenType.OPEN_PAREN, syntheticOffset)
+ ..previous = precedingToken;
+ var right = SyntheticToken(TokenType.CLOSE_PAREN, syntheticOffset)
+ ..previous = left;
+ return ast.argumentList(left, [], right);
}
SimpleIdentifier _tmpSimpleIdentifier() {
@@ -4314,6 +4402,7 @@
/// of modifiers.
class _Modifiers {
Token? abstractKeyword;
+ Token? augmentKeyword;
Token? externalKeyword;
Token? finalConstOrVarKeyword;
Token? staticKeyword;
diff --git a/pkg/analyzer/lib/src/file_system/file_system.dart b/pkg/analyzer/lib/src/file_system/file_system.dart
index b7b4655..d7bfadf 100644
--- a/pkg/analyzer/lib/src/file_system/file_system.dart
+++ b/pkg/analyzer/lib/src/file_system/file_system.dart
@@ -37,5 +37,5 @@
Uri restoreAbsolute(Source source) => pathToUri(source.fullName);
/// Return `true` if the given [uri] is a `file` URI.
- static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
+ static bool isFileUri(Uri uri) => uri.isScheme(FILE_SCHEME);
}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b32cea7..93bcdab 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -153,7 +153,7 @@
}
void visitConstructorName(covariant ConstructorNameImpl node) {
- var type = node.type2.type;
+ var type = node.type.type;
if (type == null) {
return;
}
@@ -271,10 +271,12 @@
}
void visitMethodInvocation(MethodInvocation node,
- {List<WhyNotPromotedGetter>? whyNotPromotedList}) {
+ {List<WhyNotPromotedGetter>? whyNotPromotedList,
+ required DartType? contextType}) {
whyNotPromotedList ??= [];
_methodInvocationResolver.resolve(
- node as MethodInvocationImpl, whyNotPromotedList);
+ node as MethodInvocationImpl, whyNotPromotedList,
+ contextType: contextType);
}
void visitMixinDeclaration(MixinDeclaration node) {
@@ -368,7 +370,7 @@
// TODO(brianwilkerson) Defer this check until we know there's an error (by
// in-lining _resolveArgumentsToFunction below).
var declaration = node.thisOrAncestorOfType<ClassDeclaration>();
- var superclassName = declaration?.extendsClause?.superclass2.name;
+ var superclassName = declaration?.extendsClause?.superclass.name;
if (superclassName != null &&
_resolver.definingLibrary
.shouldIgnoreUndefinedIdentifier(superclassName)) {
diff --git a/pkg/analyzer/lib/src/generated/element_type_provider.dart b/pkg/analyzer/lib/src/generated/element_type_provider.dart
index ba2554c..c089385 100644
--- a/pkg/analyzer/lib/src/generated/element_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/element_type_provider.dart
@@ -32,7 +32,7 @@
void freshTypeParameterCreated(TypeParameterElement newTypeParameter,
TypeParameterElement oldTypeParameter) {}
- List<InterfaceType> getClassInterfaces(ClassElementImpl element) =>
+ List<InterfaceType> getClassInterfaces(AbstractClassElementImpl element) =>
element.interfacesInternal;
/// Queries the parameters of an executable element's signature.
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 6741d98..bc9aba5 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -224,6 +224,10 @@
@override
VersionConstraint? sdkVersionConstraint;
+ /// The constraint on the language version for every Dart file.
+ /// Violations will be reported as analysis errors.
+ VersionConstraint? sourceLanguageConstraint;
+
ExperimentStatus _contextFeatures = ExperimentStatus();
/// The language version to use for libraries that are not in a package.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 6746259..01ff198 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -26,6 +26,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/element/well_bounded.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -73,6 +74,9 @@
/// for the kind of the function body, e.g. not `Future` for `async`.
bool hasLegalReturnType = true;
+ /// The number of enclosing [CatchClause] in this executable.
+ int catchClauseLevel = 0;
+
EnclosingExecutableContext(this.element,
{bool? isAsynchronous, this.catchErrorOnErrorReturnType})
: isAsynchronous =
@@ -163,11 +167,6 @@
/// The manager for the inheritance mappings.
final InheritanceManager3 _inheritanceManager;
- /// A flag indicating whether the visitor is currently within a catch clause.
- ///
- /// See [visitCatchClause].
- bool _isInCatchClause = false;
-
/// A flag indicating whether the visitor is currently within a comment.
bool _isInComment = false;
@@ -246,10 +245,9 @@
_UninstantiatedBoundChecker(errorReporter),
_checkUseVerifier = UseResultVerifier(errorReporter),
_requiredParametersVerifier = RequiredParametersVerifier(errorReporter),
- _duplicateDefinitionVerifier =
- DuplicateDefinitionVerifier(_currentLibrary, errorReporter) {
+ _duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
+ _inheritanceManager, _currentLibrary, errorReporter) {
_isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
- _isInCatchClause = false;
_isInStaticVariableDeclaration = false;
_isInConstructorInitializer = false;
_intType = _typeProvider.intType;
@@ -408,13 +406,12 @@
@override
void visitCatchClause(CatchClause node) {
_duplicateDefinitionVerifier.checkCatchClause(node);
- bool previousIsInCatchClause = _isInCatchClause;
try {
- _isInCatchClause = true;
+ _enclosingExecutable.catchClauseLevel++;
_checkForTypeAnnotationDeferredClass(node.exceptionType);
super.visitCatchClause(node);
} finally {
- _isInCatchClause = previousIsInCatchClause;
+ _enclosingExecutable.catchClauseLevel--;
}
}
@@ -422,15 +419,16 @@
void visitClassDeclaration(ClassDeclaration node) {
var outerClass = _enclosingClass;
try {
+ var element = node.declaredElement as ClassElementImpl;
_isInNativeClass = node.nativeClause != null;
- _enclosingClass = node.declaredElement as ClassElementImpl;
+ _enclosingClass = element;
List<ClassMember> members = node.members;
_duplicateDefinitionVerifier.checkClass(node);
_checkForBuiltInIdentifierAsName(
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
_checkForConflictingClassTypeVariableErrorCodes();
- var superclass = node.extendsClause?.superclass2;
+ var superclass = node.extendsClause?.superclass;
var implementsClause = node.implementsClause;
var withClause = node.withClause;
@@ -442,11 +440,17 @@
}
_checkForConflictingClassMembers();
- _constructorFieldsVerifier.enterClass(node);
+ _constructorFieldsVerifier.enterClass(node, element);
_checkForFinalNotInitializedInClass(members);
_checkForBadFunctionUse(node);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
_checkForMainFunction(node.name);
+
+ GetterSetterTypesVerifier(
+ typeSystem: typeSystem,
+ errorReporter: errorReporter,
+ ).checkStaticAccessors(element.accessors);
+
super.visitClassDeclaration(node);
} finally {
_isInNativeClass = false;
@@ -463,7 +467,7 @@
try {
_enclosingClass = node.declaredElement as ClassElementImpl;
_checkClassInheritance(
- node, node.superclass2, node.withClause, node.implementsClause);
+ node, node.superclass, node.withClause, node.implementsClause);
_checkForMainFunction(node.name);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
} finally {
@@ -484,9 +488,17 @@
@override
void visitCompilationUnit(CompilationUnit node) {
+ var element = node.declaredElement as CompilationUnitElement;
_featureSet = node.featureSet;
_duplicateDefinitionVerifier.checkUnit(node);
_checkForDeferredPrefixCollisions(node);
+ _checkForIllegalLanguageOverride(node);
+
+ GetterSetterTypesVerifier(
+ typeSystem: typeSystem,
+ errorReporter: errorReporter,
+ ).checkStaticAccessors(element.accessors);
+
super.visitCompilationUnit(node);
_featureSet = null;
}
@@ -495,6 +507,7 @@
void visitConstructorDeclaration(ConstructorDeclaration node) {
var element = node.declaredElement!;
_withEnclosingExecutable(element, () {
+ _checkForNonConstGenerativeEnumConstructor(node);
_checkForInvalidModifierOnBody(
node.body, CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR);
if (!_checkForConstConstructorWithNonConstSuper(node)) {
@@ -533,6 +546,7 @@
@override
void visitConstructorReference(ConstructorReference node) {
_typeArgumentsVerifier.checkConstructorReference(node);
+ _checkForInvalidGenerativeConstructorReference(node.constructorName);
}
@override
@@ -555,13 +569,44 @@
}
@override
+ void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ _requiredParametersVerifier.visitEnumConstantDeclaration(node);
+ _typeArgumentsVerifier.checkEnumConstantDeclaration(node);
+ super.visitEnumConstantDeclaration(node);
+ }
+
+ @override
void visitEnumDeclaration(EnumDeclaration node) {
var outerClass = _enclosingClass;
try {
- _enclosingClass = node.declaredElement;
+ var element = node.declaredElement as EnumElementImpl;
+ _enclosingClass = element;
_duplicateDefinitionVerifier.checkEnum(node);
+
+ _checkForBuiltInIdentifierAsName(
+ node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
+ _checkForConflictingEnumTypeVariableErrorCodes(element);
+ var implementsClause = node.implementsClause;
+ var withClause = node.withClause;
+
+ if (implementsClause != null || withClause != null) {
+ _checkClassInheritance(node, null, withClause, implementsClause);
+ }
+
+ _constructorFieldsVerifier.enterEnum(node, element);
+ _checkForFinalNotInitializedInClass(node.members);
+ _checkForWrongTypeParameterVarianceInSuperinterfaces();
+ _checkForMainFunction(node.name);
+ _checkForEnumInstantiatedToBoundsIsNotWellBounded(node, element);
+
+ GetterSetterTypesVerifier(
+ typeSystem: typeSystem,
+ errorReporter: errorReporter,
+ ).checkStaticAccessors(element.accessors);
+
super.visitEnumDeclaration(node);
} finally {
+ _constructorFieldsVerifier.leaveClass();
_enclosingClass = outerClass;
}
}
@@ -591,7 +636,8 @@
@override
void visitExtensionDeclaration(ExtensionDeclaration node) {
- _enclosingExtension = node.declaredElement;
+ var element = node.declaredElement!;
+ _enclosingExtension = element;
_duplicateDefinitionVerifier.checkExtension(node);
_checkForConflictingExtensionTypeVariableErrorCodes();
_checkForFinalNotInitializedInClass(node.members);
@@ -599,7 +645,7 @@
GetterSetterTypesVerifier(
typeSystem: typeSystem,
errorReporter: errorReporter,
- ).checkExtension(node);
+ ).checkExtension(element);
final name = node.name;
if (name != null) {
@@ -627,6 +673,7 @@
_checkForNotInitializedNonNullableStaticField(node);
_checkForWrongTypeParameterVarianceInField(node);
_checkForLateFinalFieldWithConstConstructor(node);
+ _checkForNonFinalFieldInEnum(node);
super.visitFieldDeclaration(node);
} finally {
_isInStaticVariableDeclaration = false;
@@ -698,13 +745,6 @@
_withEnclosingExecutable(functionElement, () {
SimpleIdentifier identifier = node.name;
TypeAnnotation? returnType = node.returnType;
- if (node.isGetter) {
- GetterSetterTypesVerifier(
- typeSystem: typeSystem,
- errorReporter: errorReporter,
- ).checkGetter(
- node.name, node.declaredElement as PropertyAccessorElement);
- }
if (node.isSetter) {
FunctionExpression functionExpression = node.functionExpression;
_checkForWrongNumberOfParametersForSetter(
@@ -802,7 +842,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
- node.interfaces2.forEach(_checkForImplicitDynamicType);
+ node.interfaces.forEach(_checkForImplicitDynamicType);
super.visitImplementsClause(node);
}
@@ -837,11 +877,11 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
ConstructorName constructorName = node.constructorName;
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
DartType type = namedType.typeOrThrow;
if (type is InterfaceType) {
_checkForConstOrNewWithAbstractClass(node, namedType, type);
- _checkForConstOrNewWithEnum(node, namedType, type);
+ _checkForInvalidGenerativeConstructorReference(constructorName);
_checkForConstOrNewWithMixin(node, namedType, type);
_requiredParametersVerifier.visitInstanceCreationExpression(node);
if (node.isConst) {
@@ -889,13 +929,6 @@
void visitMethodDeclaration(MethodDeclaration node) {
_withEnclosingExecutable(node.declaredElement!, () {
var returnType = node.returnType;
- if (node.isStatic && node.isGetter) {
- GetterSetterTypesVerifier(
- typeSystem: typeSystem,
- errorReporter: errorReporter,
- ).checkGetter(
- node.name, node.declaredElement as PropertyAccessorElement);
- }
if (node.isSetter) {
_checkForWrongNumberOfParametersForSetter(node.name, node.parameters);
_checkForNonVoidReturnTypeForSetter(returnType);
@@ -1124,7 +1157,10 @@
@override
void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- _requiredParametersVerifier.visitSuperConstructorInvocation(node);
+ _requiredParametersVerifier.visitSuperConstructorInvocation(
+ node,
+ enclosingConstructor: _enclosingExecutable.element.ifTypeOrNull(),
+ );
_isInConstructorInitializer = true;
try {
super.visitSuperConstructorInvocation(node);
@@ -1298,7 +1334,7 @@
@override
void visitWithClause(WithClause node) {
- node.mixinTypes2.forEach(_checkForImplicitDynamicType);
+ node.mixinTypes.forEach(_checkForImplicitDynamicType);
super.visitWithClause(node);
}
@@ -1318,7 +1354,7 @@
!_checkForNoGenerativeConstructorsInSuperclass(superclass)) {
_checkForImplicitDynamicType(superclass);
_checkForExtendsDeferredClass(superclass);
- _checkForRepeatedType(implementsClause?.interfaces2,
+ _checkForRepeatedType(implementsClause?.interfaces,
CompileTimeErrorCode.IMPLEMENTS_REPEATED);
_checkImplementsSuperClass(implementsClause);
_checkMixinsSuperClass(withClause);
@@ -1392,9 +1428,9 @@
bool problemReported = false;
int mixinTypeIndex = -1;
for (int mixinNameIndex = 0;
- mixinNameIndex < withClause.mixinTypes2.length;
+ mixinNameIndex < withClause.mixinTypes.length;
mixinNameIndex++) {
- NamedType mixinName = withClause.mixinTypes2[mixinNameIndex];
+ NamedType mixinName = withClause.mixinTypes[mixinNameIndex];
DartType mixinType = mixinName.typeOrThrow;
if (mixinType is InterfaceType) {
mixinTypeIndex++;
@@ -1444,7 +1480,7 @@
if (redirectedElement == null) {
// If the element is null, we check for the
// REDIRECT_TO_MISSING_CONSTRUCTOR case
- NamedType constructorNamedType = redirectedConstructor.type2;
+ NamedType constructorNamedType = redirectedConstructor.type;
DartType redirectedType = constructorNamedType.typeOrThrow;
if (redirectedType.element != null && !redirectedType.isDynamic) {
// Prepare the constructor name
@@ -1624,15 +1660,15 @@
}
if (extendsClause != null) {
- var superElement = extendsClause.superclass2.name.staticElement;
+ var superElement = extendsClause.superclass.name.staticElement;
if (superElement != null && superElement.name == "Function") {
errorReporter.reportErrorForNode(
- HintCode.DEPRECATED_EXTENDS_FUNCTION, extendsClause.superclass2);
+ HintCode.DEPRECATED_EXTENDS_FUNCTION, extendsClause.superclass);
}
}
if (implementsClause != null) {
- for (var interface in implementsClause.interfaces2) {
+ for (var interface in implementsClause.interfaces) {
var type = interface.type;
if (type != null && type.isDartCoreFunction) {
errorReporter.reportErrorForNode(
@@ -1645,7 +1681,7 @@
}
if (withClause != null) {
- for (NamedType type in withClause.mixinTypes2) {
+ for (NamedType type in withClause.mixinTypes) {
var mixinElement = type.name.staticElement;
if (mixinElement != null && mixinElement.name == "Function") {
errorReporter.reportErrorForNode(
@@ -1822,6 +1858,32 @@
}
}
+ void _checkForConflictingEnumTypeVariableErrorCodes(
+ EnumElementImpl element,
+ ) {
+ for (var typeParameter in element.typeParameters) {
+ var name = typeParameter.name;
+ // name is same as the name of the enclosing enum
+ if (element.name == name) {
+ errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
+ typeParameter,
+ [name],
+ );
+ }
+ // check members
+ if (element.getMethod(name) != null ||
+ element.getGetter(name) != null ||
+ element.getSetter(name) != null) {
+ errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
+ typeParameter,
+ [name],
+ );
+ }
+ }
+ }
+
/// Verify all conflicts between type variable and enclosing extension.
///
/// See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION], and
@@ -1877,6 +1939,10 @@
/// field initializers, and assert initializers.
void _checkForConflictingInitializerErrorCodes(
ConstructorDeclaration declaration) {
+ var enclosingClass = _enclosingClass;
+ if (enclosingClass == null) {
+ return;
+ }
// Count and check each redirecting initializer.
var redirectingInitializerCount = 0;
var superInitializerCount = 0;
@@ -1892,7 +1958,7 @@
RedirectingConstructorInvocation invocation = initializer;
var redirectingElement = invocation.staticElement;
if (redirectingElement == null) {
- String enclosingNamedType = _enclosingClass!.displayName;
+ String enclosingNamedType = enclosingClass.displayName;
String constructorStrName = enclosingNamedType;
if (invocation.constructorName != null) {
constructorStrName += ".${invocation.constructorName!.name}";
@@ -1919,7 +1985,12 @@
);
redirectingInitializerCount++;
} else if (initializer is SuperConstructorInvocation) {
- if (superInitializerCount == 1) {
+ if (enclosingClass.isEnum) {
+ errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.SUPER_IN_ENUM_CONSTRUCTOR,
+ initializer.superKeyword,
+ );
+ } else if (superInitializerCount == 1) {
// Only report the second (first illegal) superinitializer.
errorReporter.reportErrorForNode(
CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS, initializer);
@@ -1933,9 +2004,11 @@
if (redirectingInitializerCount > 0) {
for (ConstructorInitializer initializer in declaration.initializers) {
if (initializer is SuperConstructorInvocation) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
- initializer);
+ if (!enclosingClass.isEnum) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
+ initializer);
+ }
}
if (initializer is ConstructorFieldInitializer) {
errorReporter.reportErrorForNode(
@@ -1949,10 +2022,11 @@
}
}
}
- if (redirectingInitializerCount == 0 &&
+ if (!enclosingClass.isEnum &&
+ redirectingInitializerCount == 0 &&
superInitializerCount == 1 &&
superInitializer != declaration.initializers.last) {
- var superNamedType = _enclosingClass!.supertype!.element.displayName;
+ var superNamedType = enclosingClass.supertype!.element.displayName;
var constructorStrName = superNamedType;
var constructorName = superInitializer.constructorName;
if (constructorName != null) {
@@ -2136,21 +2210,6 @@
}
}
- /// Verify that the given instance creation [expression] is not being invoked
- /// on an enum. The [namedType] is the [NamedType] of the [ConstructorName] from
- /// the [InstanceCreationExpression], this is the AST node that the error is
- /// attached to. The [type] is the type being constructed with this
- /// [InstanceCreationExpression].
- ///
- /// See [CompileTimeErrorCode.INSTANTIATE_ENUM].
- void _checkForConstOrNewWithEnum(InstanceCreationExpression expression,
- NamedType namedType, InterfaceType type) {
- if (type.element.isEnum) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INSTANTIATE_ENUM, namedType);
- }
- }
-
/// Verify that the given [expression] is not a mixin instantiation.
void _checkForConstOrNewWithMixin(InstanceCreationExpression expression,
NamedType namedType, InterfaceType type) {
@@ -2411,6 +2470,25 @@
return true;
}
+ void _checkForEnumInstantiatedToBoundsIsNotWellBounded(
+ EnumDeclaration node,
+ EnumElementImpl element,
+ ) {
+ var valuesFieldType = element.valuesField?.type;
+ if (valuesFieldType is InterfaceType) {
+ var isWellBounded = typeSystem.isWellBounded(
+ valuesFieldType.typeArguments.single,
+ allowSuperBounded: true,
+ );
+ if (isWellBounded is NotWellBoundedTypeResult) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED,
+ node.name,
+ );
+ }
+ }
+ }
+
/// Check that if the visiting library is not system, then any given library
/// should not be SDK internal library. The [exportElement] is the
/// [ExportElement] retrieved from the node, if the element in the node was
@@ -2687,6 +2765,34 @@
}
}
+ void _checkForIllegalLanguageOverride(CompilationUnit node) {
+ var sourceLanguageConstraint = _options.sourceLanguageConstraint;
+ if (sourceLanguageConstraint == null) {
+ return;
+ }
+
+ var languageVersion = _currentLibrary.languageVersion.effective;
+ if (sourceLanguageConstraint.allows(languageVersion)) {
+ return;
+ }
+
+ var languageVersionToken = node.languageVersionToken;
+ if (languageVersionToken != null) {
+ errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
+ languageVersionToken,
+ ['$sourceLanguageConstraint'],
+ );
+ } else {
+ errorReporter.reportErrorForOffset(
+ CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
+ 0,
+ 0,
+ ['$sourceLanguageConstraint'],
+ );
+ }
+ }
+
/// Verify that the given implements [clause] does not implement classes such
/// as 'num' or 'String'.
///
@@ -2697,7 +2803,7 @@
return false;
}
bool foundError = false;
- for (NamedType type in clause.interfaces2) {
+ for (NamedType type in clause.interfaces) {
if (_checkForExtendsOrImplementsDisallowedClass(
type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS)) {
foundError = true;
@@ -2889,6 +2995,25 @@
}
}
+ void _checkForInvalidGenerativeConstructorReference(ConstructorName node) {
+ var constructorElement = node.staticElement;
+ if (constructorElement != null &&
+ constructorElement.isGenerative &&
+ constructorElement.enclosingElement.isEnum) {
+ if (_currentLibrary.featureSet.isEnabled(Feature.enhanced_enums)) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
+ node,
+ );
+ } else {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INSTANTIATE_ENUM,
+ node.type,
+ );
+ }
+ }
+ }
+
/// Verify that if the given [identifier] is part of a constructor
/// initializer, then it does not implicitly reference 'this' expression.
///
@@ -3382,7 +3507,7 @@
return false;
}
- for (NamedType mixinType in withClause.mixinTypes2) {
+ for (NamedType mixinType in withClause.mixinTypes) {
DartType type = mixinType.typeOrThrow;
if (type is InterfaceType) {
LibraryElement library = type.element.library;
@@ -3537,6 +3662,17 @@
return false;
}
+ void _checkForNonConstGenerativeEnumConstructor(ConstructorDeclaration node) {
+ if (_enclosingClass?.isEnum == true &&
+ node.constKeyword == null &&
+ node.factoryKeyword == null) {
+ errorReporter.reportErrorForName(
+ CompileTimeErrorCode.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR,
+ node,
+ );
+ }
+ }
+
/// Verify the given map [literal] either:
/// * has `const modifier`
/// * has explicit type arguments
@@ -3567,6 +3703,23 @@
CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
}
+ void _checkForNonFinalFieldInEnum(FieldDeclaration node) {
+ if (node.isStatic) return;
+
+ var variableList = node.fields;
+ if (variableList.isFinal) return;
+
+ var enclosingClass = _enclosingClass;
+ if (enclosingClass == null || !enclosingClass.isEnum) {
+ return;
+ }
+
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NON_FINAL_FIELD_IN_ENUM,
+ variableList.variables.first.name,
+ );
+ }
+
/// Verify that the given method [declaration] of operator `[]=`, has `void`
/// return type.
///
@@ -3695,7 +3848,7 @@
return false;
}
bool problemReported = false;
- for (NamedType namedType in onClause.superclassConstraints2) {
+ for (NamedType namedType in onClause.superclassConstraints) {
DartType type = namedType.typeOrThrow;
if (type is InterfaceType) {
if (_checkForExtendsOrImplementsDisallowedClass(
@@ -3889,6 +4042,7 @@
redirectedConstructor,
[constructorStrName, redirectedClass.name]);
}
+ _checkForInvalidGenerativeConstructorReference(redirectedConstructor);
}
/// Check whether the redirecting constructor, [element], is const, and
@@ -3954,7 +4108,7 @@
///
/// See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH].
void _checkForRethrowOutsideCatch(RethrowExpression expression) {
- if (!_isInCatchClause) {
+ if (_enclosingExecutable.catchClauseLevel == 0) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression);
}
@@ -4281,22 +4435,11 @@
);
if (requiredPositionalParameterCount >
- superParametersResult.positionalArgumentCount) {
+ superParametersResult.positionalArgumentCount ||
+ requiredNamedParameters.isNotEmpty) {
reportError(
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS,
- [
- superType,
- requiredPositionalParameterCount,
- superParametersResult.positionalArgumentCount,
- ],
- );
- }
- for (var requiredNamedParameterName in requiredNamedParameters) {
- reportError(
- CompileTimeErrorCode
- .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
- [requiredNamedParameterName, superType],
+ CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS,
+ [superType],
);
}
}
@@ -4742,7 +4885,7 @@
return;
}
- for (var interfaceNode in implementsClause.interfaces2) {
+ for (var interfaceNode in implementsClause.interfaces) {
var type = interfaceNode.type;
if (type is InterfaceType && type.element == superElement) {
errorReporter.reportErrorForNode(
@@ -4764,11 +4907,11 @@
!_checkForImplementsClauseErrorCodes(implementsClause)) {
// _checkForImplicitDynamicType(superclass);
_checkForRepeatedType(
- onClause?.superclassConstraints2,
+ onClause?.superclassConstraints,
CompileTimeErrorCode.ON_REPEATED,
);
_checkForRepeatedType(
- implementsClause?.interfaces2,
+ implementsClause?.interfaces,
CompileTimeErrorCode.IMPLEMENTS_REPEATED,
);
_checkForConflictingGenerics(node);
@@ -4789,7 +4932,7 @@
return;
}
- for (var mixinNode in withClause.mixinTypes2) {
+ for (var mixinNode in withClause.mixinTypes) {
var type = mixinNode.type;
if (type is InterfaceType && type.element == superElement) {
errorReporter.reportErrorForNode(
@@ -5155,3 +5298,11 @@
}
}
}
+
+extension on Object? {
+ /// If the target is [T], return it, otherwise `null`.
+ T? ifTypeOrNull<T>() {
+ final self = this;
+ return self is T ? self : null;
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 3735ddd..34d16ab 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -78,7 +78,7 @@
// Only the Allocator, Opaque and Struct class may be extended.
var extendsClause = node.extendsClause;
if (extendsClause != null) {
- final NamedType superclass = extendsClause.superclass2;
+ final NamedType superclass = extendsClause.superclass;
final ffiClass = superclass.ffiClass;
if (ffiClass != null) {
final className = ffiClass.name;
@@ -133,14 +133,14 @@
var implementsClause = node.implementsClause;
if (implementsClause != null) {
- for (NamedType type in implementsClause.interfaces2) {
+ for (NamedType type in implementsClause.interfaces) {
checkSupertype(type, FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS,
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS);
}
}
var withClause = node.withClause;
if (withClause != null) {
- for (NamedType type in withClause.mixinTypes2) {
+ for (NamedType type in withClause.mixinTypes) {
checkSupertype(type, FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH,
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH);
}
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 9ffdfb3..1d7b7a3 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -30,17 +30,20 @@
final AstBuilder astBuilder;
Parser(Source source, AnalysisErrorListener errorListener,
- {required FeatureSet featureSet, bool allowNativeClause = true})
+ {required FeatureSet featureSet,
+ bool allowNativeClause = true,
+ required LineInfo lineInfo})
: astBuilder = AstBuilder(
- ErrorReporter(
- errorListener,
- source,
- isNonNullableByDefault:
- featureSet.isEnabled(Feature.non_nullable),
- ),
- source.uri,
- true,
- featureSet) {
+ ErrorReporter(
+ errorListener,
+ source,
+ isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable),
+ ),
+ source.uri,
+ true,
+ featureSet,
+ lineInfo,
+ ) {
fastaParser = fasta.Parser(astBuilder);
astBuilder.parser = fastaParser;
astBuilder.allowNativeClause = allowNativeClause;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 5820062..92f03a7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -42,6 +43,7 @@
import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
import 'package:analyzer/src/dart/resolver/postfix_expression_resolver.dart';
@@ -69,6 +71,7 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/static_type_analyzer.dart';
import 'package:analyzer/src/generated/this_access_tracker.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/variable_type_provider.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
import 'package:meta/meta.dart';
@@ -80,11 +83,6 @@
/// Maintains and manages contextual type information used for
/// inferring types.
class InferenceContext {
- // TODO(leafp): Consider replacing these node properties with a
- // hash table help in an instance of this class.
- static const String _typeProperty =
- 'analyzer.src.generated.InferenceContext.contextType';
-
final ResolverVisitor _resolver;
/// The type system in use.
@@ -105,20 +103,17 @@
}
}
- void popFunctionBodyContext(FunctionBody node) {
+ DartType popFunctionBodyContext(FunctionBody node) {
var context = _bodyContexts.removeLast();
var flow = _resolver.flowAnalysis.flow;
- var resultType = context.computeInferredReturnType(
+ return context.computeInferredReturnType(
endOfBlockIsReachable: flow == null || flow.isReachable,
);
-
- setType(node, resultType);
}
- void pushFunctionBodyContext(FunctionBody node) {
- var imposedType = getContext(node);
+ void pushFunctionBodyContext(FunctionBody node, DartType? imposedType) {
_bodyContexts.add(
BodyInferenceContext(
typeSystem: _typeSystem,
@@ -127,38 +122,6 @@
),
);
}
-
- /// Clear the type information associated with [node].
- static void clearType(AstNode? node) {
- node?.setProperty(_typeProperty, null);
- }
-
- /// Look for contextual type information attached to [node], and returns
- /// the type if found.
- ///
- /// The returned type may be partially or completely unknown, denoted with an
- /// unknown type `_`, for example `List<_>` or `(_, int) -> void`.
- /// You can use [TypeSystemImpl.upperBoundForType] or
- /// [TypeSystemImpl.lowerBoundForType] if you would prefer a known type
- /// that represents the bound of the context type.
- static DartType? getContext(AstNode? node) =>
- node?.getProperty(_typeProperty);
-
- /// Attach contextual type information [type] to [node] for use during
- /// inference.
- static void setType(AstNode? node, DartType? type) {
- if (type == null || type.isDynamic) {
- clearType(node);
- } else {
- node?.setProperty(_typeProperty, type);
- }
- }
-
- /// Attach contextual type information [type] to [node] for use during
- /// inference.
- static void setTypeFromNode(AstNode innerNode, AstNode outerNode) {
- setType(innerNode, getContext(outerNode));
- }
}
/// Instances of the class `ResolverVisitor` are used to resolve the nodes
@@ -286,6 +249,8 @@
late final AnnotationResolver _annotationResolver = AnnotationResolver(this);
+ final bool genericMetadataIsEnabled;
+
/// Initialize a newly created visitor to resolve the nodes in an AST node.
///
/// The [definingLibrary] is the element for the library containing the node
@@ -338,7 +303,9 @@
isNonNullableByDefault: definingLibrary.isNonNullableByDefault,
),
_featureSet = featureSet,
- migrationResolutionHooks = migrationResolutionHooks {
+ migrationResolutionHooks = migrationResolutionHooks,
+ genericMetadataIsEnabled =
+ definingLibrary.featureSet.isEnabled(Feature.generic_metadata) {
var analysisOptions =
definingLibrary.context.analysisOptions as AnalysisOptionsImpl;
@@ -441,19 +408,19 @@
bool get _isNonNullableByDefault =>
_featureSet.isEnabled(Feature.non_nullable);
+ void analyzeExpression(Expression expression, DartType? contextType) {
+ if (contextType != null && contextType.isDynamic) {
+ contextType = null;
+ }
+ (expression as ExpressionImpl).resolveExpression(this, contextType);
+ }
+
/// Verify that the arguments in the given [argumentList] can be assigned to
/// their corresponding parameters.
///
/// See [CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
void checkForArgumentTypesNotAssignableInList(ArgumentList argumentList,
List<WhyNotPromotedGetter> whyNotPromotedList) {
- for (var argument in argumentList.arguments) {
- if (argument is NamedExpression) {
- insertImplicitCallReference(argument.expression);
- } else {
- insertImplicitCallReference(argument);
- }
- }
var arguments = argumentList.arguments;
for (int i = 0; i < arguments.length; i++) {
checkForArgumentTypeNotAssignableForArgument(arguments[i],
@@ -664,7 +631,8 @@
///
/// If an [FunctionReference] is inserted, returns it; otherwise, returns
/// [expression].
- ExpressionImpl insertGenericFunctionInstantiation(Expression expression) {
+ ExpressionImpl insertGenericFunctionInstantiation(Expression expression,
+ {required DartType? contextType}) {
expression as ExpressionImpl;
if (!isConstructorTearoffsEnabled) {
// Temporarily, only create [ImplicitCallReference] nodes under the
@@ -675,7 +643,7 @@
}
var staticType = expression.staticType;
- var context = InferenceContext.getContext(expression);
+ var context = contextType;
if (context == null ||
staticType is! FunctionType ||
staticType.typeFormals.isEmpty) {
@@ -715,70 +683,6 @@
return genericFunctionInstantiation;
}
- /// If `expression` should be treated as `expression.call`, inserts an
- /// [ImplicitCallReferece] node which wraps [expression].
- ///
- /// If an [ImplicitCallReferece] is inserted, returns it; otherwise, returns
- /// [expression].
- ExpressionImpl insertImplicitCallReference(Expression expression) {
- expression as ExpressionImpl;
- if (!isConstructorTearoffsEnabled) {
- // Temporarily, only create [ImplicitCallReference] nodes under the
- // 'constructor-tearoffs' feature.
- // TODO(srawlins): When we are ready to make a breaking change release to
- // the analyzer package, remove this exception.
- return expression;
- }
-
- var parent = expression.parent;
- if (parent is CascadeExpression && parent.target == expression) {
- // Do not perform an "implicit tear-off conversion" here. It should only
- // be performed on [parent]. See
- // https://github.com/dart-lang/language/issues/1873.
- return expression;
- }
- var context = InferenceContext.getContext(expression);
- var callMethod =
- getImplicitCallMethod(expression.typeOrThrow, context, expression);
- if (callMethod == null || context == null) {
- return expression;
- }
-
- // `expression` is to be treated as `expression.call`.
- context = typeSystem.flatten(context);
- var callMethodType = callMethod.type;
- List<DartType> typeArgumentTypes;
- if (isConstructorTearoffsEnabled &&
- callMethodType.typeFormals.isNotEmpty &&
- context is FunctionType) {
- typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
- context,
- callMethodType,
- errorReporter: errorReporter,
- errorNode: expression,
- // If the constructor-tearoffs feature is enabled, then so is
- // generic-metadata.
- genericMetadataIsEnabled: true,
- )!;
- if (typeArgumentTypes.isNotEmpty) {
- callMethodType = callMethodType.instantiate(typeArgumentTypes);
- }
- } else {
- typeArgumentTypes = [];
- }
- var callReference = astFactory.implicitCallReference(
- expression: expression,
- staticElement: callMethod,
- typeArguments: null,
- typeArgumentTypes: typeArgumentTypes,
- );
- NodeReplacer.replace(expression, callReference, parent: parent);
-
- callReference.staticType = callMethodType;
-
- return callReference;
- }
-
/// If we reached a null-shorting termination, and the [node] has null
/// shorting, make the type of the [node] nullable.
void nullShortingTermination(ExpressionImpl node,
@@ -875,8 +779,7 @@
hasWrite: true,
);
- InferenceContext.setType(node.index, result.indexContextType);
- node.index.accept(this);
+ analyzeExpression(node.index, result.indexContextType);
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
checkIndexExpressionIndex(
node.index,
@@ -1059,10 +962,11 @@
}
@override
- void visitAdjacentStrings(AdjacentStrings node) {
+ void visitAdjacentStrings(AdjacentStrings node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitAdjacentStrings(node as AdjacentStringsImpl);
+ typeAnalyzer.visitAdjacentStrings(node as AdjacentStringsImpl,
+ contextType: contextType);
}
@override
@@ -1076,97 +980,21 @@
}
@override
- void visitArgumentList(ArgumentList node,
- {bool isIdentical = false,
- List<WhyNotPromotedGetter>? whyNotPromotedList}) {
- whyNotPromotedList ??= [];
- var callerType = InferenceContext.getContext(node);
- NodeList<Expression> arguments = node.arguments;
- if (callerType is FunctionType) {
- var parameters = callerType.parameters;
-
- var namedParameters = <String, ParameterElement>{};
- for (var i = 0; i < parameters.length; i++) {
- var parameter = parameters[i];
- if (parameter.isNamed) {
- namedParameters[parameter.name] = parameter;
- }
- }
-
- var parent = node.parent;
- DartType? targetType;
- Element? methodElement;
- DartType? invocationContext;
- if (parent is MethodInvocation) {
- targetType = parent.realTarget?.staticType;
- methodElement = parent.methodName.staticElement;
- invocationContext = InferenceContext.getContext(parent);
- }
-
- //TODO(leafp): Consider using the parameter elements here instead.
- //TODO(leafp): Make sure that the parameter elements are getting
- // setup correctly with inference.
- var positionalParameterIndex = 0;
- for (var i = 0; i < arguments.length; i++) {
- var argument = arguments[i];
- ParameterElement? parameter;
- if (argument is NamedExpression) {
- parameter = namedParameters[argument.name.label.name];
- } else {
- while (positionalParameterIndex < parameters.length) {
- parameter = parameters[positionalParameterIndex++];
- if (!parameter.isNamed) {
- break;
- }
- }
- }
- if (parameter != null) {
- var parameterType = parameter.type;
- if (targetType != null) {
- InferenceContext.setType(
- argument,
- typeSystem.refineNumericInvocationContext(targetType,
- methodElement, invocationContext, parameterType));
- } else {
- InferenceContext.setType(argument, parameterType);
- }
- }
- }
- }
- checkUnreachableNode(node);
- int length = arguments.length;
- var flow = flowAnalysis.flow;
- for (var i = 0; i < length; i++) {
- if (isIdentical && length > 1 && i == 1) {
- var firstArg = arguments[0];
- flow?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
- }
- arguments[i].accept(this);
- if (flow != null) {
- whyNotPromotedList.add(flow.whyNotPromoted(arguments[i]));
- }
- }
- if (isIdentical && length > 1) {
- var secondArg = arguments[1];
- flow?.equalityOp_end(
- node.parent as Expression, secondArg, secondArg.typeOrThrow);
- }
- }
-
- @override
- void visitAsExpression(AsExpression node) {
+ void visitAsExpression(AsExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitAsExpression(node as AsExpressionImpl);
+ typeAnalyzer.visitAsExpression(node as AsExpressionImpl,
+ contextType: contextType);
flowAnalysis.asExpression(node);
- insertGenericFunctionInstantiation(node);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
void visitAssertInitializer(AssertInitializer node) {
- InferenceContext.setType(node.condition, typeProvider.boolType);
flowAnalysis.flow?.assert_begin();
- node.condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
boolExpressionVerifier.checkForNonBoolExpression(
node.condition,
errorCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
@@ -1179,9 +1007,8 @@
@override
void visitAssertStatement(AssertStatement node) {
- InferenceContext.setType(node.condition, typeProvider.boolType);
flowAnalysis.flow?.assert_begin();
- node.condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
boolExpressionVerifier.checkForNonBoolExpression(
node.condition,
errorCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
@@ -1193,33 +1020,41 @@
}
@override
- void visitAssignmentExpression(AssignmentExpression node) {
- _assignmentExpressionResolver.resolve(node as AssignmentExpressionImpl);
- insertGenericFunctionInstantiation(node);
+ void visitAssignmentExpression(AssignmentExpression node,
+ {DartType? contextType}) {
+ _assignmentExpressionResolver.resolve(node as AssignmentExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitAwaitExpression(AwaitExpression node) {
- var contextType = InferenceContext.getContext(node);
+ void visitAwaitExpression(AwaitExpression node, {DartType? contextType}) {
+ DartType? futureUnion;
if (contextType != null) {
- var futureUnion = _createFutureOr(contextType);
- InferenceContext.setType(node.expression, futureUnion);
+ futureUnion = _createFutureOr(contextType);
}
checkUnreachableNode(node);
- node.visitChildren(this);
- typeAnalyzer.visitAwaitExpression(node as AwaitExpressionImpl);
- insertGenericFunctionInstantiation(node);
+ analyzeExpression(node.expression, futureUnion);
+ typeAnalyzer.visitAwaitExpression(node as AwaitExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitBinaryExpression(BinaryExpression node) {
+ void visitBinaryExpression(BinaryExpression node, {DartType? contextType}) {
var migrationResolutionHooks = this.migrationResolutionHooks;
if (migrationResolutionHooks != null) {
- migrationResolutionHooks.reportBinaryExpressionContext(
- node, InferenceContext.getContext(node));
+ migrationResolutionHooks.reportBinaryExpressionContext(node, contextType);
}
- _binaryExpressionResolver.resolve(node as BinaryExpressionImpl);
- insertGenericFunctionInstantiation(node);
+ _binaryExpressionResolver.resolve(node as BinaryExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
@@ -1229,24 +1064,27 @@
}
@override
- void visitBlockFunctionBody(BlockFunctionBody node) {
+ DartType visitBlockFunctionBody(BlockFunctionBody node,
+ {DartType? imposedType}) {
try {
- inferenceContext.pushFunctionBodyContext(node);
+ inferenceContext.pushFunctionBodyContext(node, imposedType);
_thisAccessTracker.enterFunctionBody(node);
checkUnreachableNode(node);
node.visitChildren(this);
} finally {
_thisAccessTracker.exitFunctionBody(node);
- inferenceContext.popFunctionBodyContext(node);
+ imposedType = inferenceContext.popFunctionBodyContext(node);
}
+ return imposedType;
}
@override
- void visitBooleanLiteral(BooleanLiteral node) {
+ void visitBooleanLiteral(BooleanLiteral node, {DartType? contextType}) {
flowAnalysis.flow?.booleanLiteral(node, node.value);
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitBooleanLiteral(node as BooleanLiteralImpl);
+ typeAnalyzer.visitBooleanLiteral(node as BooleanLiteralImpl,
+ contextType: contextType);
}
@override
@@ -1260,9 +1098,9 @@
}
@override
- void visitCascadeExpression(covariant CascadeExpressionImpl node) {
- InferenceContext.setTypeFromNode(node.target, node);
- node.target.accept(this);
+ void visitCascadeExpression(covariant CascadeExpressionImpl node,
+ {DartType? contextType}) {
+ analyzeExpression(node.target, contextType);
if (node.isNullAware) {
flowAnalysis.flow!.nullAwareAccess_rightBegin(
@@ -1272,9 +1110,10 @@
node.cascadeSections.accept(this);
- typeAnalyzer.visitCascadeExpression(node);
+ typeAnalyzer.visitCascadeExpression(node, contextType: contextType);
nullShortingTermination(node);
+ _insertImplicitCallReference(node, contextType: contextType);
}
@override
@@ -1336,43 +1175,42 @@
}
@override
- void visitConditionalExpression(ConditionalExpression node) {
+ void visitConditionalExpression(ConditionalExpression node,
+ {DartType? contextType}) {
Expression condition = node.condition;
var flow = flowAnalysis.flow;
flow?.conditional_conditionBegin();
// TODO(scheglov) Do we need these checks for null?
- InferenceContext.setType(node.condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
boolExpressionVerifier.checkForNonBoolCondition(condition,
whyNotPromoted: whyNotPromoted);
- InferenceContext.setTypeFromNode(node.thenExpression, node);
-
if (flow != null) {
flow.conditional_thenBegin(condition, node);
checkUnreachableNode(node.thenExpression);
}
- node.thenExpression.accept(this);
+ analyzeExpression(node.thenExpression, contextType);
nullSafetyDeadCodeVerifier.flowEnd(node.thenExpression);
Expression elseExpression = node.elseExpression;
- InferenceContext.setTypeFromNode(elseExpression, node);
if (flow != null) {
flow.conditional_elseBegin(node.thenExpression);
checkUnreachableNode(elseExpression);
- elseExpression.accept(this);
+ analyzeExpression(elseExpression, contextType);
flow.conditional_end(node, elseExpression);
nullSafetyDeadCodeVerifier.flowEnd(elseExpression);
} else {
- elseExpression.accept(this);
+ analyzeExpression(elseExpression, contextType);
}
elseExpression = node.elseExpression;
- typeAnalyzer.visitConditionalExpression(node as ConditionalExpressionImpl);
+ typeAnalyzer.visitConditionalExpression(node as ConditionalExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(node, contextType: contextType);
}
@override
@@ -1382,12 +1220,11 @@
}
@override
- void visitConstructorDeclaration(ConstructorDeclaration node) {
+ void visitConstructorDeclaration(covariant ConstructorDeclarationImpl node) {
flowAnalysis.topLevelDeclaration_enter(node, node.parameters);
flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
var returnType = node.declaredElement!.type.returnType;
- InferenceContext.setType(node.body, returnType);
var outerFunction = _enclosingFunction;
try {
@@ -1395,7 +1232,14 @@
assert(_thisType == null);
_setupThisType();
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.documentationComment?.accept(this);
+ node.metadata.accept(this);
+ node.returnType.accept(this);
+ node.name?.accept(this);
+ node.parameters.accept(this);
+ node.initializers.accept(this);
+ node.redirectedConstructor?.accept(this);
+ node.body.resolve(this, returnType.isDynamic ? null : returnType);
elementResolver.visitConstructorDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -1422,20 +1266,12 @@
var fieldElement = enclosingClass!.getField(node.fieldName.name);
var fieldType = fieldElement?.type;
var expression = node.expression;
- InferenceContext.setType(expression, fieldType);
- expression.accept(this);
+ analyzeExpression(expression, fieldType);
expression = node.expression;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression);
elementResolver.visitConstructorFieldInitializer(
node as ConstructorFieldInitializerImpl);
if (fieldElement != null) {
- if (fieldType != null && expression.staticType != null) {
- var callReference = insertImplicitCallReference(expression);
- if (expression != callReference) {
- checkForInvalidAssignment(node.fieldName, callReference,
- whyNotPromoted: whyNotPromoted);
- }
- }
var enclosingConstructor = enclosingFunction as ConstructorElement;
checkForFieldInitializerNotAssignable(node, fieldElement,
isConstConstructor: enclosingConstructor.isConst,
@@ -1445,13 +1281,15 @@
@override
void visitConstructorName(ConstructorName node) {
- node.type2.accept(this);
+ node.type.accept(this);
elementResolver.visitConstructorName(node as ConstructorNameImpl);
}
@override
- void visitConstructorReference(covariant ConstructorReferenceImpl node) {
- _constructorReferenceResolver.resolve(node);
+ void visitConstructorReference(covariant ConstructorReferenceImpl node,
+ {DartType? contextType}) {
+ _constructorReferenceResolver.resolve(node, contextType: contextType);
+ _insertImplicitCallReference(node, contextType: contextType);
}
@override
@@ -1479,13 +1317,16 @@
@override
void visitDefaultFormalParameter(DefaultFormalParameter node) {
- InferenceContext.setType(node.defaultValue, node.declaredElement?.type);
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.parameter.accept(this);
+ var defaultValue = node.defaultValue;
+ if (defaultValue != null) {
+ analyzeExpression(defaultValue, node.declaredElement?.type);
+ }
ParameterElement element = node.declaredElement!;
if (element is DefaultParameterElementImpl && node.isOfLocalFunction) {
- element.constantInitializer = node.defaultValue;
+ element.constantInitializer = defaultValue;
}
}
@@ -1499,8 +1340,7 @@
node.body.accept(this);
flowAnalysis.flow?.doStatement_conditionBegin();
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
boolExpressionVerifier.checkForNonBoolCondition(condition,
@@ -1510,19 +1350,21 @@
}
@override
- void visitDoubleLiteral(DoubleLiteral node) {
+ void visitDoubleLiteral(DoubleLiteral node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitDoubleLiteral(node as DoubleLiteralImpl);
+ typeAnalyzer.visitDoubleLiteral(node as DoubleLiteralImpl,
+ contextType: contextType);
}
@override
- void visitEmptyFunctionBody(EmptyFunctionBody node) {
- if (resolveOnlyCommentInFunctionBody) {
- return;
+ DartType visitEmptyFunctionBody(EmptyFunctionBody node,
+ {DartType? imposedType}) {
+ if (!resolveOnlyCommentInFunctionBody) {
+ checkUnreachableNode(node);
+ node.visitChildren(this);
}
- checkUnreachableNode(node);
- node.visitChildren(this);
+ return imposedType ?? typeProvider.dynamicType;
}
@override
@@ -1548,27 +1390,66 @@
var element = node.declaredElement as ConstFieldElementImpl;
var initializer = element.constantInitializer;
if (initializer is InstanceCreationExpression) {
- var constructor = initializer.constructorName.staticElement;
- node.constructorElement = constructor;
- var arguments = node.arguments;
- if (arguments != null) {
- var argumentList = arguments.argumentList;
- if (constructor != null) {
- InferenceContext.setType(argumentList, constructor.type);
+ var constructorName = initializer.constructorName;
+ var constructorElement = constructorName.staticElement;
+ if (constructorElement != null) {
+ node.constructorElement = constructorElement;
+ if (!constructorElement.isConst && constructorElement.isFactory) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR,
+ node.arguments?.constructorSelector?.name ?? node.name,
+ );
+ }
+ } else {
+ var typeName = constructorName.type.name;
+ if (typeName.staticElement is EnumElementImpl) {
+ var nameNode = node.arguments?.constructorSelector?.name;
+ if (nameNode != null) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED,
+ nameNode,
+ [nameNode.name],
+ );
+ } else {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED,
+ node.name,
+ );
+ }
+ }
+ }
+ if (constructorElement != null) {
+ var arguments = node.arguments;
+ if (arguments != null) {
+ var argumentList = arguments.argumentList;
argumentList.correspondingStaticParameters =
ResolverVisitor.resolveArgumentsToParameters(
argumentList: argumentList,
- parameters: constructor.parameters,
+ parameters: constructorElement.parameters,
+ errorReporter: errorReporter,
);
for (var argument in argumentList.arguments) {
- var parameter = argument.staticParameterElement;
- if (parameter != null) {
- InferenceContext.setType(argument, parameter.type);
- }
- argument.accept(this);
+ analyzeExpression(argument, argument.staticParameterElement?.type);
+ }
+ arguments.typeArguments?.accept(this);
+
+ var whyNotPromotedList =
+ <Map<DartType, NonPromotionReason> Function()>[];
+ checkForArgumentTypesNotAssignableInList(
+ argumentList, whyNotPromotedList);
+ } else if (definingLibrary.featureSet
+ .isEnabled(Feature.enhanced_enums)) {
+ var requiredParameterCount = constructorElement.parameters
+ .where((e) => e.isRequiredPositional)
+ .length;
+ if (requiredParameterCount != 0) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+ node.name,
+ [requiredParameterCount, 0],
+ );
}
}
- arguments.typeArguments?.accept(this);
}
}
@@ -1599,30 +1480,30 @@
}
@override
- void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ DartType visitExpressionFunctionBody(ExpressionFunctionBody node,
+ {DartType? imposedType}) {
if (resolveOnlyCommentInFunctionBody) {
- return;
+ return imposedType ?? typeProvider.dynamicType;
}
try {
- inferenceContext.pushFunctionBodyContext(node);
- InferenceContext.setType(
- node.expression,
- inferenceContext.bodyContext!.contextType,
- );
+ inferenceContext.pushFunctionBodyContext(node, imposedType);
_thisAccessTracker.enterFunctionBody(node);
checkUnreachableNode(node);
- node.visitChildren(this);
- insertImplicitCallReference(node.expression);
+ analyzeExpression(
+ node.expression,
+ inferenceContext.bodyContext!.contextType,
+ );
flowAnalysis.flow?.handleExit();
inferenceContext.bodyContext!.addReturnExpression(node.expression);
} finally {
_thisAccessTracker.exitFunctionBody(node);
- inferenceContext.popFunctionBodyContext(node);
+ imposedType = inferenceContext.popFunctionBodyContext(node);
}
+ return imposedType;
}
@override
@@ -1651,13 +1532,28 @@
}
@override
- void visitExtensionOverride(ExtensionOverride node) {
+ void visitExtensionOverride(covariant ExtensionOverrideImpl node,
+ {DartType? contextType}) {
var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
node.extensionName.accept(this);
node.typeArguments?.accept(this);
- ExtensionMemberResolver(this).setOverrideReceiverContextType(node);
- visitArgumentList(node.argumentList,
+ var receiverContextType =
+ ExtensionMemberResolver(this).computeOverrideReceiverContextType(node);
+ const ExtensionOverrideInferrer().resolveInvocation(
+ resolver: this,
+ node: node,
+ rawType: receiverContextType == null
+ ? null
+ : FunctionTypeImpl(
+ typeFormals: const [],
+ parameters: [
+ ParameterElementImpl.synthetic(
+ null, receiverContextType, ParameterKind.REQUIRED)
+ ],
+ returnType: DynamicTypeImpl.instance,
+ nullabilitySuffix: NullabilitySuffix.none),
+ contextType: null,
whyNotPromotedList: whyNotPromotedList);
extensionResolver.resolveOverride(node, whyNotPromotedList);
@@ -1686,8 +1582,8 @@
}
@override
- void visitForElement(ForElement node) {
- _forResolver.resolveElement(node as ForElementImpl);
+ void visitForElement(ForElement node, {CollectionLiteralContext? context}) {
+ _forResolver.resolveElement(node as ForElementImpl, context);
}
@override
@@ -1719,13 +1615,16 @@
);
var functionType = node.declaredElement!.type;
- InferenceContext.setType(node.functionExpression, functionType);
var outerFunction = _enclosingFunction;
try {
_enclosingFunction = node.declaredElement;
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.documentationComment?.accept(this);
+ node.metadata.accept(this);
+ node.returnType?.accept(this);
+ node.name.accept(this);
+ analyzeExpression(node.functionExpression, functionType);
elementResolver.visitFunctionDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -1756,30 +1655,35 @@
}
@override
- void visitFunctionExpression(covariant FunctionExpressionImpl node) {
+ void visitFunctionExpression(covariant FunctionExpressionImpl node,
+ {DartType? contextType}) {
var outerFunction = _enclosingFunction;
_enclosingFunction = node.declaredElement;
- _functionExpressionResolver.resolve(node);
- insertGenericFunctionInstantiation(node);
+ _functionExpressionResolver.resolve(node, contextType: contextType);
+ insertGenericFunctionInstantiation(node, contextType: contextType);
_enclosingFunction = outerFunction;
}
@override
- void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ void visitFunctionExpressionInvocation(FunctionExpressionInvocation node,
+ {DartType? contextType}) {
var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
node.function.accept(this);
_functionExpressionInvocationResolver.resolve(
- node as FunctionExpressionInvocationImpl, whyNotPromotedList);
+ node as FunctionExpressionInvocationImpl, whyNotPromotedList,
+ contextType: contextType);
nullShortingTermination(node);
- insertGenericFunctionInstantiation(node);
+ var replacement =
+ insertGenericFunctionInstantiation(node, contextType: contextType);
checkForArgumentTypesNotAssignableInList(
node.argumentList, whyNotPromotedList);
+ _insertImplicitCallReference(replacement, contextType: contextType);
}
@override
- void visitFunctionReference(FunctionReference node) {
+ void visitFunctionReference(FunctionReference node, {DartType? contextType}) {
_functionReferenceResolver.resolve(node as FunctionReferenceImpl);
}
@@ -1814,11 +1718,10 @@
void visitHideCombinator(HideCombinator node) {}
@override
- void visitIfElement(IfElement node) {
+ void visitIfElement(IfElement node, {CollectionLiteralContext? context}) {
flowAnalysis.flow?.ifStatement_conditionBegin();
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -1826,13 +1729,13 @@
whyNotPromoted: whyNotPromoted);
flowAnalysis.flow?.ifStatement_thenBegin(condition, node);
- node.thenElement.accept(this);
+ (node.thenElement as CollectionElementImpl).resolveElement(this, context);
nullSafetyDeadCodeVerifier.flowEnd(node.thenElement);
var elseElement = node.elseElement;
if (elseElement != null) {
flowAnalysis.flow?.ifStatement_elseBegin();
- elseElement.accept(this);
+ (elseElement as CollectionElementImpl).resolveElement(this, context);
nullSafetyDeadCodeVerifier.flowEnd(elseElement);
}
@@ -1846,8 +1749,7 @@
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -1875,9 +1777,11 @@
}
@override
- void visitImplicitCallReference(ImplicitCallReference node) {
+ void visitImplicitCallReference(ImplicitCallReference node,
+ {DartType? contextType}) {
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(node.expression, null);
+ node.typeArguments?.accept(this);
}
@override
@@ -1888,7 +1792,8 @@
}
@override
- void visitIndexExpression(covariant IndexExpressionImpl node) {
+ void visitIndexExpression(covariant IndexExpressionImpl node,
+ {DartType? contextType}) {
node.target?.accept(this);
startNullAwareIndexExpression(node);
@@ -1901,8 +1806,7 @@
var element = result.readElement;
node.staticElement = element as MethodElement?;
- InferenceContext.setType(node.index, result.indexContextType);
- node.index.accept(this);
+ analyzeExpression(node.index, result.indexContextType);
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
checkIndexExpressionIndex(
node.index,
@@ -1919,23 +1823,28 @@
} else {
type = DynamicTypeImpl.instance;
}
- inferenceHelper.recordStaticType(node, type);
- insertGenericFunctionInstantiation(node);
+ inferenceHelper.recordStaticType(node, type, contextType: contextType);
+ var replacement =
+ insertGenericFunctionInstantiation(node, contextType: contextType);
nullShortingTermination(node);
+ _insertImplicitCallReference(replacement, contextType: contextType);
}
@override
void visitInstanceCreationExpression(
- covariant InstanceCreationExpressionImpl node) {
- _instanceCreationExpressionResolver.resolve(node);
+ covariant InstanceCreationExpressionImpl node,
+ {DartType? contextType}) {
+ _instanceCreationExpressionResolver.resolve(node, contextType: contextType);
+ _insertImplicitCallReference(node, contextType: contextType);
}
@override
- void visitIntegerLiteral(IntegerLiteral node) {
+ void visitIntegerLiteral(IntegerLiteral node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitIntegerLiteral(node);
+ typeAnalyzer.visitIntegerLiteral(node as IntegerLiteralImpl,
+ contextType: contextType);
}
@override
@@ -1951,10 +1860,11 @@
}
@override
- void visitIsExpression(IsExpression node) {
+ void visitIsExpression(IsExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitIsExpression(node as IsExpressionImpl);
+ typeAnalyzer.visitIsExpression(node as IsExpressionImpl,
+ contextType: contextType);
flowAnalysis.isExpression(node);
}
@@ -1977,27 +1887,30 @@
}
@override
- void visitLibraryIdentifier(LibraryIdentifier node) {}
+ void visitLibraryIdentifier(LibraryIdentifier node,
+ {DartType? contextType}) {}
@override
- void visitListLiteral(covariant ListLiteralImpl node) {
+ void visitListLiteral(covariant ListLiteralImpl node,
+ {DartType? contextType}) {
checkUnreachableNode(node);
- _typedLiteralResolver.resolveListLiteral(node);
+ _typedLiteralResolver.resolveListLiteral(node, contextType: contextType);
}
@override
- void visitMapLiteralEntry(MapLiteralEntry node) {
+ void visitMapLiteralEntry(MapLiteralEntry node,
+ {CollectionLiteralContext? context}) {
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(node.key, context?.keyType);
+ analyzeExpression(node.value, context?.valueType);
}
@override
- void visitMethodDeclaration(MethodDeclaration node) {
+ void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
flowAnalysis.topLevelDeclaration_enter(node, node.parameters);
flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
DartType returnType = node.declaredElement!.returnType;
- InferenceContext.setType(node.body, returnType);
var outerFunction = _enclosingFunction;
try {
@@ -2005,7 +1918,13 @@
assert(_thisType == null);
_setupThisType();
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.documentationComment?.accept(this);
+ node.metadata.accept(this);
+ node.returnType?.accept(this);
+ node.name.accept(this);
+ node.typeParameters?.accept(this);
+ node.parameters?.accept(this);
+ node.body.resolve(this, returnType.isDynamic ? null : returnType);
elementResolver.visitMethodDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -2024,7 +1943,8 @@
}
@override
- void visitMethodInvocation(covariant MethodInvocationImpl node) {
+ void visitMethodInvocation(covariant MethodInvocationImpl node,
+ {DartType? contextType}) {
var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
var target = node.target;
target?.accept(this);
@@ -2046,19 +1966,22 @@
node.typeArguments?.accept(this);
elementResolver.visitMethodInvocation(node,
- whyNotPromotedList: whyNotPromotedList);
+ whyNotPromotedList: whyNotPromotedList, contextType: contextType);
var functionRewrite = MethodInvocationResolver.getRewriteResult(node);
if (functionRewrite != null) {
_resolveRewrittenFunctionExpressionInvocation(
- functionRewrite, whyNotPromotedList);
+ functionRewrite, whyNotPromotedList,
+ contextType: contextType);
nullShortingTermination(node, discardType: true);
} else {
nullShortingTermination(node);
}
- insertGenericFunctionInstantiation(node);
+ var replacement =
+ insertGenericFunctionInstantiation(node, contextType: contextType);
checkForArgumentTypesNotAssignableInList(
node.argumentList, whyNotPromotedList);
+ _insertImplicitCallReference(replacement, contextType: contextType);
}
@override
@@ -2078,11 +2001,12 @@
}
@override
- void visitNamedExpression(NamedExpression node) {
- InferenceContext.setTypeFromNode(node.expression, node);
+ void visitNamedExpression(NamedExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
- node.visitChildren(this);
- typeAnalyzer.visitNamedExpression(node as NamedExpressionImpl);
+ node.name.accept(this);
+ analyzeExpression(node.expression, contextType);
+ typeAnalyzer.visitNamedExpression(node as NamedExpressionImpl,
+ contextType: contextType);
// Any "why not promoted" information that flow analysis had associated with
// `node.expression` now needs to be forwarded to `node`, so that when
// `visitArgumentList` iterates through the arguments, it will find it.
@@ -2105,17 +2029,20 @@
}
@override
- void visitNativeFunctionBody(NativeFunctionBody node) {
+ DartType visitNativeFunctionBody(NativeFunctionBody node,
+ {DartType? imposedType}) {
checkUnreachableNode(node);
node.visitChildren(this);
+ return imposedType ?? typeProvider.dynamicType;
}
@override
- void visitNullLiteral(NullLiteral node) {
+ void visitNullLiteral(NullLiteral node, {DartType? contextType}) {
flowAnalysis.flow?.nullLiteral(node);
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitNullLiteral(node as NullLiteralImpl);
+ typeAnalyzer.visitNullLiteral(node as NullLiteralImpl,
+ contextType: contextType);
}
@override
@@ -2125,12 +2052,13 @@
}
@override
- void visitParenthesizedExpression(ParenthesizedExpression node) {
- InferenceContext.setTypeFromNode(node.expression, node);
+ void visitParenthesizedExpression(ParenthesizedExpression node,
+ {DartType? contextType}) {
checkUnreachableNode(node);
- node.visitChildren(this);
- typeAnalyzer
- .visitParenthesizedExpression(node as ParenthesizedExpressionImpl);
+ analyzeExpression(node.expression, contextType);
+ typeAnalyzer.visitParenthesizedExpression(
+ node as ParenthesizedExpressionImpl,
+ contextType: contextType);
flowAnalysis.flow?.parenthesizedExpression(node, node.expression);
}
@@ -2149,25 +2077,35 @@
}
@override
- void visitPostfixExpression(PostfixExpression node) {
- _postfixExpressionResolver.resolve(node as PostfixExpressionImpl);
- insertGenericFunctionInstantiation(node);
+ void visitPostfixExpression(PostfixExpression node, {DartType? contextType}) {
+ _postfixExpressionResolver.resolve(node as PostfixExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitPrefixedIdentifier(covariant PrefixedIdentifierImpl node) {
- _prefixedIdentifierResolver.resolve(node);
- insertGenericFunctionInstantiation(node);
+ void visitPrefixedIdentifier(covariant PrefixedIdentifierImpl node,
+ {DartType? contextType}) {
+ _prefixedIdentifierResolver.resolve(node, contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitPrefixExpression(PrefixExpression node) {
- _prefixExpressionResolver.resolve(node as PrefixExpressionImpl);
- insertGenericFunctionInstantiation(node);
+ void visitPrefixExpression(PrefixExpression node, {DartType? contextType}) {
+ _prefixExpressionResolver.resolve(node as PrefixExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitPropertyAccess(covariant PropertyAccessImpl node) {
+ void visitPropertyAccess(covariant PropertyAccessImpl node,
+ {DartType? contextType}) {
node.target?.accept(this);
startNullAwarePropertyAccess(node);
@@ -2200,14 +2138,17 @@
// sites.
// TODO(srawlins): Switch all resolution to use the latter method, in a
// breaking change release.
- type = inferenceHelper.inferTearOff(node, propertyName, type);
+ type = inferenceHelper.inferTearOff(node, propertyName, type,
+ contextType: contextType);
}
- inferenceHelper.recordStaticType(propertyName, type);
- inferenceHelper.recordStaticType(node, type);
- insertGenericFunctionInstantiation(node);
+ inferenceHelper.recordStaticType(propertyName, type, contextType: null);
+ inferenceHelper.recordStaticType(node, type, contextType: contextType);
+ var replacement =
+ insertGenericFunctionInstantiation(node, contextType: contextType);
nullShortingTermination(node);
+ _insertImplicitCallReference(replacement, contextType: contextType);
}
@override
@@ -2221,44 +2162,47 @@
var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
elementResolver.visitRedirectingConstructorInvocation(
node as RedirectingConstructorInvocationImpl);
- InferenceContext.setType(node.argumentList, node.staticElement?.type);
- visitArgumentList(node.argumentList,
+ const RedirectingConstructorInvocationInferrer().resolveInvocation(
+ resolver: this,
+ node: node,
+ rawType: node.staticElement?.type,
+ contextType: null,
whyNotPromotedList: whyNotPromotedList);
checkForArgumentTypesNotAssignableInList(
node.argumentList, whyNotPromotedList);
}
@override
- void visitRethrowExpression(RethrowExpression node) {
+ void visitRethrowExpression(RethrowExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitRethrowExpression(node as RethrowExpressionImpl);
+ typeAnalyzer.visitRethrowExpression(node as RethrowExpressionImpl,
+ contextType: contextType);
flowAnalysis.flow?.handleExit();
}
@override
void visitReturnStatement(ReturnStatement node) {
- InferenceContext.setType(
- node.expression,
- inferenceContext.bodyContext?.contextType,
- );
-
checkUnreachableNode(node);
- node.visitChildren(this);
-
- inferenceContext.bodyContext?.addReturnExpression(node.expression);
- flowAnalysis.flow?.handleExit();
-
var expression = node.expression;
if (expression != null) {
- insertImplicitCallReference(expression);
+ analyzeExpression(
+ expression,
+ inferenceContext.bodyContext?.contextType,
+ );
+ // Pick up the expression again in case it was rewritten.
+ expression = node.expression;
}
+
+ inferenceContext.bodyContext?.addReturnExpression(expression);
+ flowAnalysis.flow?.handleExit();
}
@override
- void visitSetOrMapLiteral(SetOrMapLiteral node) {
+ void visitSetOrMapLiteral(SetOrMapLiteral node, {DartType? contextType}) {
checkUnreachableNode(node);
- _typedLiteralResolver.resolveSetOrMapLiteral(node);
+ _typedLiteralResolver.resolveSetOrMapLiteral(node,
+ contextType: contextType);
}
@override
@@ -2272,22 +2216,32 @@
}
@override
- void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
- _simpleIdentifierResolver.resolve(node);
- insertGenericFunctionInstantiation(node);
+ void visitSimpleIdentifier(covariant SimpleIdentifierImpl node,
+ {DartType? contextType}) {
+ _simpleIdentifierResolver.resolve(node, contextType: contextType);
+ _insertImplicitCallReference(
+ insertGenericFunctionInstantiation(node, contextType: contextType),
+ contextType: contextType);
}
@override
- void visitSimpleStringLiteral(SimpleStringLiteral node) {
+ void visitSimpleStringLiteral(SimpleStringLiteral node,
+ {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitSimpleStringLiteral(node as SimpleStringLiteralImpl);
+ typeAnalyzer.visitSimpleStringLiteral(node as SimpleStringLiteralImpl,
+ contextType: contextType);
}
@override
- void visitSpreadElement(SpreadElement node) {
+ void visitSpreadElement(SpreadElement node,
+ {CollectionLiteralContext? context}) {
+ var iterableType = context?.iterableType;
+ if (iterableType != null && _isNonNullableByDefault && node.isNullAware) {
+ iterableType = typeSystem.makeNullable(iterableType);
+ }
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(node.expression, iterableType);
if (!node.isNullAware) {
nullableDereferenceVerifier.expression(
@@ -2298,10 +2252,12 @@
}
@override
- void visitStringInterpolation(StringInterpolation node) {
+ void visitStringInterpolation(StringInterpolation node,
+ {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitStringInterpolation(node as StringInterpolationImpl);
+ typeAnalyzer.visitStringInterpolation(node as StringInterpolationImpl,
+ contextType: contextType);
}
@override
@@ -2314,19 +2270,23 @@
var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
elementResolver.visitSuperConstructorInvocation(
node as SuperConstructorInvocationImpl);
- InferenceContext.setType(node.argumentList, node.staticElement?.type);
- visitArgumentList(node.argumentList,
+ const SuperConstructorInvocationInferrer().resolveInvocation(
+ resolver: this,
+ node: node,
+ rawType: node.staticElement?.type,
+ contextType: null,
whyNotPromotedList: whyNotPromotedList);
checkForArgumentTypesNotAssignableInList(
node.argumentList, whyNotPromotedList);
}
@override
- void visitSuperExpression(SuperExpression node) {
+ void visitSuperExpression(SuperExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
elementResolver.visitSuperExpression(node);
- typeAnalyzer.visitSuperExpression(node as SuperExpressionImpl);
+ typeAnalyzer.visitSuperExpression(node as SuperExpressionImpl,
+ contextType: contextType);
}
@override
@@ -2339,10 +2299,10 @@
void visitSwitchCase(SwitchCase node) {
checkUnreachableNode(node);
- InferenceContext.setType(
- node.expression, _enclosingSwitchStatementExpressionType);
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.labels.accept(this);
+ analyzeExpression(node.expression, _enclosingSwitchStatementExpressionType);
+ node.statements.accept(this);
var flow = flowAnalysis.flow;
if (flow != null && flow.isReachable && _isNonNullableByDefault) {
@@ -2400,24 +2360,28 @@
}
@override
- void visitSymbolLiteral(SymbolLiteral node) {
+ void visitSymbolLiteral(SymbolLiteral node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitSymbolLiteral(node as SymbolLiteralImpl);
+ typeAnalyzer.visitSymbolLiteral(node as SymbolLiteralImpl,
+ contextType: contextType);
}
@override
- void visitThisExpression(ThisExpression node) {
+ void visitThisExpression(ThisExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitThisExpression(node as ThisExpressionImpl);
+ typeAnalyzer.visitThisExpression(node as ThisExpressionImpl,
+ contextType: contextType);
+ _insertImplicitCallReference(node, contextType: contextType);
}
@override
- void visitThrowExpression(ThrowExpression node) {
+ void visitThrowExpression(ThrowExpression node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
- typeAnalyzer.visitThrowExpression(node as ThrowExpressionImpl);
+ typeAnalyzer.visitThrowExpression(node as ThrowExpressionImpl,
+ contextType: contextType);
flowAnalysis.flow?.handleExit();
}
@@ -2445,10 +2409,10 @@
flow.tryCatchStatement_bodyBegin();
}
body.accept(this);
+ nullSafetyDeadCodeVerifier.flowEnd(node.body);
+ nullSafetyDeadCodeVerifier.tryStatementEnter(node);
if (catchClauses.isNotEmpty) {
flow.tryCatchStatement_bodyEnd(body);
- nullSafetyDeadCodeVerifier.flowEnd(node.body);
- nullSafetyDeadCodeVerifier.tryStatementEnter(node);
var catchLength = catchClauses.length;
for (var i = 0; i < catchLength; ++i) {
@@ -2464,8 +2428,8 @@
}
flow.tryCatchStatement_end();
- nullSafetyDeadCodeVerifier.tryStatementExit(node);
}
+ nullSafetyDeadCodeVerifier.tryStatementExit(node);
if (finallyBlock != null) {
flow.tryFinallyStatement_finallyBegin(
@@ -2482,7 +2446,7 @@
}
@override
- void visitTypeLiteral(TypeLiteral node) {
+ void visitTypeLiteral(TypeLiteral node, {DartType? contextType}) {
checkUnreachableNode(node);
node.visitChildren(this);
}
@@ -2522,10 +2486,6 @@
@override
void visitVariableDeclarationList(VariableDeclarationList node) {
flowAnalysis.variableDeclarationList(node);
- for (VariableDeclaration decl in node.variables) {
- VariableElement variableElement = decl.declaredElement!;
- InferenceContext.setType(decl, variableElement.type);
- }
checkUnreachableNode(node);
node.visitChildren(this);
elementResolver.visitVariableDeclarationList(node);
@@ -2542,10 +2502,9 @@
checkUnreachableNode(node);
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
flowAnalysis.flow?.whileStatement_conditionBegin(node);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -2580,6 +2539,63 @@
return typeProvider.futureOrType(type);
}
+ /// If `expression` should be treated as `expression.call`, inserts an
+ /// [ImplicitCallReference] node which wraps [expression].
+ void _insertImplicitCallReference(ExpressionImpl expression,
+ {required DartType? contextType}) {
+ var parent = expression.parent;
+ if (_shouldSkipImplicitCallReferenceDueToForm(expression, parent)) {
+ return;
+ }
+ var staticType = expression.staticType;
+ if (staticType == null) {
+ return;
+ }
+ DartType? context;
+ if (parent is AssignmentExpression) {
+ context = parent.writeType;
+ } else {
+ context = contextType;
+ }
+ var callMethod = getImplicitCallMethod(staticType, context, expression);
+ if (callMethod == null || context == null) {
+ return;
+ }
+
+ // `expression` is to be treated as `expression.call`.
+ context = typeSystem.flatten(context);
+ var callMethodType = callMethod.type;
+ List<DartType> typeArgumentTypes;
+ if (isConstructorTearoffsEnabled &&
+ callMethodType.typeFormals.isNotEmpty &&
+ context is FunctionType) {
+ typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
+ context,
+ callMethodType,
+ errorReporter: errorReporter,
+ errorNode: expression,
+ // If the constructor-tearoffs feature is enabled, then so is
+ // generic-metadata.
+ genericMetadataIsEnabled: true,
+ )!;
+ if (typeArgumentTypes.isNotEmpty) {
+ callMethodType = callMethodType.instantiate(typeArgumentTypes);
+ }
+ } else {
+ typeArgumentTypes = [];
+ }
+
+ var callReference = astFactory.implicitCallReference(
+ expression: expression,
+ staticElement: callMethod,
+ typeArguments: null,
+ typeArgumentTypes: typeArgumentTypes,
+ );
+ NodeReplacer.replace(expression, callReference, parent: parent);
+
+ callReference.staticType = callMethodType;
+ }
+
/// Continues resolution of a [FunctionExpressionInvocation] that was created
/// from a rewritten [MethodInvocation]. The target function is already
/// resolved.
@@ -2588,9 +2604,9 @@
/// ordinary method invocation. So, we need to perform the same null shorting
/// as for method invocations.
void _resolveRewrittenFunctionExpressionInvocation(
- FunctionExpressionInvocation node,
- List<WhyNotPromotedGetter> whyNotPromotedList,
- ) {
+ FunctionExpressionInvocation node,
+ List<WhyNotPromotedGetter> whyNotPromotedList,
+ {required DartType? contextType}) {
var function = node.function;
if (function is PropertyAccess &&
@@ -2607,7 +2623,8 @@
}
_functionExpressionInvocationResolver.resolve(
- node as FunctionExpressionInvocationImpl, whyNotPromotedList);
+ node as FunctionExpressionInvocationImpl, whyNotPromotedList,
+ contextType: contextType);
nullShortingTermination(node);
}
@@ -2624,6 +2641,34 @@
}
}
+ bool _shouldSkipImplicitCallReferenceDueToForm(
+ Expression expression, AstNode? parent) {
+ while (parent is ParenthesizedExpression) {
+ expression = parent;
+ parent = expression.parent;
+ }
+ if (parent is CascadeExpression && parent.target == expression) {
+ // Do not perform an "implicit tear-off conversion" here. It should only
+ // be performed on [parent]. See
+ // https://github.com/dart-lang/language/issues/1873.
+ return true;
+ }
+ if (parent is ConditionalExpression &&
+ (parent.thenExpression == expression ||
+ parent.elseExpression == expression)) {
+ // Do not perform an "implicit tear-off conversion" on the branches of a
+ // conditional expression.
+ return true;
+ }
+ if (parent is BinaryExpression &&
+ parent.operator.type == TokenType.QUESTION_QUESTION) {
+ // Do not perform an "implicit tear-off conversion" on the branches of a
+ // `??` operator.
+ return true;
+ }
+ return false;
+ }
+
/// Given an [argumentList] and the [parameters] related to the element that
/// will be invoked using those arguments, compute the list of parameters that
/// correspond to the list of arguments.
@@ -2766,30 +2811,34 @@
migrationResolutionHooks);
@override
- void visitConditionalExpression(covariant ConditionalExpressionImpl node) {
+ void visitConditionalExpression(covariant ConditionalExpressionImpl node,
+ {DartType? contextType}) {
var conditionalKnownValue =
_migrationResolutionHooks.getConditionalKnownValue(node);
if (conditionalKnownValue == null) {
- super.visitConditionalExpression(node);
+ super.visitConditionalExpression(node, contextType: contextType);
return;
} else {
var subexpressionToKeep =
conditionalKnownValue ? node.thenExpression : node.elseExpression;
subexpressionToKeep.accept(this);
- inferenceHelper.recordStaticType(node, subexpressionToKeep.typeOrThrow);
+ inferenceHelper.recordStaticType(node, subexpressionToKeep.typeOrThrow,
+ contextType: contextType);
}
}
@override
- void visitIfElement(IfElement node) {
+ void visitIfElement(IfElement node, {CollectionLiteralContext? context}) {
var conditionalKnownValue =
_migrationResolutionHooks.getConditionalKnownValue(node);
if (conditionalKnownValue == null) {
- super.visitIfElement(node);
+ super.visitIfElement(node, context: context);
return;
} else {
- (conditionalKnownValue ? node.thenElement : node.elseElement)
- ?.accept(this);
+ var element = conditionalKnownValue ? node.thenElement : node.elseElement;
+ if (element != null) {
+ (element as CollectionElementImpl).resolveElement(this, context);
+ }
}
}
@@ -2975,7 +3024,7 @@
node.documentationComment?.accept(this);
node.name.accept(this);
node.typeParameters?.accept(this);
- node.superclass2.accept(this);
+ node.superclass.accept(this);
node.withClause.accept(this);
node.implementsClause?.accept(this);
}
@@ -3059,6 +3108,13 @@
ClassElement element = node.declaredElement!;
node.metadata.accept(this);
+ nameScope = TypeParameterScope(
+ nameScope,
+ element.typeParameters,
+ );
+ _setNodeNameScope(node, nameScope);
+ visitEnumDeclarationInScope(node);
+
nameScope = ClassScope(nameScope, element);
visitEnumMembersInScope(node);
} finally {
@@ -3066,6 +3122,13 @@
}
}
+ void visitEnumDeclarationInScope(EnumDeclaration node) {
+ node.name.accept(this);
+ node.typeParameters?.accept(this);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
+ }
+
void visitEnumMembersInScope(EnumDeclaration node) {
node.documentationComment?.accept(this);
node.constants.accept(this);
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index ed375ff..77865a9 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -31,7 +31,7 @@
@Deprecated('Use uri.isScheme("dart") instead')
@override
- bool get isInSystemLibrary => uri.scheme == 'dart';
+ bool get isInSystemLibrary => uri.isScheme('dart');
@override
String get shortName => pathos.basename(fullName);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 6bd3016..946b08f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
@@ -47,8 +46,10 @@
/// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
/// `String`.</blockquote>
- void visitAdjacentStrings(covariant AdjacentStringsImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
+ void visitAdjacentStrings(covariant AdjacentStringsImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.stringType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.32: <blockquote>... the cast expression <i>e as T</i> ...
@@ -57,31 +58,39 @@
/// scope.
///
/// The static type of a cast expression <i>e as T</i> is <i>T</i>.</blockquote>
- void visitAsExpression(covariant AsExpressionImpl node) {
- _inferenceHelper.recordStaticType(node, _getType(node.type));
+ void visitAsExpression(covariant AsExpressionImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _getType(node.type),
+ contextType: contextType);
}
/// The Dart Language Specification, 16.29 (Await Expressions):
///
/// The static type of [the expression "await e"] is flatten(T) where T is
/// the static type of e.
- void visitAwaitExpression(covariant AwaitExpressionImpl node) {
+ void visitAwaitExpression(covariant AwaitExpressionImpl node,
+ {required DartType? contextType}) {
var resultType = node.expression.typeOrThrow;
resultType = _typeSystem.flatten(resultType);
- _inferenceHelper.recordStaticType(node, resultType);
+ _inferenceHelper.recordStaticType(node, resultType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.4: <blockquote>The static type of a boolean literal is
/// bool.</blockquote>
- void visitBooleanLiteral(covariant BooleanLiteralImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+ void visitBooleanLiteral(covariant BooleanLiteralImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.boolType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.15.2: <blockquote>A cascaded method invocation expression
/// of the form <i>e..suffix</i> is equivalent to the expression <i>(t) {t.suffix; return
/// t;}(e)</i>.</blockquote>
- void visitCascadeExpression(covariant CascadeExpressionImpl node) {
- _inferenceHelper.recordStaticType(node, node.target.typeOrThrow);
+ void visitCascadeExpression(covariant CascadeExpressionImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, node.target.typeOrThrow,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.19: <blockquote> ... a conditional expression <i>c</i> of
@@ -91,14 +100,18 @@
///
/// The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
/// and the static type of <i>e<sub>3</sub></i>.</blockquote>
- void visitConditionalExpression(covariant ConditionalExpressionImpl node) {
- _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression);
+ void visitConditionalExpression(covariant ConditionalExpressionImpl node,
+ {required DartType? contextType}) {
+ _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.3: <blockquote>The static type of a literal double is
/// double.</blockquote>
- void visitDoubleLiteral(covariant DoubleLiteralImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.doubleType);
+ void visitDoubleLiteral(covariant DoubleLiteralImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.doubleType,
+ contextType: contextType);
}
void visitExtensionOverride(ExtensionOverride node) {
@@ -141,20 +154,6 @@
node.staticType = _dynamicType;
}
- /// The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
- /// either the form <i>new T.id(a<sub>1</sub>, …, a<sub>n</sub>)</i> or the form <i>new
- /// T(a<sub>1</sub>, …, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
- ///
- /// The Dart Language Specification, 12.11.2: <blockquote>The static type of a constant object
- /// expression of either the form <i>const T.id(a<sub>1</sub>, …, a<sub>n</sub>)</i> or the
- /// form <i>const T(a<sub>1</sub>, …, a<sub>n</sub>)</i> is <i>T</i>. </blockquote>
- void visitInstanceCreationExpression(
- covariant InstanceCreationExpressionImpl node) {
- _inferInstanceCreationExpression(node);
- _inferenceHelper.recordStaticType(
- node, node.constructorName.type2.typeOrThrow);
- }
-
/// <blockquote>
/// An integer literal has static type \code{int}, unless the surrounding
/// static context type is a type which \code{int} is not assignable to, and
@@ -170,16 +169,16 @@
/// type of $e$ is the same as the static type of an integer literal with the
/// same contexttype
/// </blockquote>
- void visitIntegerLiteral(IntegerLiteral node) {
- // Check the parent context for negated integer literals.
- var context = InferenceContext.getContext(
- (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node);
- if (context == null ||
- _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
- !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
- _inferenceHelper.recordStaticType(node, _typeProvider.intType);
+ void visitIntegerLiteral(IntegerLiteralImpl node,
+ {required DartType? contextType}) {
+ if (contextType == null ||
+ _typeSystem.isAssignableTo(_typeProvider.intType, contextType) ||
+ !_typeSystem.isAssignableTo(_typeProvider.doubleType, contextType)) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.intType,
+ contextType: contextType);
} else {
- _inferenceHelper.recordStaticType(node, _typeProvider.doubleType);
+ _inferenceHelper.recordStaticType(node, _typeProvider.doubleType,
+ contextType: contextType);
}
}
@@ -187,106 +186,133 @@
/// denote a type available in the current lexical scope.
///
/// The static type of an is-expression is `bool`.</blockquote>
- void visitIsExpression(covariant IsExpressionImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+ void visitIsExpression(covariant IsExpressionImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.boolType,
+ contextType: contextType);
}
void visitMethodInvocation(MethodInvocation node) {
throw StateError('Should not be invoked');
}
- void visitNamedExpression(covariant NamedExpressionImpl node) {
+ void visitNamedExpression(covariant NamedExpressionImpl node,
+ {required DartType? contextType}) {
Expression expression = node.expression;
- _inferenceHelper.recordStaticType(node, expression.typeOrThrow);
+ _inferenceHelper.recordStaticType(node, expression.typeOrThrow,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.2: <blockquote>The static type of `null` is bottom.
/// </blockquote>
- void visitNullLiteral(covariant NullLiteralImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.nullType);
+ void visitNullLiteral(covariant NullLiteralImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.nullType,
+ contextType: contextType);
}
- void visitParenthesizedExpression(
- covariant ParenthesizedExpressionImpl node) {
+ void visitParenthesizedExpression(covariant ParenthesizedExpressionImpl node,
+ {required DartType? contextType}) {
Expression expression = node.expression;
- _inferenceHelper.recordStaticType(node, expression.typeOrThrow);
+ _inferenceHelper.recordStaticType(node, expression.typeOrThrow,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.9: <blockquote>The static type of a rethrow expression is
/// bottom.</blockquote>
- void visitRethrowExpression(covariant RethrowExpressionImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.bottomType);
+ void visitRethrowExpression(covariant RethrowExpressionImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.bottomType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
/// `String`.</blockquote>
- void visitSimpleStringLiteral(covariant SimpleStringLiteralImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
+ void visitSimpleStringLiteral(covariant SimpleStringLiteralImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.stringType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
/// `String`.</blockquote>
- void visitStringInterpolation(covariant StringInterpolationImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
+ void visitStringInterpolation(covariant StringInterpolationImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.stringType,
+ contextType: contextType);
}
- void visitSuperExpression(covariant SuperExpressionImpl node) {
+ void visitSuperExpression(covariant SuperExpressionImpl node,
+ {required DartType? contextType}) {
var thisType = _resolver.thisType;
_resolver.flowAnalysis.flow?.thisOrSuper(node, thisType ?? _dynamicType);
if (thisType == null ||
node.thisOrAncestorOfType<ExtensionDeclaration>() != null) {
// TODO(brianwilkerson) Report this error if it hasn't already been
// reported.
- _inferenceHelper.recordStaticType(node, _dynamicType);
+ _inferenceHelper.recordStaticType(node, _dynamicType,
+ contextType: contextType);
} else {
- _inferenceHelper.recordStaticType(node, thisType);
+ _inferenceHelper.recordStaticType(node, thisType,
+ contextType: contextType);
}
}
- void visitSymbolLiteral(covariant SymbolLiteralImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.symbolType);
+ void visitSymbolLiteral(covariant SymbolLiteralImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.symbolType,
+ contextType: contextType);
}
/// The Dart Language Specification, 12.10: <blockquote>The static type of `this` is the
/// interface of the immediately enclosing class.</blockquote>
- void visitThisExpression(covariant ThisExpressionImpl node) {
+ void visitThisExpression(covariant ThisExpressionImpl node,
+ {required DartType? contextType}) {
var thisType = _resolver.thisType;
_resolver.flowAnalysis.flow?.thisOrSuper(node, thisType ?? _dynamicType);
if (thisType == null) {
// TODO(brianwilkerson) Report this error if it hasn't already been
// reported.
- _inferenceHelper.recordStaticType(node, _dynamicType);
+ _inferenceHelper.recordStaticType(node, _dynamicType,
+ contextType: contextType);
} else {
- _inferenceHelper.recordStaticType(node, thisType);
+ _inferenceHelper.recordStaticType(node, thisType,
+ contextType: contextType);
}
}
/// The Dart Language Specification, 12.8: <blockquote>The static type of a throw expression is
/// bottom.</blockquote>
- void visitThrowExpression(covariant ThrowExpressionImpl node) {
- _inferenceHelper.recordStaticType(node, _typeProvider.bottomType);
+ void visitThrowExpression(covariant ThrowExpressionImpl node,
+ {required DartType? contextType}) {
+ _inferenceHelper.recordStaticType(node, _typeProvider.bottomType,
+ contextType: contextType);
}
/// Set the static type of [node] to be the least upper bound of the static
/// types of subexpressions [expr1] and [expr2].
void _analyzeLeastUpperBound(
- ExpressionImpl node, Expression expr1, Expression expr2) {
+ ExpressionImpl node, Expression expr1, Expression expr2,
+ {required DartType? contextType}) {
var staticType1 = expr1.typeOrThrow;
var staticType2 = expr2.typeOrThrow;
- _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
+ _analyzeLeastUpperBoundTypes(node, staticType1, staticType2,
+ contextType: contextType);
}
/// Set the static type of [node] to be the least upper bound of the static
/// types [staticType1] and [staticType2].
void _analyzeLeastUpperBoundTypes(
- ExpressionImpl node, DartType staticType1, DartType staticType2) {
+ ExpressionImpl node, DartType staticType1, DartType staticType2,
+ {required DartType? contextType}) {
DartType staticType =
_typeSystem.getLeastUpperBound(staticType1, staticType2);
staticType = _resolver.toLegacyTypeIfOptOut(staticType);
- _inferenceHelper.recordStaticType(node, staticType);
+ _inferenceHelper.recordStaticType(node, staticType,
+ contextType: contextType);
}
/// Return the type represented by the given type [annotation].
@@ -299,55 +325,4 @@
}
return type;
}
-
- /// Given an instance creation of a possibly generic type, infer the type
- /// arguments using the current context type as well as the argument types.
- void _inferInstanceCreationExpression(InstanceCreationExpressionImpl node) {
- // TODO(leafp): Currently, we may re-infer types here, since we
- // sometimes resolve multiple times. We should really check that we
- // have not already inferred something. However, the obvious ways to
- // check this don't work, since we may have been instantiated
- // to bounds in an earlier phase, and we *do* want to do inference
- // in that case.
-
- // Get back to the uninstantiated generic constructor.
- // TODO(jmesserly): should we store this earlier in resolution?
- // Or look it up, instead of jumping backwards through the Member?
- var constructorName = node.constructorName;
- var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
- constructorName: constructorName,
- definingLibrary: _resolver.definingLibrary,
- );
-
- // If the constructor is not generic, we are done.
- if (elementToInfer == null) {
- return;
- }
-
- var typeName = constructorName.type2;
- var typeArguments = typeName.typeArguments;
-
- var constructorType = elementToInfer.asType;
- var arguments = node.argumentList;
- var inferred = _resolver.inferenceHelper.inferGenericInvoke(
- node, constructorType, typeArguments, arguments, constructorName,
- isConst: node.isConst);
-
- if (inferred != null) {
- // Fix up the parameter elements based on inferred method.
- arguments.correspondingStaticParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- argumentList: arguments,
- parameters: inferred.parameters,
- );
- typeName.type = inferred.returnType;
- // Update the static element as well. This is used in some cases, such as
- // computing constant values. It is stored in two places.
- var constructorElement = ConstructorMember.from(
- elementToInfer.element,
- inferred.returnType as InterfaceType,
- );
- constructorName.staticElement = constructorElement;
- }
- }
}
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 9fb88ca..34986e6 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -241,7 +242,8 @@
WithClause? withClause,
ImplementsClause? implementsClause,
{List<ClassMember> members = const [],
- bool isMacro = false}) =>
+ bool isMacro = false,
+ bool isAugmentation = false}) =>
astFactory.classDeclaration(
null,
null,
@@ -249,6 +251,7 @@
? null
: TokenFactory.tokenFromKeyword(abstractKeyword),
isMacro ? TokenFactory.tokenFromString('macro') : null,
+ isAugmentation ? TokenFactory.tokenFromString('augment') : null,
TokenFactory.tokenFromKeyword(Keyword.CLASS),
identifier3(name),
typeParameters,
@@ -266,7 +269,8 @@
NamedType superclass,
WithClause withClause,
ImplementsClause? implementsClause,
- {bool isMacro = false}) =>
+ {bool isMacro = false,
+ bool isAugmentation = false}) =>
astFactory.classTypeAlias(
null,
null,
@@ -278,6 +282,7 @@
? null
: TokenFactory.tokenFromKeyword(abstractKeyword),
isMacro ? TokenFactory.tokenFromString('macro') : null,
+ isAugmentation ? TokenFactory.tokenFromString('augment') : null,
superclass,
withClause,
implementsClause,
@@ -319,7 +324,8 @@
directives: directives,
declarations: declarations,
endToken: TokenFactory.tokenFromType(TokenType.EOF),
- featureSet: FeatureSet.latestLanguageVersion());
+ featureSet: FeatureSet.latestLanguageVersion(),
+ lineInfo: LineInfo.fromContent(''));
static CompilationUnitImpl compilationUnit9(
{String? scriptTag,
@@ -333,7 +339,8 @@
directives: directives,
declarations: declarations,
endToken: TokenFactory.tokenFromType(TokenType.EOF),
- featureSet: featureSet);
+ featureSet: featureSet,
+ lineInfo: LineInfo.fromContent(''));
static ConditionalExpressionImpl conditionalExpression(Expression condition,
Expression thenExpression, Expression elseExpression) =>
@@ -639,6 +646,7 @@
null,
null,
null,
+ null,
type,
keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
identifier3(name),
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
deleted file mode 100644
index c457420..0000000
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated("Use package:analyzer/src/dart/element/type_system.dart instead")
-library type_system_generated;
-
-export 'package:analyzer/src/dart/element/type_system.dart';
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
index 4b37ce5..d2f6b13 100644
--- a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -77,7 +77,7 @@
/// Initialize a newly created instance of this class to represent the ignore
/// comments in the given compilation [unit].
IgnoreInfo.forDart(CompilationUnit unit, String content) {
- var lineInfo = unit.lineInfo!;
+ var lineInfo = unit.lineInfo;
for (var comment in unit.ignoreComments) {
var lexeme = comment.lexeme;
if (lexeme.contains('ignore:')) {
diff --git a/pkg/analyzer/lib/src/manifest/manifest_warning_code.g.dart b/pkg/analyzer/lib/src/manifest/manifest_warning_code.g.dart
index 8ac1bdd..3e8424e 100644
--- a/pkg/analyzer/lib/src/manifest/manifest_warning_code.g.dart
+++ b/pkg/analyzer/lib/src/manifest/manifest_warning_code.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.g.dart b/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.g.dart
index e1565ec..cc54c3a 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.g.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.g.dart
@@ -5,7 +5,7 @@
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
-// 'dart pkg/analyzer/tool/messages/generate.dart' to update.
+// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
import "package:analyzer/error/error.dart";
@@ -514,7 +514,7 @@
// name: local_package
// ```
//
- // If the path is wrong, then replace it with a the correct path.
+ // If the path is wrong, then replace it with the correct path.
static const PubspecWarningCode PATH_PUBSPEC_DOES_NOT_EXIST =
PubspecWarningCode(
'PATH_PUBSPEC_DOES_NOT_EXIST',
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index b5a3097..e39cd99 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -1317,7 +1317,7 @@
}
void _buildFileDeclarations(CompilationUnit unit) {
- lineInfo = unit.lineInfo!;
+ lineInfo = unit.lineInfo;
lineStarts = lineInfo.lineStarts;
isLibrary = true;
diff --git a/pkg/analyzer/lib/src/source/package_map_resolver.dart b/pkg/analyzer/lib/src/source/package_map_resolver.dart
index 9b96f99..c1d3bf0 100644
--- a/pkg/analyzer/lib/src/source/package_map_resolver.dart
+++ b/pkg/analyzer/lib/src/source/package_map_resolver.dart
@@ -79,6 +79,6 @@
/// Returns `true` if [uri] is a `package` URI.
static bool isPackageUri(Uri uri) {
- return uri.scheme == PACKAGE_SCHEME;
+ return uri.isScheme(PACKAGE_SCHEME);
}
}
diff --git a/pkg/analyzer/lib/src/source/source_resource.dart b/pkg/analyzer/lib/src/source/source_resource.dart
index 9334b31..3e4adf7 100644
--- a/pkg/analyzer/lib/src/source/source_resource.dart
+++ b/pkg/analyzer/lib/src/source/source_resource.dart
@@ -80,7 +80,7 @@
@Deprecated('Use uri.isScheme("dart") instead')
@override
- bool get isInSystemLibrary => uri.scheme == DartUriResolver.DART_SCHEME;
+ bool get isInSystemLibrary => uri.isScheme(DartUriResolver.DART_SCHEME);
@Deprecated('Not used anymore')
@override
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 44e5dc8..67e3358 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -68,6 +68,12 @@
/// Right: location.
IS_INVOKED_BY,
+ /// Left: an unnamed constructor.
+ /// Is invoked by an enum constant, without arguments, which is special
+ /// because when the name given, an empty argument list must be added.
+ /// Right: location.
+ IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
+
/// Left: any element.
/// Is referenced (and not invoked, read/written) at.
/// Right: location.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index a17feaf..adb8e7d 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -496,6 +496,12 @@
/// Right: location.
IS_INVOKED_BY,
+ /// Left: an unnamed constructor.
+ /// Is invoked by an enum constant, without arguments, which is special
+ /// because when the name given, an empty argument list must be added.
+ /// Right: location.
+ IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
+
/// Left: any element.
/// Is referenced (and not invoked, read/written) at.
/// Right: location.
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index a332f28..f9c96037 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -123,11 +123,14 @@
/// Create a [SummaryDataStore] and populate it with the summaries in
/// [summaryPaths].
+ @Deprecated('Use tmp() and addBundle() instead')
SummaryDataStore(Iterable<String> summaryPaths,
{ResourceProvider? resourceProvider}) {
summaryPaths.forEach((String path) => _fillMaps(path, resourceProvider));
}
+ SummaryDataStore.tmp();
+
/// Add the given [bundle] loaded from the file with the given [path].
void addBundle(String? path, PackageBundleReader bundle) {
bundles.add(bundle);
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index bb34ac0..3713497 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -17,7 +17,7 @@
late final InSummaryUriResolver _uriResolver;
SummaryBasedDartSdk.forBundle(this._bundle) {
- var dataStore = SummaryDataStore([]);
+ var dataStore = SummaryDataStore.tmp();
// TODO(scheglov) We need a solution to avoid these paths at all.
dataStore.addBundle('', bundle);
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 114c5ec..df1bb2d 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -207,7 +207,7 @@
atSign: Tokens.at(),
name: name,
typeArguments: typeArguments,
- period: Tokens.period(),
+ period: constructorName != null ? Tokens.period() : null,
constructorName: constructorName,
arguments: arguments,
);
@@ -240,7 +240,7 @@
Tokens.assert_(),
Tokens.openParenthesis(),
condition,
- Tokens.comma(),
+ message != null ? Tokens.comma() : null,
message,
Tokens.closeParenthesis(),
);
@@ -855,6 +855,7 @@
var node = astFactory.mixinDeclaration(
null,
metadata,
+ null,
Tokens.mixin_(),
name,
typeParameters,
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index e03af22..d9a70fa 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -166,7 +166,7 @@
// We need to inform the applier about the right shape of the AST.
// _sink.writeByte(node.name != null ? 1 : 0);
- _writeNode(node.type2);
+ _writeNode(node.type);
_writeOptionalNode(node.name);
_sink.writeElement(node.staticElement);
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index ead4620..e3976e43 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -93,14 +93,11 @@
node.accept(_resolutionVisitor);
// Node may have been rewritten so get it again.
node = getNode();
- if (contextType != null) {
- InferenceContext.setType(node, contextType);
- }
node.accept(_scopeResolverVisitor);
}
_prepareEnclosingDeclarations();
_flowAnalysis.topLevelDeclaration_enter(node.parent!, null);
- node.accept(_resolverVisitor);
+ _resolverVisitor.analyzeExpression(node, contextType);
_flowAnalysis.topLevelDeclaration_exit();
}
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index b30141a..7f45994 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -142,7 +142,7 @@
}
@override
- void visitClassDeclaration(ClassDeclaration node) {
+ void visitClassDeclaration(covariant ClassDeclarationImpl node) {
_compilationUnitMember(node);
_token(node.abstractKeyword);
_token(node.macroKeyword);
@@ -159,7 +159,7 @@
}
@override
- void visitClassTypeAlias(ClassTypeAlias node) {
+ void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
_compilationUnitMember(node);
_token(node.abstractKeyword);
_token(node.macroKeyword);
@@ -167,7 +167,7 @@
node.name.accept(this);
node.typeParameters?.accept(this);
_token(node.equals);
- node.superclass2.accept(this);
+ node.superclass.accept(this);
node.withClause.accept(this);
node.implementsClause?.accept(this);
_token(node.semicolon);
@@ -231,7 +231,7 @@
@override
void visitConstructorName(ConstructorName node) {
- node.type2.accept(this);
+ node.type.accept(this);
_token(node.period);
node.name?.accept(this);
}
@@ -242,6 +242,12 @@
}
@override
+ void visitConstructorSelector(ConstructorSelector node) {
+ _token(node.period);
+ node.name.accept(this);
+ }
+
+ @override
void visitContinueStatement(ContinueStatement node) {
_token(node.continueKeyword);
node.label?.accept(this);
@@ -296,9 +302,17 @@
}
@override
+ void visitEnumConstantArguments(EnumConstantArguments node) {
+ node.typeArguments?.accept(this);
+ node.constructorSelector?.accept(this);
+ node.argumentList.accept(this);
+ }
+
+ @override
void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
_declaration(node);
node.name.accept(this);
+ node.arguments?.accept(this);
}
@override
@@ -306,8 +320,13 @@
_compilationUnitMember(node);
_token(node.enumKeyword);
node.name.accept(this);
+ node.typeParameters?.accept(this);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
_token(node.leftBracket);
- _nodeList(node.constants, node.rightBracket);
+ _nodeList(node.constants, node.semicolon ?? node.rightBracket);
+ _token(node.semicolon);
+ node.members.accept(this);
_token(node.rightBracket);
}
@@ -338,7 +357,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
_token(node.extendsKeyword);
- node.superclass2.accept(this);
+ node.superclass.accept(this);
}
@override
@@ -572,7 +591,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
_token(node.implementsKeyword);
- _nodeList(node.interfaces2, node.endToken.next);
+ _nodeList(node.interfaces, node.endToken.next);
}
@override
@@ -740,7 +759,7 @@
@override
void visitOnClause(OnClause node) {
_token(node.onKeyword);
- _nodeList(node.superclassConstraints2, node.endToken.next);
+ _nodeList(node.superclassConstraints, node.endToken.next);
}
@override
@@ -877,6 +896,18 @@
}
@override
+ void visitSuperFormalParameter(SuperFormalParameter node) {
+ _normalFormalParameter(node);
+ _token(node.keyword);
+ node.type?.accept(this);
+ _token(node.superKeyword);
+ _token(node.period);
+ node.identifier.accept(this);
+ node.typeParameters?.accept(this);
+ node.parameters?.accept(this);
+ }
+
+ @override
void visitSwitchCase(SwitchCase node) {
_nodeList(node.labels);
_token(node.keyword);
@@ -1005,7 +1036,7 @@
@override
void visitWithClause(WithClause node) {
_token(node.withKeyword);
- _nodeList(node.mixinTypes2, node.endToken.next);
+ _nodeList(node.mixinTypes, node.endToken.next);
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 53915eb..6400c29 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -276,6 +276,9 @@
unitElement: element.enclosingElement,
);
_readTypeParameters(reader, element.typeParameters);
+ element.supertype = reader._readOptionalInterfaceType();
+ element.mixins = reader._readInterfaceTypeList();
+ element.interfaces = reader._readInterfaceTypeList();
applyConstantOffsets?.perform();
}
}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 489d45d..6cc91be 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -176,6 +176,10 @@
_resolutionSink._writeAnnotationList(element.metadata);
_writeTypeParameters(element.typeParameters, () {
+ _resolutionSink.writeType(element.supertype);
+ _resolutionSink._writeTypeList(element.mixins);
+ _resolutionSink._writeTypeList(element.interfaces);
+
_writeList(
element.fields.where((e) {
return !e.isSynthetic ||
diff --git a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
index 0449c8c..cafb22c 100644
--- a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
@@ -18,12 +18,16 @@
void resolve() {
for (var unitElement in _libraryElement.units) {
- var classElements = [...unitElement.classes, ...unitElement.mixins];
+ var classElements = [
+ ...unitElement.classes,
+ ...unitElement.enums,
+ ...unitElement.mixins,
+ ];
for (var classElement in classElements) {
for (var constructorElement in classElement.constructors) {
_constructor(
unitElement as CompilationUnitElementImpl,
- classElement as ClassElementImpl,
+ classElement as AbstractClassElementImpl,
constructorElement as ConstructorElementImpl,
);
}
@@ -33,7 +37,7 @@
void _constructor(
CompilationUnitElementImpl unitElement,
- ClassElementImpl classElement,
+ AbstractClassElementImpl classElement,
ConstructorElementImpl element,
) {
if (element.isSynthetic) return;
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 667c275..a8fdcde 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -150,7 +150,7 @@
}
});
- node.superclass2.accept(this);
+ node.superclass.accept(this);
node.withClause.accept(this);
node.implementsClause?.accept(this);
}
@@ -220,9 +220,6 @@
hasConstConstructor: true,
);
- var needsImplicitConstructor =
- !node.members.any((e) => e is ConstructorDeclaration);
-
// Build fields for all enum constants.
var constants = node.constants;
var valuesElements = <Expression>[];
@@ -231,6 +228,7 @@
var name = constant.name.name;
var field = ConstFieldElementImpl(name, constant.name.offset)
..hasImplicitType = true
+ ..hasInitializer = true
..isConst = true
..isEnumConstant = true
..isStatic = true
@@ -243,7 +241,7 @@
);
var constructorSelector = constant.arguments?.constructorSelector;
- var constructorName = constructorSelector?.name.name ?? '';
+ var constructorName = constructorSelector?.name.name;
var initializer = astFactory.instanceCreationExpression(
null,
@@ -254,10 +252,12 @@
),
typeArguments: constant.arguments?.typeArguments,
),
- Tokens.period(),
- astFactory.simpleIdentifier(
- StringToken(TokenType.STRING, constructorName, -1),
- ),
+ constructorName != null ? Tokens.period() : null,
+ constructorName != null
+ ? astFactory.simpleIdentifier(
+ StringToken(TokenType.STRING, constructorName, -1),
+ )
+ : null,
),
astFactory.argumentList(
Tokens.openParenthesis(),
@@ -339,22 +339,18 @@
holder.addNonSyntheticField(valuesField);
}
- // TODO(scheglov) implement
- // node.extendsClause?.accept(this);
- // node.withClause?.accept(this);
- // node.implementsClause?.accept(this);
-
- // Build the 'index' field.
- var indexField = ConstFieldElementImpl('index', -1)
- ..isFinal = true
- ..isSynthetic = true;
- holder.addNonSyntheticField(indexField);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
_withEnclosing(holder, () {
node.typeParameters?.accept(this);
_visitPropertyFirst<FieldDeclaration>(node.members);
});
+ var needsImplicitConstructor = !holder.constructors.any(
+ (e) => e.name.isEmpty || e.isGenerative,
+ );
+
if (needsImplicitConstructor) {
holder.addConstructor(
ConstructorElementImpl('', -1)
@@ -363,20 +359,11 @@
);
}
- MethodElementImpl? syntheticToStringMethod;
- if (holder.getMethod('toString').element == null) {
- syntheticToStringMethod = MethodElementImpl('toString', -1)
- ..isSynthetic = true;
- holder.addMethod(name, syntheticToStringMethod);
- }
-
_libraryBuilder.implicitEnumNodes.add(
ImplicitEnumNodes(
element: element,
- indexField: indexField,
valuesTypeNode: valuesTypeNode,
valuesField: valuesField,
- syntheticToStringMethod: syntheticToStringMethod,
),
);
@@ -386,7 +373,7 @@
element.methods = holder.methods;
element.typeParameters = holder.typeParameters;
- // TODO(scheglov) resolve field formals
+ _resolveConstructorFieldFormals(element);
}
@override
@@ -403,7 +390,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
- node.superclass2.accept(this);
+ node.superclass.accept(this);
}
@override
@@ -420,7 +407,7 @@
node.declaredElement = element;
_linker.elementNodes[element] = node;
- var refName = name ?? 'extension-${_nextUnnamedExtensionId++}';
+ var refName = name ?? '${_nextUnnamedExtensionId++}';
var reference = _enclosingContext.addExtension(refName, element);
if (name != null) {
@@ -565,6 +552,7 @@
if (node.isGetter) {
var element = PropertyAccessorElementImpl(name, nameOffset);
element.isGetter = true;
+ element.isStatic = true;
reference = _enclosingContext.addGetter(name, element);
executableElement = element;
@@ -573,6 +561,7 @@
} else if (node.isSetter) {
var element = PropertyAccessorElementImpl(name, nameOffset);
element.isSetter = true;
+ element.isStatic = true;
reference = _enclosingContext.addSetter(name, element);
executableElement = element;
@@ -580,6 +569,7 @@
_buildSyntheticVariable(name: name, accessorElement: element);
} else {
var element = FunctionElementImpl(name, nameOffset);
+ element.isStatic = true;
reference = _enclosingContext.addFunction(name, element);
executableElement = element;
}
@@ -754,7 +744,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
- node.interfaces2.accept(this);
+ node.interfaces.accept(this);
}
@override
@@ -814,6 +804,14 @@
element.isGetter = true;
element.isStatic = node.isStatic;
+ // `class Enum {}` in `dart:core` declares `int get index` as abstract.
+ // But the specification says that practically a different class
+ // implementing `Enum` is used as a superclass, so `index` should be
+ // considered to have non-abstract implementation.
+ if (_enclosingContext.isDartCoreEnum && name == 'index') {
+ element.isAbstract = false;
+ }
+
reference = _enclosingContext.addGetter(name, element);
executableElement = element;
@@ -902,7 +900,7 @@
@override
void visitOnClause(OnClause node) {
- node.superclassConstraints2.accept(this);
+ node.superclassConstraints.accept(this);
}
@override
@@ -1099,7 +1097,7 @@
@override
void visitWithClause(WithClause node) {
- node.mixinTypes2.accept(this);
+ node.mixinTypes.accept(this);
}
List<ElementAnnotation> _buildAnnotations(List<Annotation> nodeList) {
@@ -1117,9 +1115,6 @@
_withEnclosing(holder, () {
_visitPropertyFirst<FieldDeclaration>(node.members);
});
- element.accessors = holder.propertyAccessors;
- element.fields = holder.properties.whereType<FieldElement>().toList();
- element.methods = holder.methods;
if (holder.constructors.isEmpty) {
holder.addConstructor(
@@ -1127,18 +1122,12 @@
);
}
- var constructors = holder.constructors;
- element.constructors = constructors;
+ element.accessors = holder.propertyAccessors;
+ element.constructors = holder.constructors;
+ element.fields = holder.properties.whereType<FieldElement>().toList();
+ element.methods = holder.methods;
- // We have all fields and constructors.
- // Now we can resolve field formal parameters.
- for (var constructor in constructors) {
- for (var parameter in constructor.parameters) {
- if (parameter is FieldFormalParameterElementImpl) {
- parameter.field = element.getField(parameter.name);
- }
- }
- }
+ _resolveConstructorFieldFormals(element);
}
void _buildExecutableElementChildren({
@@ -1204,6 +1193,16 @@
node?.accept(this);
}
+ void _resolveConstructorFieldFormals(AbstractClassElementImpl element) {
+ for (var constructor in element.constructors) {
+ for (var parameter in constructor.parameters) {
+ if (parameter is FieldFormalParameterElementImpl) {
+ parameter.field = element.getField(parameter.name);
+ }
+ }
+ }
+ }
+
Uri? _selectAbsoluteUri(NamespaceDirective directive) {
var relativeUriStr = _selectRelativeUri(
directive.configurations,
@@ -1372,6 +1371,11 @@
this.hasConstConstructor = false,
});
+ bool get isDartCoreEnum {
+ final element = this.element;
+ return element is ClassElementImpl && element.isDartCoreEnum;
+ }
+
Reference addClass(String name, ClassElementImpl element) {
classes.add(element);
return _bindReference('@class', name, element);
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index ff4cdbc..201c671 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -119,6 +119,7 @@
static const int _isAsynchronous = 1 << 1;
static const int _isExternal = 1 << 2;
static const int _isGenerator = 1 << 3;
+ static const int _isStatic = 1 << 4;
static void read(SummaryDataReader reader, FunctionElementImpl element) {
var byte = reader.readByte();
@@ -126,6 +127,7 @@
element.isAsynchronous = (byte & _isAsynchronous) != 0;
element.isExternal = (byte & _isExternal) != 0;
element.isGenerator = (byte & _isGenerator) != 0;
+ element.isStatic = (byte & _isStatic) != 0;
}
static void write(BufferedSink sink, FunctionElementImpl element) {
@@ -134,6 +136,7 @@
result |= element.isAsynchronous ? _isAsynchronous : 0;
result |= element.isExternal ? _isExternal : 0;
result |= element.isGenerator ? _isGenerator : 0;
+ result |= element.isStatic ? _isStatic : 0;
sink.writeByte(result);
}
}
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 1d68050..e2bf8ca 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -1051,7 +1051,7 @@
sink.writeUInt30(unit.offset);
sink.writeUInt30(unit.length);
- sink.writeUint30List(unit.lineInfo?.lineStarts ?? [0]);
+ sink.writeUint30List(unit.lineInfo.lineStarts);
_writeLibraryName(unit);
@@ -1740,7 +1740,7 @@
void _applyToEnumConstantInitializer(ConstFieldElementImpl element) {
var initializer = element.constantInitializer;
if (initializer is InstanceCreationExpression) {
- initializer.constructorName.type2.typeArguments?.accept(this);
+ initializer.constructorName.type.typeArguments?.accept(this);
for (var argument in initializer.argumentList.arguments) {
argument.accept(this);
}
@@ -1754,6 +1754,7 @@
@override
void visitAnnotation(Annotation node) {
_tokenOrNull(node.atSign);
+ _tokenOrNull(node.period);
super.visitAnnotation(node);
}
@@ -1774,6 +1775,7 @@
void visitAssertInitializer(AssertInitializer node) {
_tokenOrNull(node.assertKeyword);
_tokenOrNull(node.leftParenthesis);
+ _tokenOrNull(node.comma);
_tokenOrNull(node.rightParenthesis);
super.visitAssertInitializer(node);
}
@@ -1811,7 +1813,7 @@
@override
void visitConstructorName(ConstructorName node) {
- node.type2.accept(this);
+ node.type.accept(this);
_tokenOrNull(node.period);
node.name?.accept(this);
}
@@ -1824,6 +1826,8 @@
@override
void visitFormalParameterList(FormalParameterList node) {
_tokenOrNull(node.leftParenthesis);
+ _tokenOrNull(node.leftDelimiter);
+ _tokenOrNull(node.rightDelimiter);
_tokenOrNull(node.rightParenthesis);
super.visitFormalParameterList(node);
}
@@ -1835,6 +1839,15 @@
}
@override
+ void visitIfElement(IfElement node) {
+ _tokenOrNull(node.ifKeyword);
+ _tokenOrNull(node.leftParenthesis);
+ _tokenOrNull(node.rightParenthesis);
+ _tokenOrNull(node.elseKeyword);
+ super.visitIfElement(node);
+ }
+
+ @override
void visitIndexExpression(IndexExpression node) {
_tokenOrNull(node.leftBracket);
_tokenOrNull(node.rightBracket);
@@ -1872,6 +1885,12 @@
}
@override
+ void visitLabel(Label node) {
+ _tokenOrNull(node.colon);
+ super.visitLabel(node);
+ }
+
+ @override
void visitListLiteral(ListLiteral node) {
_tokenOrNull(node.constKeyword);
_tokenOrNull(node.leftBracket);
@@ -1880,6 +1899,12 @@
}
@override
+ void visitMapLiteralEntry(MapLiteralEntry node) {
+ _tokenOrNull(node.separator);
+ super.visitMapLiteralEntry(node);
+ }
+
+ @override
void visitMethodInvocation(MethodInvocation node) {
node.target?.accept(this);
_tokenOrNull(node.operator);
@@ -1889,6 +1914,12 @@
}
@override
+ void visitNamedType(NamedType node) {
+ _tokenOrNull(node.question);
+ super.visitNamedType(node);
+ }
+
+ @override
void visitNullLiteral(NullLiteral node) {
_tokenOrNull(node.literal);
}
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index aa57e1e..36f7c25 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -22,17 +22,13 @@
class ImplicitEnumNodes {
final EnumElementImpl element;
- final FieldElementImpl indexField;
final ast.NamedTypeImpl valuesTypeNode;
final ConstFieldElementImpl valuesField;
- final MethodElementImpl? syntheticToStringMethod;
ImplicitEnumNodes({
required this.element,
- required this.indexField,
required this.valuesTypeNode,
required this.valuesField,
- required this.syntheticToStringMethod,
});
}
@@ -134,7 +130,8 @@
void buildEnumChildren() {
var typeProvider = element.typeProvider;
for (var enum_ in implicitEnumNodes) {
- enum_.indexField.type = typeProvider.intType;
+ enum_.element.supertype =
+ typeProvider.enumType ?? typeProvider.objectType;
var valuesType = typeProvider.listType(
element.typeSystem.instantiateToBounds2(
classElement: enum_.element,
@@ -143,7 +140,6 @@
);
enum_.valuesTypeNode.type = valuesType;
enum_.valuesField.type = valuesType;
- enum_.syntheticToStringMethod?.returnType = typeProvider.stringType;
}
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 21183bd..01ddaa6 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -71,9 +71,10 @@
var reader = _libraryReaders[uriStr];
if (reader == null) {
+ var libraryUriList = rootReference.children.map((e) => e.name).toList();
throw ArgumentError(
'Missing library: $uriStr\n'
- 'Available libraries: ${_libraryReaders.keys.toList()}',
+ 'Available libraries: $libraryUriList',
);
}
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index 63659bb7..faac307 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -78,7 +78,15 @@
@override
void visitEnumDeclaration(EnumDeclaration node) {
node.metadata.accept(this);
- node.constants.accept(this);
+ node.typeParameters?.accept(this);
+
+ _scope = LinkingNodeContext.get(node).scope;
+ try {
+ node.constants.accept(this);
+ node.members.accept(this);
+ } finally {
+ _scope = _libraryScope;
+ }
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/named_type_builder.dart b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
index e6cd97a..9b4f698 100644
--- a/pkg/analyzer/lib/src/summary2/named_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
@@ -103,7 +103,7 @@
typeArguments: arguments,
nullabilitySuffix: nullabilitySuffix,
);
- type = typeSystem.toLegacyType(type) as InterfaceType;
+ type = typeSystem.toLegacyTypeIfOptOut(type) as InterfaceType;
_type = type;
} else if (element is TypeAliasElementImpl) {
var aliasedType = _getAliasedType(element);
@@ -114,7 +114,7 @@
typeArguments: arguments,
nullabilitySuffix: nullabilitySuffix,
);
- type = typeSystem.toLegacyType(type);
+ type = typeSystem.toLegacyTypeIfOptOut(type);
_type = type;
} else if (element is NeverElementImpl) {
if (typeSystem.isNonNullableByDefault) {
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index dd5b4cc..1cecbd4 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -80,7 +80,7 @@
LinkingNodeContext(node, scope);
node.typeParameters?.accept(this);
- node.superclass2.accept(this);
+ node.superclass.accept(this);
node.withClause.accept(this);
node.implementsClause?.accept(this);
nodesToBuildType.addDeclaration(node);
@@ -122,10 +122,8 @@
scope = TypeParameterScope(scope, element.typeParameters);
node.typeParameters?.accept(this);
- // TODO(scheglov) implement
- // node.extendsClause?.accept(this);
- // node.implementsClause?.accept(this);
- // node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
+ node.withClause?.accept(this);
scope = ClassScope(scope, element);
LinkingNodeContext(node, scope);
@@ -141,7 +139,7 @@
@override
void visitExtendsClause(ExtendsClause node) {
- node.superclass2.accept(this);
+ node.superclass.accept(this);
}
@override
@@ -289,7 +287,7 @@
@override
void visitImplementsClause(ImplementsClause node) {
- node.interfaces2.accept(this);
+ node.interfaces.accept(this);
}
@override
@@ -386,7 +384,7 @@
@override
void visitOnClause(OnClause node) {
- node.superclassConstraints2.accept(this);
+ node.superclassConstraints.accept(this);
}
@override
@@ -444,7 +442,7 @@
@override
void visitWithClause(WithClause node) {
- node.mixinTypes2.accept(this);
+ node.mixinTypes.accept(this);
}
NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 004c65b..993aa69 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -351,6 +351,7 @@
_unitElement = unit as CompilationUnitElementImpl;
unit.classes.forEach(_addClassConstructorFieldFormals);
unit.classes.forEach(_addClassElementFields);
+ unit.enums.forEach(_addClassConstructorFieldFormals);
unit.enums.forEach(_addClassElementFields);
unit.extensions.forEach(_addExtensionElementFields);
unit.mixins.forEach(_addClassElementFields);
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index 795d229..f69284f 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -122,7 +122,7 @@
var extendsClause = node.extendsClause;
if (extendsClause != null) {
- var type = extendsClause.superclass2.type;
+ var type = extendsClause.superclass.type;
if (type is InterfaceType && _isInterfaceTypeClass(type)) {
element.supertype = type;
} else {
@@ -135,18 +135,18 @@
}
element.mixins = _toInterfaceTypeList(
- node.withClause?.mixinTypes2,
+ node.withClause?.mixinTypes,
);
element.interfaces = _toInterfaceTypeList(
- node.implementsClause?.interfaces2,
+ node.implementsClause?.interfaces,
);
}
void _classTypeAlias(ClassTypeAlias node) {
var element = node.declaredElement as ClassElementImpl;
- var superType = node.superclass2.type;
+ var superType = node.superclass.type;
if (superType is InterfaceType && _isInterfaceTypeInterface(superType)) {
element.supertype = superType;
} else {
@@ -154,11 +154,11 @@
}
element.mixins = _toInterfaceTypeList(
- node.withClause.mixinTypes2,
+ node.withClause.mixinTypes,
);
element.interfaces = _toInterfaceTypeList(
- node.implementsClause?.interfaces2,
+ node.implementsClause?.interfaces,
);
}
@@ -223,7 +223,15 @@
}
void _enumDeclaration(EnumDeclaration node) {
- // TODO(scheglov) implement
+ var element = node.declaredElement as EnumElementImpl;
+
+ element.mixins = _toInterfaceTypeList(
+ node.withClause?.mixinTypes,
+ );
+
+ element.interfaces = _toInterfaceTypeList(
+ node.implementsClause?.interfaces,
+ );
}
void _extensionDeclaration(ExtensionDeclaration node) {
@@ -294,7 +302,7 @@
var element = node.declaredElement as MixinElementImpl;
var constraints = _toInterfaceTypeList(
- node.onClause?.superclassConstraints2,
+ node.onClause?.superclassConstraints,
);
if (constraints.isEmpty) {
constraints = [_objectType(element)];
@@ -302,7 +310,7 @@
element.superclassConstraints = constraints;
element.interfaces = _toInterfaceTypeList(
- node.implementsClause?.interfaces2,
+ node.implementsClause?.interfaces,
);
}
@@ -362,7 +370,7 @@
/// Performs mixins inference in a [ClassDeclaration].
class _MixinInference {
- final ClassElementImpl element;
+ final AbstractClassElementImpl element;
final TypeSystemImpl typeSystem;
final FeatureSet featureSet;
final InterfaceType classType;
@@ -387,7 +395,7 @@
void perform(WithClause? withClause) {
if (withClause == null) return;
- for (var mixinNode in withClause.mixinTypes2) {
+ for (var mixinNode in withClause.mixinTypes) {
var mixinType = _inferSingle(mixinNode as NamedTypeImpl);
interfacesMerger.addWithSupertypes(mixinType);
}
@@ -512,14 +520,15 @@
/// we are inferring the [element] now, i.e. there is a loop.
///
/// This is an error. So, we return the empty list, and break the loop.
- List<InterfaceType> _callbackWhenLoop(ClassElementImpl element) {
+ List<InterfaceType> _callbackWhenLoop(AbstractClassElementImpl element) {
element.mixinInferenceCallback = null;
return <InterfaceType>[];
}
/// This method is invoked when mixins are asked from the [element], and
/// we are not inferring the [element] now, i.e. there is no loop.
- List<InterfaceType>? _callbackWhenRecursion(ClassElementImpl element) {
+ List<InterfaceType>? _callbackWhenRecursion(
+ AbstractClassElementImpl element) {
var node = _linker.getLinkingNode(element);
if (node != null) {
_inferDeclaration(node);
@@ -528,7 +537,7 @@
return null;
}
- void _infer(ClassElementImpl element, WithClause? withClause) {
+ void _infer(AbstractClassElementImpl element, WithClause? withClause) {
if (withClause != null) {
element.mixinInferenceCallback = _callbackWhenLoop;
try {
@@ -537,7 +546,7 @@
} finally {
element.mixinInferenceCallback = null;
element.mixins = _toInterfaceTypeList(
- withClause.mixinTypes2,
+ withClause.mixinTypes,
);
}
}
@@ -550,6 +559,9 @@
} else if (node is ClassTypeAlias) {
var element = node.declaredElement as ClassElementImpl;
_infer(element, node.withClause);
+ } else if (node is EnumDeclaration) {
+ var element = node.declaredElement as EnumElementImpl;
+ _infer(element, node.withClause);
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 7159665..0c572a2 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
+import 'package:collection/src/iterable_extensions.dart';
/// Helper for finding elements declared in the resolved [unit].
class FindElement extends _FindElementBase {
@@ -406,147 +407,27 @@
}
FieldElement field(String name, {String? of}) {
- FieldElement? result;
-
- void findIn(List<FieldElement> fields) {
- for (var field in fields) {
- if (field.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = field;
- }
- }
- }
-
- for (var enum_ in unitElement.enums) {
- if (of != null && enum_.name != of) {
- continue;
- }
- findIn(enum_.fields);
- }
-
- for (var class_ in unitElement.classes) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.fields);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.fields);
- }
-
- for (var extension in unitElement.extensions) {
- if (of != null && extension.name != of) {
- continue;
- }
- findIn(extension.fields);
- }
-
- if (result != null) {
- return result!;
- }
- throw StateError('Not found: $name');
+ return _findInClassesLike(
+ className: of,
+ fromClass: (element) => element.getField(name),
+ fromExtension: (element) => element.getField(name),
+ );
}
PropertyAccessorElement getter(String name, {String? of}) {
- PropertyAccessorElement? result;
-
- void findIn(List<PropertyAccessorElement> accessors) {
- for (var accessor in accessors) {
- if (accessor.isGetter && accessor.displayName == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = accessor;
- }
- }
- }
-
- for (var enum_ in unitElement.enums) {
- if (of != null && enum_.name != of) {
- continue;
- }
- findIn(enum_.accessors);
- }
-
- for (var extension_ in unitElement.extensions) {
- if (of != null && extension_.name != of) {
- continue;
- }
- findIn(extension_.accessors);
- }
-
- for (var class_ in unitElement.classes) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.accessors);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.accessors);
- }
-
- if (result != null) {
- return result!;
- }
- throw StateError('Not found: $name');
+ return _findInClassesLike(
+ className: of,
+ fromClass: (element) => element.getGetter(name),
+ fromExtension: (element) => element.getGetter(name),
+ );
}
MethodElement method(String name, {String? of}) {
- MethodElement? result;
-
- void findIn(List<MethodElement> methods) {
- for (var method in methods) {
- if (method.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = method;
- }
- }
- }
-
- for (var class_ in unitElement.classes) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.methods);
- }
-
- for (var enum_ in unitElement.enums) {
- if (of != null && enum_.name != of) {
- continue;
- }
- findIn(enum_.methods);
- }
-
- for (var extension_ in unitElement.extensions) {
- if (of != null && extension_.name != of) {
- continue;
- }
- findIn(extension_.methods);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.methods);
- }
-
- if (result != null) {
- return result!;
- }
- throw StateError('Not found: $name');
+ return _findInClassesLike(
+ className: of,
+ fromClass: (element) => element.getMethod(name),
+ fromExtension: (element) => element.getMethod(name),
+ );
}
ClassElement mixin(String name) {
@@ -581,44 +462,11 @@
}
PropertyAccessorElement setter(String name, {String? of}) {
- PropertyAccessorElement? result;
-
- void findIn(List<PropertyAccessorElement> accessors) {
- for (var accessor in accessors) {
- if (accessor.isSetter && accessor.displayName == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = accessor;
- }
- }
- }
-
- for (var extension_ in unitElement.extensions) {
- if (of != null && extension_.name != of) {
- continue;
- }
- findIn(extension_.accessors);
- }
-
- for (var class_ in unitElement.classes) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.accessors);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.accessors);
- }
-
- if (result != null) {
- return result!;
- }
- throw StateError('Not found: $name');
+ return _findInClassesLike(
+ className: of,
+ fromClass: (element) => element.getSetter(name),
+ fromExtension: (element) => element.getSetter(name),
+ );
}
FunctionElement topFunction(String name) {
@@ -657,7 +505,43 @@
}
ConstructorElement unnamedConstructor(String name) {
- return class_(name).unnamedConstructor!;
+ return _findInClassesLike(
+ className: name,
+ fromClass: (e) => e.unnamedConstructor,
+ fromExtension: (_) => null,
+ );
+ }
+
+ T _findInClassesLike<T extends Element>({
+ required String? className,
+ required T? Function(ClassElement element) fromClass,
+ required T? Function(ExtensionElement element) fromExtension,
+ }) {
+ bool filter(Element element) {
+ return className == null || element.name == className;
+ }
+
+ var classes = [
+ ...unitElement.classes,
+ ...unitElement.enums,
+ ...unitElement.mixins,
+ ];
+
+ var results = [
+ ...classes.where(filter).map(fromClass),
+ ...unitElement.extensions.where(filter).map(fromExtension),
+ ].whereNotNull().toList();
+
+ var result = results.singleOrNull;
+ if (result != null) {
+ return result;
+ }
+
+ if (results.isEmpty) {
+ throw StateError('Not found');
+ } else {
+ throw StateError('Not unique');
+ }
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index b25d26f..d137ec9 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -127,6 +127,10 @@
return _node(search, (n) => n is ConstructorReference);
}
+ ConstructorSelector constructorSelector(String search) {
+ return _node(search, (n) => n is ConstructorSelector);
+ }
+
ContinueStatement continueStatement(String search) {
return _node(search, (n) => n is ContinueStatement);
}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index 9c4b72b..5c68765 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -51,25 +51,62 @@
libFolder.getChildAssumingFile('meta.dart').writeAsStringSync(r'''
library meta;
-const _AlwaysThrows alwaysThrows = const _AlwaysThrows();
-const _DoNotStore doNotStore = _DoNotStore();
-const _Factory factory = const _Factory();
-const Immutable immutable = const Immutable();
-const _Internal internal = const Internal();
-const _Literal literal = const _Literal();
-const _MustCallSuper mustCallSuper = const _MustCallSuper();
-const _NonVirtual nonVirtual = const _NonVirtual();
-const _OptionalTypeArgs optionalTypeArgs = const _OptionalTypeArgs();
-const _Protected protected = const _Protected();
-const Required required = const Required();
-const _Sealed sealed = const _Sealed();
-const UseResult useResult = UseResult();
-const _VisibleForOverriding visibleForOverriding = _VisibleForOverriding();
-const _VisibleForTesting visibleForTesting = const _VisibleForTesting();
+import 'meta_meta.dart';
-class _AlwaysThrows {
- const _AlwaysThrows();
+const _AlwaysThrows alwaysThrows = _AlwaysThrows();
+
+@Deprecated('Use the `covariant` modifier instead')
+const _Checked checked = _Checked();
+
+const _DoNotStore doNotStore = _DoNotStore();
+
+const _Experimental experimental = _Experimental();
+
+const _Factory factory = _Factory();
+
+const Immutable immutable = Immutable();
+
+const _Internal internal = _Internal();
+
+const _IsTest isTest = _IsTest();
+
+const _IsTestGroup isTestGroup = _IsTestGroup();
+
+const _Literal literal = _Literal();
+
+const _MustCallSuper mustCallSuper = _MustCallSuper();
+
+const _NonVirtual nonVirtual = _NonVirtual();
+
+const _OptionalTypeArgs optionalTypeArgs = _OptionalTypeArgs();
+
+const _Protected protected = _Protected();
+
+const Required required = Required();
+
+const _Sealed sealed = _Sealed();
+
+const UseResult useResult = UseResult();
+
+@Deprecated('No longer has meaning')
+const _Virtual virtual = _Virtual();
+
+const _VisibleForOverriding visibleForOverriding = _VisibleForOverriding();
+
+const _VisibleForTesting visibleForTesting = _VisibleForTesting();
+
+class Immutable {
+ final String reason;
+
+ const Immutable([this.reason = '']);
}
+
+class Required {
+ final String reason;
+
+ const Required([this.reason = '']);
+}
+
@Target({
TargetKind.field,
TargetKind.function,
@@ -77,50 +114,91 @@
TargetKind.method,
TargetKind.topLevelVariable,
})
+class UseResult {
+ final String reason;
+
+ final String? parameterDefined;
+
+ const UseResult([this.reason = '']) : parameterDefined = null;
+
+ const UseResult.unless({required this.parameterDefined, this.reason = ''});
+}
+
+class _AlwaysThrows {
+ const _AlwaysThrows();
+}
+
+class _Checked {
+ const _Checked();
+}
+
+@Target({
+ TargetKind.classType,
+ TargetKind.function,
+ TargetKind.getter,
+ TargetKind.library,
+ TargetKind.method,
+})
class _DoNotStore {
const _DoNotStore();
}
+
+class _Experimental {
+ const _Experimental();
+}
+
class _Factory {
const _Factory();
}
-class Immutable {
- final String reason;
- const Immutable([this.reason]);
-}
+
class _Internal {
- const Internal();
+ const _Internal();
}
+
+class _IsTest {
+ const _IsTest();
+}
+
+class _IsTestGroup {
+ const _IsTestGroup();
+}
+
class _Literal {
const _Literal();
}
+
class _MustCallSuper {
const _MustCallSuper();
}
+
class _NonVirtual {
const _NonVirtual();
}
+
+@Target({
+ TargetKind.classType,
+ TargetKind.extension,
+ TargetKind.function,
+ TargetKind.method,
+ TargetKind.mixinType,
+ TargetKind.typedefType,
+})
class _OptionalTypeArgs {
const _OptionalTypeArgs();
}
+
class _Protected {
const _Protected();
}
-class Required {
- final String reason;
- const Required([this.reason]);
-}
+
class _Sealed {
const _Sealed();
}
-class UseResult {
- final String? parameterDefined;
- final String reason;
- const UseResult([this.reason = '']);
- const UseResult.unless({required this.parameterDefined, this.reason = ''});
-}
+
class _VisibleForOverriding {
const _VisibleForOverriding();
}
+
class _VisibleForTesting {
const _VisibleForTesting();
}
@@ -128,10 +206,12 @@
libFolder.getChildAssumingFile('meta_meta.dart').writeAsStringSync(r'''
library meta_meta;
+@Target({TargetKind.classType})
class Target {
final Set<TargetKind> kinds;
const Target(this.kinds);
}
+
enum TargetKind {
classType,
enumType,
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 84784c3..d1cb139 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -624,6 +624,8 @@
class Type {}
+class TypeError extends Error {}
+
class UnsupportedError {
UnsupportedError(String message);
}
diff --git a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
index c082771..867272e 100644
--- a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
+++ b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
@@ -14,6 +14,11 @@
String convertPath(String path) => resourceProvider.convertPath(path);
+ void deleteAnalysisOptionsYamlFile(String directoryPath) {
+ var path = join(directoryPath, file_paths.analysisOptionsYaml);
+ deleteFile(path);
+ }
+
void deleteFile(String path) {
String convertedPath = convertPath(path);
resourceProvider.deleteFile(convertedPath);
@@ -24,6 +29,15 @@
resourceProvider.deleteFolder(convertedPath);
}
+ void deletePackageConfigJsonFile(String directoryPath) {
+ var path = join(
+ directoryPath,
+ file_paths.dotDartTool,
+ file_paths.packageConfigJson,
+ );
+ deleteFile(path);
+ }
+
File getFile(String path) {
String convertedPath = convertPath(path);
return resourceProvider.getFile(convertedPath);
diff --git a/pkg/analyzer/lib/src/util/sdk.dart b/pkg/analyzer/lib/src/util/sdk.dart
index d588cc3..6e73efb 100644
--- a/pkg/analyzer/lib/src/util/sdk.dart
+++ b/pkg/analyzer/lib/src/util/sdk.dart
@@ -6,27 +6,5 @@
import 'package:path/path.dart' as path;
-String getSdkPath([List<String>? args]) {
- // Look for --dart-sdk on the command line.
- if (args != null) {
- int index = args.indexOf('--dart-sdk');
-
- if (index != -1 && (index + 1 < args.length)) {
- return args[index + 1];
- }
-
- for (String arg in args) {
- if (arg.startsWith('--dart-sdk=')) {
- return arg.substring('--dart-sdk='.length);
- }
- }
- }
-
- // Look in env['DART_SDK']
- if (Platform.environment['DART_SDK'] != null) {
- return Platform.environment['DART_SDK']!;
- }
-
- // Use Platform.resolvedExecutable.
- return path.dirname(path.dirname(Platform.resolvedExecutable));
-}
+/// Return the path to the runtime Dart SDK.
+String getSdkPath() => path.dirname(path.dirname(Platform.resolvedExecutable));
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 5198c44..7350937 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -83,7 +83,7 @@
}
Source? _resolveAbsolute(Uri uri) {
- if (uri.scheme == 'file') {
+ if (uri.isScheme('file')) {
var path = fileUriToNormalizedPath(_context, uri);
var pathRelativeToRoot = _workspace._relativeToRoot(path);
if (pathRelativeToRoot == null) return null;
@@ -91,7 +91,7 @@
var file = _workspace.findFile(fullFilePath);
return file?.createSource(uri);
}
- if (uri.scheme != 'package') {
+ if (!uri.isScheme('package')) {
return null;
}
String uriPath = Uri.decodeComponent(uri.path);
@@ -692,13 +692,16 @@
.getFolder(root)
.getChildAssumingFile('BUILD')
.readAsStringSync();
- var hasNonNullableFlag = buildContent
+ var flattenedBuildContent = buildContent
.split('\n')
.map((e) => e.trim())
.where((e) => !e.startsWith('#'))
.map((e) => e.replaceAll(' ', ''))
- .join()
- .contains('dart_package(null_safety=True');
+ .join();
+ var hasNonNullableFlag = const {
+ 'dart_package(null_safety=True',
+ 'dart_package(sound_null_safety=True',
+ }.any(flattenedBuildContent.contains);
if (hasNonNullableFlag) {
// Enabled by default.
} else {
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index 4e06f04..c30333e 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -73,7 +73,7 @@
@override
Source? resolveAbsolute(Uri uri) {
- if (uri.scheme != 'package') {
+ if (!uri.isScheme('package')) {
return null;
}
diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart
index 34ab9c1..035744b 100644
--- a/pkg/analyzer/lib/src/workspace/workspace.dart
+++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -82,7 +82,7 @@
/// example, the case of a [InSummarySource]). In this case, use
/// [workspace]'s package URI resolver to fetch the file path.
String? filePathFromSource(Source source) {
- if (source.uri.scheme == 'package') {
+ if (source.uri.isScheme('package')) {
return workspace.packageUriResolver.resolveAbsolute(source.uri)?.fullName;
} else {
return source.fullName;
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index d791d4c..477c268 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -1551,6 +1551,9 @@
comment: |-
Parameters:
0: the name of the member
+ NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR:
+ problemMessage: Generative enum constructors must be 'const'.
+ correctionMessage: Try adding the keyword 'const'.
NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY:
sharedName: COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
problemMessage: "Constant values from a deferred library can't be used as keys in a 'const' map literal."
@@ -1632,6 +1635,9 @@
correctionMessage: "Try removing the keyword 'const' from the map literal or removing the keyword 'deferred' from the import."
hasPublishedDocs: true
comment: No parameters.
+ CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE:
+ problemMessage: "Concrete classes can't have 'Enum' as a superinterface."
+ correctionMessage: Try specifying a different interface, or remove it from the list.
CONCRETE_CLASS_WITH_ABSTRACT_MEMBER:
problemMessage: "'{0}' must have a method body because '{1}' isn't abstract."
correctionMessage: "Try making '{1}' abstract, or adding a body to '{0}'."
@@ -1849,6 +1855,14 @@
```dart
class C<T> {}
```
+ CONFLICTING_TYPE_VARIABLE_AND_ENUM:
+ sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
+ problemMessage: "'{0}' can't be used to name both a type variable and the enum in which the type variable is defined."
+ correctionMessage: Try renaming either the type variable or the enum.
+ hasPublishedDocs: true
+ comment: |-
+ Parameters:
+ 0: the name of the type variable
CONFLICTING_TYPE_VARIABLE_AND_EXTENSION:
sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
problemMessage: "'{0}' can't be used to name both a type variable and the extension in which the type variable is defined."
@@ -1908,6 +1922,14 @@
comment: |-
Parameters:
0: the name of the type variable
+ CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM:
+ sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+ problemMessage: "'{0}' can't be used to name both a type variable and a member in this enum."
+ correctionMessage: Try renaming either the type variable or the member.
+ hasPublishedDocs: true
+ comment: |-
+ Parameters:
+ 0: the name of the type variable
CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION:
sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
problemMessage: "'{0}' can't be used to name both a type variable and a member in this extension."
@@ -2758,7 +2780,32 @@
Parameters:
0: the name of the type
CONTINUE_LABEL_ON_SWITCH:
- problemMessage: A continue label resolves to switch, must be loop or switch member
+ problemMessage: A `continue` label resolves to a `switch` statement, but the label must be on a loop or a switch member.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when the label in a `continue`
+ statement resolves to a label on a `switch` statement.
+
+ #### Example
+
+ The following code produces this diagnostic because the label `l`, used to
+ label a `switch` statement, is used in the `continue` statement:
+
+ ```dart
+ void f(int i) {
+ l: switch (i) {
+ case 0:
+ continue [!l!];
+ }
+ }
+ ```
+
+ #### Common fixes
+
+ Find a different way to achieve the control flow you need; for example, by
+ introducing a loop that re-executes the `switch` statement.
COULD_NOT_INFER:
problemMessage: "Couldn't infer type parameter '{0}'.{1}"
comment: |-
@@ -3073,9 +3120,45 @@
}
```
DISALLOWED_TYPE_INSTANTIATION_EXPRESSION:
- problemMessage: Only a generic type, generic function, generic instance method, or generic constructor can be type instantiated.
- correctionMessage: Try instantiating the type(s) of a generic type, generic function, generic instance method, or generic constructor.
+ problemMessage: Only a generic type, generic function, generic instance method, or generic constructor can have type arguments.
+ correctionMessage: Try removing the type arguments, or instantiating the type(s) of a generic type, generic function, generic instance method, or generic constructor.
comment: No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when an expression with a value that
+ is anything other than one of the allowed kinds of values is followed by
+ type arguments. The allowed kinds of values are:
+ - generic types,
+ - generic constructors, and
+ - generic functions, including top-level functions, static and instance
+ members, and local functions.
+
+ #### Example
+
+ The following code produces this diagnostic because `i` is a top-level
+ variable, which isn't one of the allowed cases:
+
+ ```dart
+ int i = 1;
+
+ void f() {
+ print([!i!]<int>);
+ }
+ ```
+
+ #### Common fixes
+
+ If the referenced value is correct, then remove the type arguments:
+
+ ```dart
+ int i = 1;
+
+ void f() {
+ print(i);
+ }
+ ```
DUPLICATE_CONSTRUCTOR_NAME:
sharedName: DUPLICATE_CONSTRUCTOR
problemMessage: "The constructor with name '{0}' is already defined."
@@ -3332,6 +3415,60 @@
ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING:
problemMessage: "The name of the enum constant can't be the same as the enum's name."
correctionMessage: Try renaming the constant.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when an enum constant has the same
+ name as the enum in which it's declared.
+
+ #### Example
+
+ The following code produces this diagnostic because the enum constant `E`
+ has the same name as the enclosing enum `E`:
+
+ ```dart
+ enum E {
+ [!E!]
+ }
+ ```
+
+ #### Common fixes
+
+ If the name of the enum is correct, then rename the constant:
+
+ ```dart
+ enum E {
+ e
+ }
+ ```
+
+ If the name of the constant is correct, then rename the enum:
+
+ ```dart
+ enum F {
+ E
+ }
+ ```
+ ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR:
+ problemMessage: The invoked constructor isn't a const constructor.
+ correctionMessage: Try invoking a const generative constructor.
+ ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED:
+ problemMessage: The result of instantiating the enum to bounds is not well-bounded.
+ correctionMessage: Try using different bounds for type parameters.
+ ENUM_MIXIN_WITH_INSTANCE_VARIABLE:
+ problemMessage: Mixins applied to enums can't have instance variables.
+ correctionMessage: Try replacing the instance variables with getters.
+ ENUM_WITH_ABSTRACT_MEMBER:
+ problemMessage: "'{0}' must have a method body because '{1}' is an enum."
+ correctionMessage: "Try adding a body to '{0}'."
+ comment: |-
+ Parameters:
+ 0: the name of the abstract method
+ 1: the name of the enclosing enum
+ ENUM_WITH_NAME_VALUES:
+ problemMessage: The name 'values' is not a valid name for an enum.
+ correctionMessage: Try using a different name.
EQUAL_ELEMENTS_IN_CONST_SET:
problemMessage: "Two elements in a constant set literal can't be equal."
correctionMessage: Change or remove the duplicate element.
@@ -3975,14 +4112,61 @@
sharedName: EXTERNAL_WITH_INITIALIZER
problemMessage: External fields can't have initializers.
correctionMessage: "Try removing the field initializer or the 'external' keyword from the field declaration."
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a field or variable marked with
+ the keyword `external` has an initializer, or when an external field is
+ initialized in a constructor.
+
+ #### Examples
+
+ The following code produces this diagnostic because the external field `x`
+ is assigned a value in an initializer:
+
+ ```dart
+ class C {
+ external int x;
+ C() : [!x!] = 0;
+ }
+ ```
+
+ The following code produces this diagnostic because the external field `x`
+ has an initializer:
+
+ ```dart
+ class C {
+ external final int [!x!] = 0;
+ }
+ ```
+
+ The following code produces this diagnostic because the external top level
+ variable `x` has an initializer:
+
+ ```dart
+ external final int [!x!] = 0;
+ ```
+
+ #### Common fixes
+
+ Remove the initializer:
+
+ ```dart
+ class C {
+ external final int x;
+ }
+ ```
EXTERNAL_FIELD_INITIALIZER:
sharedName: EXTERNAL_WITH_INITIALIZER
problemMessage: External fields can't have initializers.
correctionMessage: "Try removing the initializer or the 'external' keyword."
+ hasPublishedDocs: true
EXTERNAL_VARIABLE_INITIALIZER:
sharedName: EXTERNAL_WITH_INITIALIZER
problemMessage: External variables can't have initializers.
correctionMessage: "Try removing the initializer or the 'external' keyword."
+ hasPublishedDocs: true
EXTRA_POSITIONAL_ARGUMENTS:
problemMessage: "Too many positional arguments: {0} expected, but {1} found."
correctionMessage: Try removing the extra arguments.
@@ -4314,9 +4498,42 @@
problemMessage: Initializing formal parameters can only be used in constructors.
correctionMessage: Try using a normal parameter.
comment: |-
- 7.6.1 Generative Constructors: It is a compile-time error if an
- initializing formal is used by a function other than a non-redirecting
- generative constructor.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when an initializing formal
+ parameter is used in the parameter list for anything other than a
+ constructor.
+
+ #### Example
+
+ The following code produces this diagnostic because the initializing
+ formal parameter `this.x` is being used in the method `m`:
+
+ ```dart
+ class A {
+ int x = 0;
+
+ m([[!this.x!] = 0]) {}
+ }
+ ```
+
+ #### Common fixes
+
+ Replace the initializing formal parameter with a normal parameter and
+ assign the field within the body of the method:
+
+ ```dart
+ class A {
+ int x = 0;
+
+ m([int x = 0]) {
+ this.x = x;
+ }
+ }
+ ```
FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR:
problemMessage: "The redirecting constructor can't have a field initializer."
correctionMessage: Try initializing the field in the constructor being redirected to.
@@ -4989,6 +5206,35 @@
```dart
int f() => 0;
```
+ ILLEGAL_ENUM_VALUES_DECLARATION:
+ sharedName: ILLEGAL_ENUM_VALUES
+ problemMessage: An instance member named 'values' can't be declared in a class that implements 'Enum'.
+ correctionMessage: Try using a different name.
+ ILLEGAL_ENUM_VALUES_INHERITANCE:
+ sharedName: ILLEGAL_ENUM_VALUES
+ problemMessage: An instance member named 'values' can't be inherited from '{0}' in a class that implements 'Enum'.
+ correctionMessage: Try using a different name.
+ comment: |-
+ Parameters:
+ 0: the name of the class that declares 'values'
+ ILLEGAL_LANGUAGE_VERSION_OVERRIDE:
+ problemMessage: The language version must be {0}.
+ correctionMessage: Try removing the language version override and migrating the code.
+ ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION:
+ sharedName: ILLEGAL_CONCRETE_ENUM_MEMBER
+ problemMessage: A concrete instance member named '{0}' can't be declared in a class that implements 'Enum'.
+ correctionMessage: Try using a different name.
+ comment: |-
+ Parameters:
+ 0: the name of member that cannot be declared
+ ILLEGAL_CONCRETE_ENUM_MEMBER_INHERITANCE:
+ sharedName: ILLEGAL_CONCRETE_ENUM_MEMBER
+ problemMessage: A concrete instance member named '{0}' can't be inherited from '{1}' in a class that implements 'Enum'.
+ correctionMessage: Try using a different name.
+ comment: |-
+ Parameters:
+ 0: the name of member that cannot be inherited
+ 1: the name of the class that declares the member
ILLEGAL_SYNC_GENERATOR_RETURN_TYPE:
problemMessage: "Functions marked 'sync*' must have a return type that is a supertype of 'Iterable<T>' for some type 'T'."
correctionMessage: "Try fixing the return type of the function, or removing the modifier 'sync*' from the function body."
@@ -5192,12 +5438,12 @@
int get defaultX => 0;
}
```
- IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT:
- problemMessage: The named parameter '{0}' is required in the implicitly invoked unnamed constructor of '{1}'.
- correctionMessage: Try declaring corresponding named super-parameter, or explicitly invoking a different constructor.
- IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS:
- problemMessage: The implicitly invoked unnamed constructor of '{0}' expects {1} positional arguments, but {2} found.
- correctionMessage: Try declaring positional super-parameters, or explicitly invoking a different constructor.
+ IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS:
+ problemMessage: The implicitly invoked unnamed constructor from '{0}' has required parameters.
+ correctionMessage: Try adding an explicit super initializer with the required arguments.
+ comment: |-
+ Parameters:
+ 0: the name of the superclass
IMPORT_INTERNAL_LIBRARY:
problemMessage: "The library '{0}' is internal and can't be imported."
hasPublishedDocs: true
@@ -5226,11 +5472,41 @@
problemMessage: "The imported library '{0}' can't have a part-of directive."
correctionMessage: Try importing the library that the part is a part of.
comment: |-
- 14.1 Imports: It is a compile-time error if the specified URI of an
- immediate import does not refer to a library declaration.
-
Parameters:
0: the uri pointing to a non-library declaration
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a [part file][] is imported
+ into a library.
+
+ #### Example
+
+ Given a [part file][] named `part.dart` containing the following:
+
+ ```dart
+ %uri="lib/part.dart"
+ part of lib;
+
+ class C{}
+ ```
+
+ The following code produces this diagnostic because imported files can't
+ have a part-of directive:
+
+ ```dart
+ library lib;
+
+ import [!'part.dart'!];
+
+ C c = C();
+ ```
+
+ #### Common fixes
+
+ Import the library that contains the [part file][] rather than the
+ [part file][] itself.
INCONSISTENT_CASE_EXPRESSION_TYPES:
problemMessage: "Case expressions must have the same types, '{0}' isn't a '{1}'."
comment: |-
@@ -5312,12 +5588,46 @@
INCONSISTENT_LANGUAGE_VERSION_OVERRIDE:
problemMessage: Parts must have exactly the same language version override as the library.
comment: |-
- It is a compile-time error if a part file has a different language version
- override than its library.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
- https://github.com/dart-lang/language/blob/master/accepted/
- future-releases/language-versioning/feature-specification.md
- #individual-library-language-version-override
+ The analyzer produces this diagnostic when a [part file][] has a language
+ version override comment that specifies a different language version than
+ the one being used for the library to which the part belongs.
+
+ #### Example
+
+ Given a [part file][] named `part.dart` that contains the following:
+
+ ```dart
+ %uri="lib/part.dart"
+ // @dart = 2.6
+ part of 'test.dart';
+ ```
+
+ The following code produces this diagnostic because the parts of a library
+ must have the same language version as the defining compilation unit:
+
+ ```dart
+ // @dart = 2.5
+ part [!'part.dart'!];
+ ```
+
+ #### Common fixes
+
+ Remove the language version override from the [part file][], so that it
+ implicitly uses the same version as the defining compilation unit:
+
+ ```dart
+ part of 'test.dart';
+ ```
+
+ If necessary, either adjust the language version override in the defining
+ compilation unit to be appropriate for the code in the part, or migrate
+ the code in the [part file][] to be consistent with the new language
+ version.
INITIALIZER_FOR_NON_EXISTENT_FIELD:
problemMessage: "'{0}' isn't a field in the enclosing class."
correctionMessage: "Try correcting the name to match an existing field, or defining a field named '{0}'."
@@ -5710,6 +6020,7 @@
instantiated:
```dart
+ // @dart = 2.16
enum E {a}
var e = [!E!]();
@@ -5721,6 +6032,7 @@
constants defined in the enum:
```dart
+ // @dart = 2.16
enum E {a}
var e = E.a;
@@ -6501,6 +6813,9 @@
void m2(String s) {}
}
```
+ INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR:
+ problemMessage: Generative enum constructors can only be used as targets of redirection.
+ correctionMessage: Try using a factory constructor, or an enum constant.
INVALID_REFERENCE_TO_THIS:
problemMessage: "Invalid reference to 'this' expression."
hasPublishedDocs: true
@@ -7871,11 +8186,41 @@
9.1 Mixin Application: It is a compile-time error if <i>S</i> does not
denote a class available in the immediately enclosing scope.
MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS:
- problemMessage: "Constructors can have at most one 'this' redirection."
+ problemMessage: Constructors can have only one 'this' redirection, at most.
correctionMessage: Try removing all but one of the redirections.
comment: |-
- 7.6.1 Generative Constructors: A generative constructor may be redirecting,
- in which case its only action is to invoke another generative constructor.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a constructor redirects to more
+ than one other constructor in the same class (using `this`).
+
+ #### Example
+
+ The following code produces this diagnostic because the unnamed
+ constructor in `C` is redirecting to both `this.a` and `this.b`:
+
+ ```dart
+ class C {
+ C() : this.a(), [!this.b()!];
+ C.a();
+ C.b();
+ }
+ ```
+
+ #### Common fixes
+
+ Remove all but one of the redirections:
+
+ ```dart
+ class C {
+ C() : this.a();
+ C.a();
+ C.b();
+ }
+ ```
MULTIPLE_SUPER_INITIALIZERS:
problemMessage: "A constructor can have at most one 'super' initializer."
correctionMessage: "Try removing all but one of the 'super' initializers."
@@ -8625,7 +8970,7 @@
#### Example
- The following code produces this diagnostic beause `a` isn't a constant:
+ The following code produces this diagnostic because `a` isn't a constant:
```dart
var a = 'a';
@@ -8728,6 +9073,10 @@
13.2 Expression Statements: It is a compile-time error if a non-constant
map literal that has no explicit type arguments appears in a place where a
statement is expected.
+ NON_FINAL_FIELD_IN_ENUM:
+ problemMessage: Enum can only declare final fields.
+ correctionMessage: Try making the field final.
+ comment: No parameters.
NON_GENERATIVE_CONSTRUCTOR:
problemMessage: "The generative constructor '{0}' is expected, but a factory was found."
correctionMessage: Try calling a different constructor of the superclass, or making the called constructor not be a factory constructor.
@@ -8780,14 +9129,76 @@
problemMessage: "The unnamed constructor of superclass '{0}' (called by the default constructor of '{1}') must be a generative constructor, but factory found."
correctionMessage: "Try adding an explicit constructor that has a different superinitializer or changing the superclass constructor '{2}' to not be a factory constructor."
comment: |-
- An error code for when a class has no explicit constructor, and therefore
- a constructor is implicitly defined which uses a factory as a
- superinitializer. See [NON_GENERATIVE_CONSTRUCTOR].
-
Parameters:
0: the name of the superclass
1: the name of the current class
2: the implicitly called factory constructor of the superclass
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a class has an implicit
+ generative constructor and the superclass has an explicit unnamed factory
+ constructor. The implicit constructor in the subclass implicitly invokes
+ the unnamed constructor in the superclass, but generative constructors can
+ only invoke another generative constructor, not a factory constructor.
+
+ #### Example
+
+ The following code produces this diagnostic because the implicit
+ constructor in `B` invokes the unnamed constructor in `A`, but the
+ constructor in `A` is a factory constructor, when a generative constructor
+ is required:
+
+ ```dart
+ class A {
+ factory A() => throw 0;
+ A.named();
+ }
+
+ class [!B!] extends A {}
+ ```
+
+ #### Common fixes
+
+ If the unnamed constructor in the superclass can be a generative
+ constructor, then change it to be a generative constructor:
+
+ ```dart
+ class A {
+ A();
+ A.named();
+ }
+
+ class B extends A { }
+ ```
+
+ If the unnamed constructor can't be a generative constructor and there are
+ other generative constructors in the superclass, then explicitly invoke
+ one of them:
+
+ ```dart
+ class A {
+ factory A() => throw 0;
+ A.named();
+ }
+
+ class B extends A {
+ B() : super.named();
+ }
+ ```
+
+ If there are no generative constructors that can be used and none can be
+ added, then implement the superclass rather than extending it:
+
+ ```dart
+ class A {
+ factory A() => throw 0;
+ A.named();
+ }
+
+ class B implements A {}
+ ```
NON_SYNC_FACTORY:
problemMessage: "Factory bodies can't use 'async', 'async*', or 'sync*'."
hasPublishedDocs: true
@@ -9509,16 +9920,73 @@
constructor
1: the name of the subclass that does not contain any explicit constructors
NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS:
- problemMessage: "The class '{0}' cannot extend '{1}' because '{1}' only has factory constructors (no generative constructors), and '{0}' has at least one generative constructor."
- correctionMessage: "Try implementing the class instead, adding a generative (not factory) constructor to the superclass {0}, or a factory constructor to the subclass."
+ problemMessage: "The class '{0}' can't extend '{1}' because '{1}' only has factory constructors (no generative constructors), and '{0}' has at least one generative constructor."
+ correctionMessage: "Try implementing the class instead, adding a generative (not factory) constructor to the superclass '{1}', or a factory constructor to the subclass."
comment: |-
- User friendly specialized error for [NON_GENERATIVE_CONSTRUCTOR]. This
- handles the case of `class E extends Exception` which will never work
- because [Exception] has no generative constructors.
-
Parameters:
0: the name of the subclass
1: the name of the superclass
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a class that has at least one
+ generative constructor (whether explicit or implicit) has a superclass
+ that doesn't have any generative constructors. Every generative
+ constructor, except the one defined in `Object`, invokes, either
+ explicitly or implicitly, one of the generative constructors from its
+ superclass.
+
+ #### Example
+
+ The following code produces this diagnostic because the class `B` has an
+ implicit generative constructor that can't invoke a generative constructor
+ from `A` because `A` doesn't have any generative constructors:
+
+ ```dart
+ class A {
+ factory A.none() => throw '';
+ }
+
+ class B extends [!A!] {}
+ ```
+
+ #### Common fixes
+
+ If the superclass should have a generative constructor, then add one:
+
+ ```dart
+ class A {
+ A();
+ factory A.none() => throw '';
+ }
+
+ class B extends A {}
+ ```
+
+ If the subclass shouldn't have a generative constructor, then remove it by
+ adding a factory constructor:
+
+ ```dart
+ class A {
+ factory A.none() => throw '';
+ }
+
+ class B extends A {
+ factory B.none() => throw '';
+ }
+ ```
+
+ If the subclass must have a generative constructor but the superclass
+ can't have one, then implement the superclass instead:
+
+ ```dart
+ class A {
+ factory A.none() => throw '';
+ }
+
+ class B implements A {}
+ ```
NULLABLE_TYPE_IN_EXTENDS_CLAUSE:
problemMessage: "A class can't extend a nullable type."
correctionMessage: Try removing the question mark.
@@ -9788,8 +10256,8 @@
If the library should be using a different file as a part, then change the
URI in the part directive to be the URI of the other file.
- If the part file should be a part of this library, then update the URI (or
- library name) in the part-of directive to be the URI (or name) of the
+ If the [part file][] should be a part of this library, then update the URI
+ (or library name) in the part-of directive to be the URI (or name) of the
correct library.
PART_OF_NON_PART:
problemMessage: "The included part '{0}' must have a part-of directive."
@@ -9849,13 +10317,14 @@
#### Description
The analyzer produces this diagnostic when a library that doesn't have a
- `library` directive (and hence has no name) contains a `part` directive and
- the `part of` directive in the part file uses a name to specify the library
- that it's a part of.
+ `library` directive (and hence has no name) contains a `part` directive
+ and the `part of` directive in the [part file][] uses a name to specify
+ the library that it's a part of.
#### Example
- Given a part file named `part_file.dart` containing the following code:
+ Given a [part file][] named `part_file.dart` containing the following
+ code:
```dart
%uri="lib/part_file.dart"
@@ -9863,8 +10332,8 @@
```
The following code produces this diagnostic because the library including
- the part file doesn't have a name even though the part file uses a name to
- specify which library it's a part of:
+ the [part file][] doesn't have a name even though the [part file][] uses a
+ name to specify which library it's a part of:
```dart
part [!'part_file.dart'!];
@@ -9872,8 +10341,8 @@
#### Common fixes
- Change the `part of` directive in the part file to specify its library by
- URI:
+ Change the `part of` directive in the [part file][] to specify its library
+ by URI:
```dart
part of 'test.dart';
@@ -9968,17 +10437,57 @@
If the name is wrong, then correct the name.
PREFIX_SHADOWED_BY_LOCAL_DECLARATION:
- problemMessage: "The prefix '{0}' can't be used here because it is shadowed by a local declaration."
+ problemMessage: "The prefix '{0}' can't be used here because it's shadowed by a local declaration."
correctionMessage: Try renaming either the prefix or the local declaration.
comment: |-
- From the `Static Types` section of the spec:
+ Parameters:
+ 0: the prefix being shadowed
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
- A type T is malformed if:
- - T has the form id or the form prefix.id, and in the enclosing lexical
- scope, the name id (respectively prefix.id) does not denote a type.
+ The analyzer produces this diagnostic when an import prefix is used in a
+ context where it isn't visible because it was shadowed by a local
+ declaration.
- In particular, this means that if an import prefix is shadowed by a local
- declaration, it is an error to try to use it as a prefix for a type name.
+ #### Example
+
+ The following code produces this diagnostic because the prefix `a` is
+ being used to access the class `Future`, but isn't visible because it's
+ shadowed by the parameter `a`:
+
+ ```dart
+ import 'dart:async' as a;
+
+ a.Future? f(int a) {
+ [!a!].Future? x;
+ return x;
+ }
+ ```
+
+ #### Common fixes
+
+ Rename either the prefix:
+
+ ```dart
+ import 'dart:async' as p;
+
+ p.Future? f(int a) {
+ p.Future? x;
+ return x;
+ }
+ ```
+
+ Or rename the local variable:
+
+ ```dart
+ import 'dart:async' as a;
+
+ a.Future? f(int p) {
+ a.Future? x;
+ return x;
+ }
+ ```
PRIVATE_COLLISION_IN_MIXIN_APPLICATION:
problemMessage: "The private name '{0}', defined by '{1}', conflicts with the same name defined by '{2}'."
correctionMessage: "Try removing '{1}' from the 'with' clause."
@@ -10063,11 +10572,90 @@
}
```
PRIVATE_SETTER:
- problemMessage: "The setter '{0}' is private and can't be accessed outside of the library that declares it."
+ problemMessage: "The setter '{0}' is private and can't be accessed outside the library that declares it."
correctionMessage: Try making it public.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a private setter is used in a
+ library where it isn't visible.
+
+ #### Example
+
+ Given a file named `a.dart` that contains the following:
+
+ ```dart
+ %uri="lib/a.dart"
+ class A {
+ static int _f = 0;
+ }
+ ```
+
+ The following code produces this diagnostic because it references the
+ private setter `_f` even though the setter isn't visible:
+
+ ```dart
+ import 'a.dart';
+
+ void f() {
+ A.[!_f!] = 0;
+ }
+ ```
+
+ #### Common fixes
+
+ If you're able to make the setter public, then do so:
+
+ ```dart
+ %uri="lib/a.dart"
+ class A {
+ static int f = 0;
+ }
+ ```
+
+ If you aren't able to make the setter public, then find a different way to
+ implement the code.
READ_POTENTIALLY_UNASSIGNED_FINAL:
- problemMessage: "The final variable '{0}' can't be read because it is potentially unassigned at this point."
+ problemMessage: "The final variable '{0}' can't be read because it's potentially unassigned at this point."
correctionMessage: Ensure that it is assigned on necessary execution paths.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a final local variable that
+ isn't initialized at the declaration site is read at a point where the
+ compiler can't prove that the variable is always initialized before it's
+ referenced.
+
+ #### Example
+
+ The following code produces this diagnostic because the final local
+ variable `x` is read (on line 3) when it's possible that it hasn't yet
+ been initialized:
+
+ ```dart
+ int f() {
+ final int x;
+ return [!x!];
+ }
+ ```
+
+ #### Common fixes
+
+ Ensure that the variable has been initialized before it's read:
+
+ ```dart
+ int f(bool b) {
+ final int x;
+ if (b) {
+ x = 0;
+ } else {
+ x = 1;
+ }
+ return x;
+ }
+ ```
RECURSIVE_COMPILE_TIME_CONSTANT:
problemMessage: The compile-time constant expression depends on itself.
hasPublishedDocs: true
@@ -10371,8 +10959,45 @@
problemMessage: "The redirecting constructor '{0}' can't redirect to a constructor of the abstract class '{1}'."
correctionMessage: Try redirecting to a constructor of a different class.
comment: |-
- A factory constructor can't redirect to a non-generative constructor of an
- abstract class.
+ Parameters:
+ 0: the name of the redirecting constructor
+ 1: the name of the abstract class defining the constructor being redirected to
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a constructor redirects to a
+ constructor in an abstract class.
+
+ #### Example
+
+ The following code produces this diagnostic because the factory
+ constructor in `A` redirects to a constructor in `B`, but `B` is an
+ abstract class:
+
+ ```dart
+ class A {
+ factory A() = [!B!];
+ }
+
+ abstract class B implements A {}
+ ```
+
+ #### Common fixes
+
+ If the code redirects to the correct constructor, then change the class so
+ that it isn't abstract:
+
+ ```dart
+ class A {
+ factory A() = B;
+ }
+
+ class B implements A {}
+ ```
+
+ Otherwise, change the factory constructor so that it either redirects to a
+ constructor in a concrete class, or has a concrete implementation.
REDIRECT_TO_INVALID_FUNCTION_TYPE:
problemMessage: "The redirected constructor '{0}' has incompatible parameters with '{1}'."
correctionMessage: Try redirecting to a different constructor.
@@ -10511,8 +11136,58 @@
problemMessage: "The constructor '{0}' couldn't be found in '{1}'."
correctionMessage: "Try redirecting to a different constructor, or define the constructor named '{0}'."
comment: |-
- 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with
- the const modifier but <i>k'</i> is not a constant constructor.
+ Parameters:
+ 0: the name of the constructor
+ 1: the name of the class containing the constructor
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a constructor redirects to a
+ constructor that doesn't exist.
+
+ #### Example
+
+ The following code produces this diagnostic because the factory
+ constructor in `A` redirects to a constructor in `B` that doesn't exist:
+
+ ```dart
+ class A {
+ factory A() = [!B.name!];
+ }
+
+ class B implements A {
+ B();
+ }
+ ```
+
+ #### Common fixes
+
+ If the constructor being redirected to is correct, then define the
+ constructor:
+
+ ```dart
+ class A {
+ factory A() = B.name;
+ }
+
+ class B implements A {
+ B();
+ B.name();
+ }
+ ```
+
+ If a different constructor should be invoked, then update the redirect:
+
+ ```dart
+ class A {
+ factory A() = B;
+ }
+
+ class B implements A {
+ B();
+ }
+ ```
REDIRECT_TO_NON_CLASS:
problemMessage: "The name '{0}' isn't a type and can't be used in a redirected constructor."
correctionMessage: Try redirecting to a different constructor.
@@ -11371,6 +12046,9 @@
B(int x) : assert(x >= 0), super(x);
}
```
+ SUPER_IN_ENUM_CONSTRUCTOR:
+ problemMessage: The enum constructor can't have a 'super' initializer.
+ correctionMessage: Try removing the 'super' invocation.
SUPER_IN_EXTENSION:
problemMessage: "The 'super' keyword can't be used in an extension because an extension doesn't have a superclass."
hasPublishedDocs: true
@@ -11461,14 +12139,44 @@
}
```
SWITCH_CASE_COMPLETES_NORMALLY:
- problemMessage: "The 'case' should not complete normally."
- correctionMessage: "Try adding 'break', or 'return', etc."
+ problemMessage: "The 'case' shouldn't complete normally."
+ correctionMessage: "Try adding 'break', 'return', or 'throw'."
comment: |-
- It is an error if any case of a switch statement except the last case (the
- default case if present) may complete normally. The previous syntactic
- restriction requiring the last statement of each case to be one of an
- enumerated list of statements (break, continue, return, throw, or rethrow)
- is removed.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when the statements following a
+ `case` label in a `switch` statement could fall through to the next `case`
+ or `default` label.
+
+ #### Example
+
+ The following code produces this diagnostic because the `case` label with
+ a value of zero (`0`) falls through to the `default` statements:
+
+ ```dart
+ void f(int a) {
+ switch (a) {
+ [!case!] 0:
+ print(0);
+ default:
+ return;
+ }
+ }
+ ```
+
+ #### Common fixes
+
+ Change the flow of control so that the `case` won't fall through. There
+ are several ways that this can be done, including adding one of the
+ following at the end of the current list of statements:
+ - a `return` statement,
+ - a `throw` expression,
+ - a `break` statement,
+ - a `continue`, or
+ - an invocation of a function or method whose return type is `Never`.
SWITCH_EXPRESSION_NOT_ASSIGNABLE:
problemMessage: "Type '{0}' of the switch expression isn't assignable to the type '{1}' of case expressions."
hasPublishedDocs: true
@@ -12196,8 +12904,8 @@
hasPublishedDocs: true
comment: |-
Parameters:
- 0: the name of the enumeration constant that is not defined
- 1: the name of the enumeration used to access the constant
+ 0: the name of the enum constant that is not defined
+ 1: the name of the enum used to access the constant
documentation: |-
#### Description
@@ -12235,6 +12943,17 @@
var e = E.b;
```
+ UNDEFINED_ENUM_CONSTRUCTOR_NAMED:
+ sharedName: UNDEFINED_ENUM_CONSTRUCTOR
+ problemMessage: The enum doesn't have a constructor named '{0}'.
+ correctionMessage: Try correcting the name to the name of an existing constructor, or defining constructor with the name '{0}'.
+ comment: |-
+ Parameters:
+ 0: the name of the constructor that is undefined
+ UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED:
+ sharedName: UNDEFINED_ENUM_CONSTRUCTOR
+ problemMessage: The enum doesn't have an unnamed constructor.
+ correctionMessage: Try adding the name of an existing constructor, or defining an unnamed constructor.
UNDEFINED_EXTENSION_GETTER:
problemMessage: "The getter '{0}' isn't defined for the extension '{1}'."
correctionMessage: "Try correcting the name to the name of an existing getter, or defining a getter named '{0}'."
@@ -13308,6 +14027,9 @@
Either rewrite the code so that the expression has a value or rewrite the
code so that it doesn't depend on the value.
+ VALUES_DECLARATION_IN_ENUM:
+ problemMessage: A member named 'values' can't be declared in an enum.
+ correctionMessage: Try using a different name.
VARIABLE_TYPE_MISMATCH:
problemMessage: "A value of type '{0}' can't be assigned to a const variable of type '{1}'."
correctionMessage: "Try using a subtype, or removing the 'const' keyword"
@@ -13563,6 +14285,13 @@
}
C f() => C.named();
```
+ WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM:
+ problemMessage: The enum is declared with {0} type parameters, but {1} type arguments were given.
+ correctionMessage: Try adjusting the number of type arguments.
+ comment: |-
+ Parameters:
+ 0: the number of type parameters that were declared
+ 1: the number of type arguments provided
WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION:
problemMessage: "The extension '{0}' is declared with {1} type parameters, but {2} type arguments were given."
correctionMessage: Try adjusting the number of type arguments.
@@ -13834,6 +14563,7 @@
problemMessage: "Fields in a struct class whose type is 'Pointer' shouldn't have any annotations."
correctionMessage: Try removing the annotation.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -13875,6 +14605,7 @@
comment: |-
Parameters:
0: the name of the argument
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -13930,6 +14661,7 @@
problemMessage: "Subclasses of 'Struct' and 'Union' are backed by native memory, and can't be instantiated by a generative constructor."
correctionMessage: "Try allocating it via allocation, or load from a 'Pointer'."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -13984,6 +14716,7 @@
Parameters:
0: the name of the subclass
1: the name of the superclass
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14036,6 +14769,7 @@
problemMessage: Fields in a struct class must have exactly one annotation indicating the native type.
correctionMessage: Try removing the extra annotation.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14075,6 +14809,7 @@
problemMessage: "'Array's must have exactly one 'Array' annotation."
correctionMessage: Try removing the extra annotation.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14137,6 +14872,7 @@
problemMessage: "Constructors in subclasses of 'Struct' and 'Union' can't have field initializers."
correctionMessage: Try removing the field initializer and marking the field as external.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14181,6 +14917,7 @@
problemMessage: "Fields in subclasses of 'Struct' and 'Union' can't have initializers."
correctionMessage: Try removing the initializer and marking the field as external.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14219,6 +14956,7 @@
problemMessage: "Fields of 'Struct' and 'Union' subclasses must be marked external."
correctionMessage: "Try adding the 'external' modifier."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14259,6 +14997,7 @@
comment: |-
Parameters:
0: the name of the struct class
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14295,6 +15034,7 @@
problemMessage: "The method 'Pointer.fromFunction' can't have an exceptional return value (the second argument) when the return type of the function is either 'void', 'Handle' or 'Pointer'."
correctionMessage: Try removing the exceptional return value.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14343,6 +15083,7 @@
comment: |-
Parameters:
0: the type of the field
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14388,6 +15129,7 @@
problemMessage: "FFI leaf call can't return a 'Handle'."
correctionMessage: Try changing the return type to primitive or struct.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14444,6 +15186,7 @@
problemMessage: "FFI leaf call can't take arguments of type 'Handle'."
correctionMessage: Try changing the argument type to primitive or struct.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14494,6 +15237,7 @@
problemMessage: "The annotation doesn't match the declared type of the field."
correctionMessage: Try using a different annotation or changing the declared type to match.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14543,6 +15287,7 @@
problemMessage: "Fields in a struct class must either have the type 'Pointer' or an annotation indicating the native type."
correctionMessage: Try adding an annotation.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14583,6 +15328,7 @@
problemMessage: "The method 'Pointer.fromFunction' must have an exceptional return value (the second argument) when the return type of the function is neither 'void', 'Handle', nor 'Pointer'."
correctionMessage: Try adding an exceptional return value.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14628,6 +15374,7 @@
comment: |-
Parameters:
0: the type of the field
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14673,6 +15420,7 @@
problemMessage: "Fields of type 'Array' must have exactly one 'Array' annotation."
correctionMessage: "Try adding an 'Array' annotation, or removing all but one of the annotations."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14714,6 +15462,7 @@
Parameters:
0: the type that should be a valid dart:ffi native type.
1: the name of the function whose invocation depends on this relationship
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14764,6 +15513,7 @@
0: the type that should be a subtype
1: the supertype that the subtype is compared to
2: the name of the function whose invocation depends on this relationship
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14829,6 +15579,7 @@
comment: |-
Parameters:
0: the name of the function, method, or constructor having type arguments
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14876,6 +15627,7 @@
comment: |-
Parameters:
0: the type that should be a valid dart:ffi native type.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14924,6 +15676,7 @@
problemMessage: Array dimensions must be positive numbers.
correctionMessage: Try changing the input to a positive number.
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -14964,6 +15717,7 @@
comment: |-
Parameters:
0: the type of the field
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15004,6 +15758,7 @@
problemMessage: "Structs must have at most one 'Packed' annotation."
correctionMessage: "Try removing extra 'Packed' annotations."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15043,6 +15798,7 @@
problemMessage: Only packing to 1, 2, 4, 8, and 16 bytes is supported.
correctionMessage: "Try changing the 'Packed' annotation alignment to 1, 2, 4, 8, or 16."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15084,6 +15840,7 @@
Parameters:
0: the name of the outer struct
1: the name of the struct being nested
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15165,6 +15922,7 @@
problemMessage: "'Array's must have an 'Array' annotation that matches the dimensions."
correctionMessage: "Try adjusting the arguments in the 'Array' annotation."
comment: No parameters.
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15221,6 +15979,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15270,6 +16029,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
SUBTYPE_OF_FFI_CLASS_IN_WITH:
sharedName: SUBTYPE_OF_FFI_CLASS
problemMessage: "The class '{0}' can't mix in '{1}'."
@@ -15278,6 +16038,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS:
sharedName: SUBTYPE_OF_STRUCT_CLASS
problemMessage: "The class '{0}' can't extend '{1}' because '{1}' is a subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
@@ -15286,6 +16047,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
documentation: |-
#### Description
@@ -15339,6 +16101,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
SUBTYPE_OF_STRUCT_CLASS_IN_WITH:
sharedName: SUBTYPE_OF_STRUCT_CLASS
problemMessage: "The class '{0}' can't mix in '{1}' because '{1}' is a subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
@@ -15347,6 +16110,7 @@
Parameters:
0: the name of the subclass
1: the name of the class being extended, implemented, or mixed in
+ hasPublishedDocs: true
HintCode:
ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER:
problemMessage: "The argument type '{0}' can't be assigned to the parameter type '{1} Function(Object)' or '{1} Function(Object, StackTrace)'."
@@ -15412,6 +16176,33 @@
problemMessage: "'{0}' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable."
correctionMessage: Try removing the assignment.
comment: Users should not assign values marked `@doNotStore`.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when the value of a function
+ (including methods and getters) that is explicitly or implicitly marked by
+ the `[doNotStore][meta-doNotStore]` annotation is stored in either a field
+ or top-level variable.
+
+ #### Example
+
+ The following code produces this diagnostic because the value of the
+ function `f` is being stored in the top-level variable `x`:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ @doNotStore
+ int f() => 1;
+
+ var x = [!f()!];
+ ```
+
+ #### Common fixes
+
+ Replace references to the field or variable with invocations of the
+ function producing the value.
BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE:
problemMessage: "This function has a nullable return type of '{0}', but ends without returning a value."
correctionMessage: "Try adding a return statement, or if no value is ever returned, try changing the return type to 'void'."
@@ -15419,6 +16210,40 @@
comment: |-
Parameters:
0: the name of the declared return type
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a method or function can
+ implicitly return `null` by falling off the end. While this is valid Dart
+ code, it's better for the return of `null` to be explicit.
+
+ #### Example
+
+ The following code produces this diagnostic because the function `f`
+ implicitly returns `null`:
+
+ ```dart
+ String? [!f!]() {}
+ ```
+
+ #### Common fixes
+
+ If the return of `null` is intentional, then make it explicit:
+
+ ```dart
+ String? f() {
+ return null;
+ }
+ ```
+
+ If the function should return a non-null value along that path, then add
+ the missing return statement:
+
+ ```dart
+ String? f() {
+ return '';
+ }
+ ```
CAN_BE_NULL_AFTER_NULL_AWARE:
problemMessage: "The receiver uses '?.', so its value can be null."
correctionMessage: "Replace the '.' with a '?.' in the invocation."
@@ -15676,6 +16501,56 @@
problemMessage: "Using the 'new' keyword in a comment reference is deprecated."
correctionMessage: Try referring to a constructor by its name.
comment: No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a comment reference (the name
+ of a declaration enclosed in square brackets in a documentation comment)
+ uses the keyword `new` to refer to a constructor. This form is deprecated.
+
+ #### Examples
+
+ The following code produces this diagnostic because the unnamed
+ constructor is being referenced using `new C`:
+
+ ```dart
+ /// See [[!new!] C].
+ class C {
+ C();
+ }
+ ```
+
+ The following code produces this diagnostic because the constructor named
+ `c` is being referenced using `new C.c`:
+
+ ```dart
+ /// See [[!new!] C.c].
+ class C {
+ C.c();
+ }
+ ```
+
+ #### Common fixes
+
+ If you're referencing a named constructor, then remove the keyword `new`:
+
+ ```dart
+ /// See [C.c].
+ class C {
+ C.c();
+ }
+ ```
+
+ If you're referencing the unnamed constructor, then remove the keyword
+ `new` and append `.new` after the class name:
+
+ ```dart
+ /// See [C.new].
+ class C {
+ C.c();
+ }
+ ```
DEPRECATED_MIXIN_FUNCTION:
sharedName: DEPRECATED_SUBTYPE_OF_FUNCTION
problemMessage: "Mixing in 'Function' is deprecated."
@@ -16074,11 +16949,50 @@
```
If type arguments shouldn't be required for the class, then mark the class
- with the `@optionalTypeArgs` annotation (from `package:meta`):
+ with the `[optionalTypeArgs][meta-optionalTypeArgs]` annotation (from
+ `package:meta`):
IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE:
- problemMessage: "The library '{0}' is legacy, and should not be imported into a null safe library."
+ problemMessage: "The library '{0}' is legacy, and shouldn't be imported into a null safe library."
correctionMessage: Try migrating the imported library.
- comment: "https://github.com/dart-lang/sdk/issues/44063"
+ comment: |-
+ No parameters.
+
+ https://github.com/dart-lang/sdk/issues/44063
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a library that is null safe
+ imports a library that isn't null safe.
+
+ #### Example
+
+ Given a file named `a.dart` that contains the following:
+
+ ```dart
+ %uri="lib/a.dart"
+ // @dart = 2.9
+
+ class A {}
+ ```
+
+ The following code produces this diagnostic because a library that null
+ safe is importing a library that isn't null safe:
+
+ ```dart
+ import [!'a.dart'!];
+
+ A? f() => null;
+ ```
+
+ #### Common fixes
+
+ If you can migrate the imported library to be null safe, then migrate it
+ and update or remove the migrated library's language version.
+
+ If you can't migrate the imported library, then the importing library
+ needs to have a language version that is before 2.12, when null safety was
+ enabled by default.
INFERENCE_FAILURE_ON_COLLECTION_LITERAL:
problemMessage: "The type argument(s) of '{0}' can't be inferred."
correctionMessage: "Use explicit type argument(s) for '{0}'."
@@ -16126,29 +17040,121 @@
When "strict-inference" in enabled, function parameters must be
declared with a specific type, or inherit a type.
INVALID_ANNOTATION_TARGET:
- problemMessage: "The annotation '{0}' can only be used on {1}"
+ problemMessage: "The annotation '{0}' can only be used on {1}."
comment: |-
Parameters:
0: the name of the annotation
1: the list of valid targets
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when an annotation is applied to a
+ kind of declaration that it doesn't support.
+
+ #### Example
+
+ The following code produces this diagnostic because the `optionalTypeArgs`
+ annotation isn't defined to be valid for top-level variables:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ @[!optionalTypeArgs!]
+ int x = 0;
+ ```
+
+ #### Common fixes
+
+ Remove the annotation from the declaration.
INVALID_EXPORT_OF_INTERNAL_ELEMENT:
problemMessage: "The member '{0}' can't be exported as a part of a package's public API."
correctionMessage: "Try using a hide clause to hide '{0}'."
comment: |-
- This hint is generated anywhere where an element annotated with `@internal`
- is exported as a part of a package's public API.
-
Parameters:
0: the name of the element
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a [public library][] exports a
+ declaration that is marked with the `[internal][meta-internal]`
+ annotation.
+
+ #### Example
+
+ Given a file named `a.dart` in the `src` directory that contains:
+
+ ```dart
+ %uri="lib/src/a.dart"
+ import 'package:meta/meta.dart';
+
+ @internal class One {}
+ ```
+
+ The following code, when found in a [public library][] produces this
+ diagnostic because the `export` directive is exporting a name that is only
+ intended to be used internally:
+
+ ```dart
+ [!export 'src/a.dart';!]
+ ```
+
+ #### Common fixes
+
+ If the export is needed, then add a `hide` clause to hide the internal
+ names:
+
+ ```dart
+ export 'src/a.dart' hide One;
+ ```
+
+ If the export isn't needed, then remove it.
INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY:
problemMessage: "The member '{0}' can't be exported as a part of a package's public API, but is indirectly exported as part of the signature of '{1}'."
correctionMessage: "Try using a hide clause to hide '{0}'."
comment: |-
- This hint is generated anywhere where an element annotated with `@internal`
- is exported indirectly as a part of a package's public API.
-
Parameters:
0: the name of the element
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a [public library][] exports a
+ top-level function with a return type or at least one parameter type that
+ is marked with the `[internal][meta-internal]` annotation.
+
+ #### Example
+
+ Given a file named `a.dart` in the `src` directory that contains the
+ following:
+
+ ```dart
+ %uri="lib/src/a.dart"
+ import 'package:meta/meta.dart';
+
+ @internal
+ typedef IntFunction = int Function();
+
+ int f(IntFunction g) => g();
+ ```
+
+ The following code produces this diagnostic because the function `f` has a
+ parameter of type `IntFunction`, and `IntFunction` is only intended to be
+ used internally:
+
+ ```dart
+ [!export 'src/a.dart' show f;!]
+ ```
+
+ #### Common fixes
+
+ If the function must be public, then make all the types in the function's
+ signature public types.
+
+ If the function doesn't need to be exported, then stop exporting it,
+ either by removing it from the `show` clause, adding it to the `hide`
+ clause, or by removing the export.
INVALID_FACTORY_ANNOTATION:
problemMessage: Only methods can be annotated as factories.
comment: |-
@@ -16157,17 +17163,91 @@
INVALID_FACTORY_METHOD_DECL:
problemMessage: "Factory method '{0}' must have a return type."
comment: |-
- This hint is generated anywhere a @factory annotation is associated with
- a method that does not declare a return type.
+ Parameters:
+ 0: The name of the method
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a method that is annotated with
+ the `[factory][meta-factory]` annotation has a return type of `void`.
+
+ #### Example
+
+ The following code produces this diagnostic because the method `createC`
+ is annotated with the `[factory][meta-factory]` annotation but doesn't
+ return any value:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ class Factory {
+ @factory
+ void [!createC!]() {}
+ }
+
+ class C {}
+ ```
+
+ #### Common fixes
+
+ Change the return type to something other than `void`:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ class Factory {
+ @factory
+ C createC() => C();
+ }
+
+ class C {}
+ ```
INVALID_FACTORY_METHOD_IMPL:
problemMessage: "Factory method '{0}' doesn't return a newly allocated object."
comment: |-
- This hint is generated anywhere a @factory annotation is associated with
- a non-abstract method that can return anything other than a newly allocated
- object.
-
Parameters:
0: the name of the method
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a method that is annotated with
+ the `[factory][meta-factory]` annotation doesn't return a newly allocated
+ object.
+
+ #### Example
+
+ The following code produces this diagnostic because the method `createC`
+ returns the value of a field rather than a newly created instance of `C`:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ class Factory {
+ C c = C();
+
+ @factory
+ C [!createC!]() => c;
+ }
+
+ class C {}
+ ```
+
+ #### Common fixes
+
+ Change the method to return a newly created instance of the return type:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ class Factory {
+ @factory
+ C createC() => C();
+ }
+
+ class C {}
+ ```
INVALID_IMMUTABLE_ANNOTATION:
problemMessage: Only classes can be annotated as being immutable.
comment: |-
@@ -16176,121 +17256,145 @@
INVALID_INTERNAL_ANNOTATION:
problemMessage: "Only public elements in a package's private API can be annotated as being internal."
comment: |-
- This hint is generated anywhere a @internal annotation is associated with
- an element found in a package's public API.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a declaration is annotated with
+ the `[internal][meta-internal]` annotation and that declaration is either
+ in a [public library][] or has a private name.
+
+ #### Example
+
+ The following code, when in a [public library][], produces this diagnostic
+ because the `[internal][meta-internal]` annotation can't be applied to
+ declarations in a [public library][]:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ [!@internal!]
+ class C {}
+ ```
+
+ The following code, whether in a public or internal library, produces this
+ diagnostic because the `[internal][meta-internal]` annotation can't be
+ applied to declarations with private names:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ [!@internal!]
+ class _C {}
+
+ void f(_C c) {}
+ ```
+
+ #### Common fixes
+
+ If the declaration has a private name, then remove the annotation:
+
+ ```dart
+ class _C {}
+
+ void f(_C c) {}
+ ```
+
+ If the declaration has a public name and is intended to be internal to the
+ package, then move the annotated declaration into an internal library (in
+ other words, a library inside the `src` directory).
+
+ Otherwise, remove the use of the annotation:
+
+ ```dart
+ class C {}
+ ```
INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The language version override can't specify a version greater than the latest known language version: {0}.{1}"
+ problemMessage: "The language version override can't specify a version greater than the latest known language version: {0}.{1}."
correctionMessage: Try removing the language version override.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The Dart language version override number must begin with '@dart'"
+ problemMessage: "The Dart language version override number must begin with '@dart'."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ The analyzer produces this diagnostic when a comment that appears to be an
+ attempt to specify a language version override doesn't conform to the
+ requirements for such a comment. For more information, see
+ [Per-library language version selection](https://dart.dev/guides/language/evolution#per-library-language-version-selection).
+
+ #### Example
+
+ The following code produces this diagnostic because the word `dart` must
+ be lowercase in such a comment and because there's no equal sign between
+ the word `dart` and the version number:
+
+ ```dart
+ [!// @Dart 2.9!]
+ ```
+
+ #### Common fixes
+
+ If the comment is intended to be a language version override, then change
+ the comment to follow the correct format:
+
+ ```dart
+ // @dart = 2.9
+ ```
INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: The language version override must be before any declaration or directive.
+ problemMessage: The language version override must be specified before any declaration or directive.
correctionMessage: Try moving the language version override to the top of the file.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The Dart language version override comment must be specified with the word 'dart' in all lower case"
+ problemMessage: "The Dart language version override comment must be specified with the word 'dart' in all lower case."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
problemMessage: "The Dart language version override comment must be specified with a version number, like '2.0', after the '=' character."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The Dart language version override number can't be prefixed with a letter"
+ problemMessage: "The Dart language version override number can't be prefixed with a letter."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The Dart language version override comment can't be followed by any non-whitespace characters"
+ problemMessage: "The Dart language version override comment can't be followed by any non-whitespace characters."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
problemMessage: The Dart language version override comment must be specified with exactly two slashes.
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS:
sharedName: INVALID_LANGUAGE_VERSION_OVERRIDE
- problemMessage: "The Dart language version override comment must be specified with an '=' character"
+ problemMessage: "The Dart language version override comment must be specified with an '=' character."
correctionMessage: "Specify a Dart language version override with a comment like '// @dart = 2.0'."
comment: |-
- Invalid Dart language version comments don't follow the specification [1].
- If a comment begins with "@dart" or "dart" (letters in any case),
- followed by optional whitespace, followed by optional non-alphanumeric,
- non-whitespace characters, followed by optional whitespace, followed by
- an optional alphabetical character, followed by a digit, then the
- comment is considered to be an attempt at a language version override
- comment. If this attempted language version override comment is not a
- valid language version override comment, it is reported.
-
- [1] https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/feature-specification.md#individual-library-language-version-override
+ No parameters.
+ hasPublishedDocs: true
INVALID_LITERAL_ANNOTATION:
problemMessage: Only const constructors can have the `@literal` annotation.
hasPublishedDocs: true
@@ -16298,8 +17402,8 @@
documentation: |-
#### Description
- The analyzer produces this diagnostic when the `@literal` annotation is
- applied to anything other than a const constructor.
+ The analyzer produces this diagnostic when the `[literal][[meta-literal]]`
+ annotation is applied to anything other than a const constructor.
#### Examples
@@ -16469,11 +17573,41 @@
INVALID_USE_OF_INTERNAL_MEMBER:
problemMessage: "The member '{0}' can only be used within its package."
comment: |-
- This hint is generated anywhere where a member annotated with `@internal`
- is used outside of the package in which it is declared.
-
Parameters:
0: the name of the member
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a reference to a declaration
+ that is annotated with the `[internal][meta-internal]` annotation is found
+ outside the package containing the declaration.
+
+ #### Example
+
+ Given a package `p` that defines a library containing a declaration marked
+ with the `[internal][meta-internal]` annotation:
+
+ ```dart
+ %uri="package:p/src/p.dart"
+ import 'package:meta/meta.dart';
+
+ @internal
+ class C {}
+ ```
+
+ The following code produces this diagnostic because it's referencing the
+ class `C`, which isn't intended to be used outside the package `p`:
+
+ ```dart
+ import 'package:p/src/p.dart';
+
+ void f([!C!] c) {}
+ ```
+
+ #### Common fixes
+
+ Remove the reference to the internal declaration.
INVALID_USE_OF_PROTECTED_MEMBER:
problemMessage: "The member '{0}' can only be used within instance members of subclasses of '{1}'."
comment: |-
@@ -16493,8 +17627,9 @@
#### Description
The analyzer produces this diagnostic when an instance member that is
- annotated with `visibleForOverriding` is referenced outside the library in
- which it's declared for any reason other than to override it.
+ annotated with `[visibleForOverriding][meta-visibleForOverriding]` is
+ referenced outside the library in which it's declared for any reason other
+ than to override it.
#### Example
@@ -16558,8 +17693,9 @@
documentation: |-
#### Description
- The analyzer produces this diagnostic when either the `@visibleForTemplate`
- or `@visibleForTesting` annotation is applied to a non-public declaration.
+ The analyzer produces this diagnostic when either the `visibleForTemplate`
+ or `[visibleForTesting][meta-visibleForTesting]` annotation is applied to
+ a non-public declaration.
#### Example
@@ -16603,9 +17739,10 @@
#### Description
The analyzer produces this diagnostic when anything other than a public
- instance member of a class is annotated with `visibleForOverriding`.
- Because only public instance members can be overridden outside the defining
- library, there's no value to annotating any other declarations.
+ instance member of a class is annotated with
+ `[visibleForOverriding][meta-visibleForOverriding]`. Because only public
+ instance members can be overridden outside the defining library, there's
+ no value to annotating any other declarations.
#### Example
@@ -16729,9 +17866,9 @@
#### Description
The analyzer produces this diagnostic when the superclass constraint of a
- mixin is a class from a different package that was marked as `@sealed`.
- Classes that are sealed can't be extended, implemented, mixed in, or used
- as a superclass constraint.
+ mixin is a class from a different package that was marked as
+ `[sealed][meta-sealed]`. Classes that are sealed can't be extended,
+ implemented, mixed in, or used as a superclass constraint.
#### Example
@@ -16770,8 +17907,8 @@
The analyzer produces this diagnostic when an immutable class defines one
or more instance fields that aren't final. A class is immutable if it's
- marked as being immutable using the annotation `@immutable` or if it's a
- subclass of an immutable class.
+ marked as being immutable using the annotation
+ `[immutable][meta-immutable]` or if it's a subclass of an immutable class.
#### Example
@@ -16826,8 +17963,8 @@
#### Description
The analyzer produces this diagnostic when a method that overrides a method
- that is annotated as `@mustCallSuper` doesn't invoke the overridden method
- as required.
+ that is annotated as `[mustCallSuper][meta-mustCallSuper]` doesn't invoke
+ the overridden method as required.
#### Example
@@ -16892,10 +18029,10 @@
#### Description
The analyzer produces this diagnostic when a constructor that has the
- `@literal` annotation is invoked without using the `const` keyword, but all
- of the arguments to the constructor are constants. The annotation indicates
- that the constructor should be used to create a constant value whenever
- possible.
+ `[literal][meta-literal]` annotation is invoked without using the `const`
+ keyword, but all of the arguments to the constructor are constants. The
+ annotation indicates that the constructor should be used to create a
+ constant value whenever possible.
#### Example
@@ -17022,8 +18159,43 @@
NULL_CHECK_ALWAYS_FAILS:
problemMessage: "This null-check will always throw an exception because the expression will always evaluate to 'null'."
comment: |-
- This hint indicates that a null literal is null-checked with `!`, but null
- is never not null.
+ No parameters.
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when the null check operator (`!`)
+ is used on an expression whose value can only be `null`. In such a case
+ the operator always throws an exception, which likely isn't the intended
+ behavior.
+
+ #### Example
+
+ The following code produces this diagnostic because the function `g` will
+ always return `null`, which means that the null check in `f` will always
+ throw:
+
+ ```dart
+ void f() {
+ [!g()!!];
+ }
+
+ Null g() => null;
+ ```
+
+ #### Common fixes
+
+ If you intend to always throw an exception, then replace the null check
+ with an explicit `throw` expression to make the intent more clear:
+
+ ```dart
+ void f() {
+ g();
+ throw TypeError();
+ }
+
+ Null g() => null;
+ ```
OVERRIDE_ON_NON_OVERRIDING_FIELD:
sharedName: OVERRIDE_ON_NON_OVERRIDING_MEMBER
problemMessage: "The field doesn't override an inherited getter or setter."
@@ -17122,8 +18294,57 @@
problemMessage: "'{0}' is annotated with 'doNotStore' and shouldn't be returned unless '{1}' is also annotated."
correctionMessage: "Annotate '{1}' with 'doNotStore'."
comment: |-
- Users should not return values marked `@doNotStore` from functions,
- methods or getters not marked `@doNotStore`.
+ Parameters:
+ 0: the name of the annotated function being invoked
+ 1: the name of the function containing the return
+ hasPublishedDocs: true
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a value that is annotated with
+ the `[doNotStore][meta-doNotStore]` annotation is returned from a method,
+ getter, or function that doesn't have the same annotation.
+
+ #### Example
+
+ The following code produces this diagnostic because the result of invoking
+ `f` shouldn't be stored, but the function `g` isn't annotated to preserve
+ that semantic:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ @doNotStore
+ int f() => 0;
+
+ int g() => [!f()!];
+ ```
+
+ #### Common fixes
+
+ If the value that shouldn't be stored is the correct value to return, then
+ mark the function with the `[doNotStore][meta-doNotStore]` annotation:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ @doNotStore
+ int f() => 0;
+
+ @doNotStore
+ int g() => f();
+ ```
+
+ Otherwise, return a different value from the function:
+
+ ```dart
+ import 'package:meta/meta.dart';
+
+ @doNotStore
+ int f() => 0;
+
+ int g() => 0;
+ ```
SDK_VERSION_ASYNC_EXPORTED_FROM_CORE:
problemMessage: "The class '{0}' wasn't exported from 'dart:core' until version 2.1, but this code is required to be able to run on earlier versions."
correctionMessage: "Try either importing 'dart:async' or updating the SDK constraints."
@@ -17782,10 +19003,10 @@
#### Description
The analyzer produces this diagnostic when a sealed class (one that either
- has the `@sealed` annotation or inherits or mixes in a sealed class) is
- referenced in either the `extends`, `implements`, or `with` clause of a
- class or mixin declaration if the declaration isn't in the same package as
- the sealed class.
+ has the `[sealed][meta-sealed]` annotation or inherits or mixes in a
+ sealed class) is referenced in either the `extends`, `implements`, or
+ `with` clause of a class or mixin declaration if the declaration isn't in
+ the same package as the sealed class.
#### Example
@@ -18009,8 +19230,8 @@
#### Description
The analyzer produces this diagnostic when an annotation of the form
- `@UnusedResult.unless(parameterDefined: parameterName)` specifies a
- parameter name that isn't defined by the annotated function.
+ `[UseResult][meta-UseResult].unless(parameterDefined: parameterName)`
+ specifies a parameter name that isn't defined by the annotated function.
#### Example
@@ -18654,16 +19875,16 @@
#### Description
The analyzer produces this diagnostic when a function annotated with
- `useResult` is invoked, and the value returned by that function isn't used.
- The value is considered to be used if a member of the value is invoked, if
- the value is passed to another function, or if the value is assigned to a
- variable or field.
+ `[useResult][meta-useResult]` is invoked, and the value returned by that
+ function isn't used. The value is considered to be used if a member of the
+ value is invoked, if the value is passed to another function, or if the
+ value is assigned to a variable or field.
#### Example
The following code produces this diagnostic because the invocation of
`c.a()` isn't used, even though the method `a` is annotated with
- `useResult`:
+ `[useResult][meta-useResult]`:
```dart
import 'package:meta/meta.dart';
@@ -18903,6 +20124,9 @@
EMPTY_ENUM_BODY:
problemMessage: An enum must declare at least one constant name.
correctionMessage: Try declaring a constant.
+ ENUM_CONSTANT_WITH_TYPE_ARGUMENTS_WITHOUT_ARGUMENTS:
+ problemMessage: Missing arguments in enum constructor invocation.
+ correctionMessage: Try adding an argument list.
EXPECTED_CASE_OR_DEFAULT:
problemMessage: "Expected 'case' or 'default'."
correctionMessage: Try placing this code inside a case clause.
@@ -19596,7 +20820,7 @@
name: local_package
```
- If the path is wrong, then replace it with a the correct path.
+ If the path is wrong, then replace it with the correct path.
UNNECESSARY_DEV_DEPENDENCY:
problemMessage: "The dev dependency on {0} is unnecessary because there is also a normal dependency on that package."
correctionMessage: Try removing the dev dependency.
@@ -19832,7 +21056,7 @@
#### Description
The analyzer produces this diagnostic when a `switch` statement for an enum
- doesn't include an option for one of the values in the enumeration.
+ doesn't include an option for one of the values in the enum.
Note that `null` is always a possible value for an enum and therefore also
must be handled.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5994057..064de4b 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 3.2.0
+version: 3.3.1
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
@@ -7,8 +7,7 @@
sdk: '>=2.14.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^34.0.0
- cli_util: ^0.3.0
+ _fe_analyzer_shared: ^36.0.0
collection: ^1.15.0
convert: ^3.0.0
crypto: ^3.0.0
diff --git a/pkg/analyzer/test/dart/analysis/utilities_test.dart b/pkg/analyzer/test/dart/analysis/utilities_test.dart
index 36bdc90..c1aa179 100644
--- a/pkg/analyzer/test/dart/analysis/utilities_test.dart
+++ b/pkg/analyzer/test/dart/analysis/utilities_test.dart
@@ -10,10 +10,11 @@
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:path/path.dart' as p;
-import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../../util/feature_sets.dart';
+
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(UtilitiesTest);
@@ -91,10 +92,7 @@
String content = '''
int? f() => 1;
''';
- var featureSet = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.9.0'),
- flags: [],
- );
+ var featureSet = FeatureSets.language_2_9;
expect(featureSet.isEnabled(Feature.non_nullable), isFalse);
ParseStringResult result = _withMemoryFile(
content,
@@ -180,10 +178,7 @@
String content = '''
int? f() => 1;
''';
- var featureSet = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.9.0'),
- flags: [],
- );
+ var featureSet = FeatureSets.language_2_9;
expect(featureSet.isEnabled(Feature.non_nullable), isFalse);
ParseStringResult result = parseString(
content: content, throwIfDiagnostics: false, featureSet: featureSet);
diff --git a/pkg/analyzer/test/error/error_test.dart b/pkg/analyzer/test/error/error_test.dart
index 0cce128..afad0dc 100644
--- a/pkg/analyzer/test/error/error_test.dart
+++ b/pkg/analyzer/test/error/error_test.dart
@@ -37,7 +37,7 @@
if (declaration is ClassDeclaration) {
var extendsClause = declaration.extendsClause;
if (extendsClause != null &&
- extendsClause.superclass2.name.name == 'ErrorCode') {
+ extendsClause.superclass.name.name == 'ErrorCode') {
String className = declaration.name.name;
for (ClassMember member in declaration.members) {
if (member is FieldDeclaration && member.isStatic) {
diff --git a/pkg/analyzer/test/generated/class_member_parser_test.dart b/pkg/analyzer/test/generated/class_member_parser_test.dart
index 28b8faf..1917bae 100644
--- a/pkg/analyzer/test/generated/class_member_parser_test.dart
+++ b/pkg/analyzer/test/generated/class_member_parser_test.dart
@@ -23,8 +23,8 @@
implements AbstractParserViaProxyTestCase {
void test_parse_member_called_late() {
var unit = parseCompilationUnit(
- 'class C { void late() { new C().late(); } }',
- featureSet: nonNullable);
+ 'class C { void late() { new C().late(); } }',
+ );
var declaration = unit.declarations[0] as ClassDeclaration;
var method = declaration.members[0] as MethodDeclaration;
@@ -380,7 +380,6 @@
void test_parseClassMember_finalAndCovariantLateWithInitializer() {
createParser(
'covariant late final int f = 0;',
- featureSet: nonNullable,
);
parser.parseClassMember('C');
assertErrors(errors: [
@@ -1137,7 +1136,7 @@
expect(constructor.separator!.type, TokenType.EQ);
expect(constructor.initializers, isEmpty);
expect(constructor.redirectedConstructor, isNotNull);
- expect(constructor.redirectedConstructor!.type2.name.name, 'prefix.B');
+ expect(constructor.redirectedConstructor!.type.name.name, 'prefix.B');
expect(constructor.redirectedConstructor!.period!.type, TokenType.PERIOD);
expect(constructor.redirectedConstructor!.name!.name, 'foo');
expect(constructor.body, isEmptyFunctionBody);
@@ -1187,7 +1186,7 @@
expect(constructor.separator!.type, TokenType.EQ);
expect(constructor.initializers, isEmpty);
expect(constructor.redirectedConstructor, isNotNull);
- expect(constructor.redirectedConstructor!.type2.name.name, 'B');
+ expect(constructor.redirectedConstructor!.type.name.name, 'B');
expect(constructor.redirectedConstructor!.period, isNull);
expect(constructor.redirectedConstructor!.name, isNull);
expect(constructor.body, isEmptyFunctionBody);
@@ -1438,7 +1437,7 @@
}
void test_parseField_abstract() {
- createParser('abstract int i;', featureSet: nonNullable);
+ createParser('abstract int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1448,7 +1447,7 @@
}
void test_parseField_abstract_external() {
- createParser('abstract external int i;', featureSet: nonNullable);
+ createParser('abstract external int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1461,7 +1460,7 @@
}
void test_parseField_abstract_late() {
- createParser('abstract late int? i;', featureSet: nonNullable);
+ createParser('abstract late int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1473,7 +1472,7 @@
}
void test_parseField_abstract_late_final() {
- createParser('abstract late final int? i;', featureSet: nonNullable);
+ createParser('abstract late final int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1485,7 +1484,7 @@
}
void test_parseField_abstract_static() {
- createParser('abstract static int? i;', featureSet: nonNullable);
+ createParser('abstract static int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1497,7 +1496,7 @@
}
void test_parseField_const_late() {
- createParser('const late T f = 0;', featureSet: nonNullable);
+ createParser('const late T f = 0;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1523,7 +1522,7 @@
}
void test_parseField_external() {
- createParser('external int i;', featureSet: nonNullable);
+ createParser('external int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1533,7 +1532,7 @@
}
void test_parseField_external_abstract() {
- createParser('external abstract int i;', featureSet: nonNullable);
+ createParser('external abstract int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1546,7 +1545,7 @@
}
void test_parseField_external_late() {
- createParser('external late int? i;', featureSet: nonNullable);
+ createParser('external late int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1558,7 +1557,7 @@
}
void test_parseField_external_late_final() {
- createParser('external late final int? i;', featureSet: nonNullable);
+ createParser('external late final int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1570,7 +1569,7 @@
}
void test_parseField_external_static() {
- createParser('external static int? i;', featureSet: nonNullable);
+ createParser('external static int? i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1580,7 +1579,7 @@
}
void test_parseField_final_late() {
- createParser('final late T f;', featureSet: nonNullable);
+ createParser('final late T f;');
ClassMember member = parser.parseClassMember('C');
assertErrors(errors: [
expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4),
@@ -1606,7 +1605,7 @@
}
void test_parseField_late() {
- createParser('late T f;', featureSet: nonNullable);
+ createParser('late T f;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1630,7 +1629,7 @@
}
void test_parseField_late_const() {
- createParser('late const T f = 0;', featureSet: nonNullable);
+ createParser('late const T f = 0;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
@@ -1656,7 +1655,7 @@
}
void test_parseField_late_final() {
- createParser('late final T f;', featureSet: nonNullable);
+ createParser('late final T f;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1680,7 +1679,7 @@
}
void test_parseField_late_var() {
- createParser('late var f;', featureSet: nonNullable);
+ createParser('late var f;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
expect(member, isFieldDeclaration);
@@ -1703,7 +1702,7 @@
}
void test_parseField_non_abstract() {
- createParser('int i;', featureSet: nonNullable);
+ createParser('int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1713,7 +1712,7 @@
}
void test_parseField_non_external() {
- createParser('int i;', featureSet: nonNullable);
+ createParser('int i;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertNoErrors();
@@ -1723,7 +1722,7 @@
}
void test_parseField_var_late() {
- createParser('var late f;', featureSet: nonNullable);
+ createParser('var late f;');
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index e52a181..7e7f0ab 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,7 +5,9 @@
@deprecated
library analyzer.test.constant_test;
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -48,6 +50,25 @@
await _assertValueInt(74 ^ 42, "74 ^ 42");
}
+ test_conditionalExpression_unknownCondition_dynamic() async {
+ await assertErrorsInCode('''
+const bool kIsWeb = identical(0, 0.0);
+const x = kIsWeb ? a : b;
+''', [
+ error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 58,
+ 1),
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 58, 1),
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 62, 1),
+ error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 62,
+ 1),
+ ]);
+
+ var x_result = findElement.topVar('x').evaluationResult;
+ assertDartObjectText(x_result.value, r'''
+dynamic <unknown>
+''');
+ }
+
test_constructorInvocation_fieldInitializer() async {
var result = await _getExpressionValue("const C(2)", context: '''
class C {
@@ -392,6 +413,92 @@
''');
}
+ /// Enum constants can reference other constants.
+ test_object_enum_enhanced_constants() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v1(42), v2(v1);
+ final Object? a;
+ const E([this.a]);
+}
+''');
+
+ assertDartObjectText(findElement.field('v2').evaluationResult.value, r'''
+E
+ _name: String v2
+ a: E
+ _name: String v1
+ a: int 42
+ index: int 0
+ index: int 1
+''');
+ }
+
+ test_object_enum_enhanced_named() async {
+ await resolveTestCode('''
+enum E<T> {
+ v1<double>.named(10),
+ v2.named(20);
+ final T f;
+ const E.named(this.f);
+}
+
+const x1 = E.v1;
+const x2 = E.v2;
+''');
+
+ _assertTopVarConstValue('x1', r'''
+E<double>
+ _name: String v1
+ f: double 10.0
+ index: int 0
+''');
+
+ _assertTopVarConstValue('x2', r'''
+E<int>
+ _name: String v2
+ f: int 20
+ index: int 1
+''');
+ }
+
+ test_object_enum_enhanced_unnamed() async {
+ await resolveTestCode('''
+enum E<T> {
+ v1<int>(10),
+ v2(20),
+ v3('abc');
+ final T f;
+ const E(this.f);
+}
+
+const x1 = E.v1;
+const x2 = E.v2;
+const x3 = E.v3;
+''');
+
+ _assertTopVarConstValue('x1', r'''
+E<int>
+ _name: String v1
+ f: int 10
+ index: int 0
+''');
+
+ _assertTopVarConstValue('x2', r'''
+E<int>
+ _name: String v2
+ f: int 20
+ index: int 1
+''');
+
+ _assertTopVarConstValue('x3', r'''
+E<String>
+ _name: String v3
+ f: String abc
+ index: int 2
+''');
+ }
+
test_parenthesizedExpression() async {
await _assertValueString("a", "('a')");
}
@@ -521,3 +628,14 @@
return element.evaluationResult!;
}
}
+
+extension on VariableElement {
+ EvaluationResultImpl get evaluationResult {
+ var constVariable = this as ConstVariableElement;
+ var evaluationResult = constVariable.evaluationResult;
+ if (evaluationResult == null) {
+ fail('Not evaluated: $this');
+ }
+ return evaluationResult;
+ }
+}
diff --git a/pkg/analyzer/test/generated/error_parser_test.dart b/pkg/analyzer/test/generated/error_parser_test.dart
index 41a03fc..139bb79 100644
--- a/pkg/analyzer/test/generated/error_parser_test.dart
+++ b/pkg/analyzer/test/generated/error_parser_test.dart
@@ -11,6 +11,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../util/ast_type_matchers.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
main() {
@@ -1683,9 +1684,9 @@
void test_invalidTypedef() {
parseCompilationUnit("typedef var Function(var arg);", errors: [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 7),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 3),
expectedError(ParserErrorCode.VAR_RETURN_TYPE, 8, 3),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 1),
]);
@@ -2431,7 +2432,7 @@
}
void test_positionalAfterNamedArgument() {
- createParser('(x: 1, 2)');
+ createParser('(x: 1, 2)', featureSet: FeatureSets.language_2_16);
ArgumentList list = parser.parseArgumentList();
expectNotNullIfNoErrors(list);
listener.assertErrors(
diff --git a/pkg/analyzer/test/generated/expression_parser_test.dart b/pkg/analyzer/test/generated/expression_parser_test.dart
index 356ecc9..5749b4d 100644
--- a/pkg/analyzer/test/generated/expression_parser_test.dart
+++ b/pkg/analyzer/test/generated/expression_parser_test.dart
@@ -4,14 +4,12 @@
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show AbstractScanner;
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/ast.dart'
show InstanceCreationExpressionImpl;
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
-import 'package:pub_semver/src/version.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -27,11 +25,6 @@
/// Tests of the fasta parser based on [ExpressionParserTestMixin].
@reflectiveTest
class ExpressionParserTest extends FastaParserTestCase {
- final beforeUiAsCode = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.2.0'),
- flags: [],
- );
-
void test_binaryExpression_allOperators() {
// https://github.com/dart-lang/sdk/issues/36255
for (TokenType type in TokenType.all) {
@@ -671,7 +664,7 @@
expect(instanceCreation.keyword, isNotNull);
ConstructorName name = instanceCreation.constructorName;
expect(name, isNotNull);
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNull);
expect(name.name, isNull);
expect(instanceCreation.argumentList, isNotNull);
@@ -1044,7 +1037,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type.name.name, 'A.B');
expect(type.typeArguments, isNull);
expect(name.period, isNull);
@@ -1061,7 +1054,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments, isNull);
expect(name.period, isNotNull);
@@ -1079,7 +1072,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments!.arguments, hasLength(1));
expect(name.period, isNotNull);
@@ -1096,7 +1089,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments!.arguments, hasLength(1));
expect(name.period, isNull);
@@ -1113,7 +1106,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments, isNull);
expect(name.period, isNull);
@@ -1130,7 +1123,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments, isNull);
expect(name.period, isNull);
@@ -1147,7 +1140,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments!.arguments, hasLength(1));
expect(name.period, isNotNull);
@@ -1164,7 +1157,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments, isNull);
expect(name.period, isNotNull);
@@ -1182,7 +1175,7 @@
expect(expression.keyword!.keyword, Keyword.NEW);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- NamedType type = name.type2;
+ NamedType type = name.type;
expect(type, isNotNull);
expect(type.typeArguments!.arguments, hasLength(1));
expect(name.period, isNull);
@@ -1427,7 +1420,7 @@
expect(expression.keyword, isNotNull);
ConstructorName name = expression.constructorName;
expect(name, isNotNull);
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNull);
expect(name.name, isNull);
expect(expression.argumentList, isNotNull);
diff --git a/pkg/analyzer/test/generated/extension_methods_parser_test.dart b/pkg/analyzer/test/generated/extension_methods_parser_test.dart
index a7409c6..5c2a5c1 100644
--- a/pkg/analyzer/test/generated/extension_methods_parser_test.dart
+++ b/pkg/analyzer/test/generated/extension_methods_parser_test.dart
@@ -2,13 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:pub_semver/src/version.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
main() {
@@ -153,8 +152,7 @@
}
void test_parse_toplevel_member_called_late_calling_self() {
- var unit = parseCompilationUnit('void late() { late(); }',
- featureSet: nonNullable);
+ var unit = parseCompilationUnit('void late() { late(); }');
var method = unit.declarations[0] as FunctionDeclaration;
expect(method.documentationComment, isNull);
@@ -228,10 +226,7 @@
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
],
- featureSet: FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.3.0'),
- flags: [],
- ),
+ featureSet: FeatureSets.language_2_3,
);
}
diff --git a/pkg/analyzer/test/generated/formal_parameter_parser_test.dart b/pkg/analyzer/test/generated/formal_parameter_parser_test.dart
index 0b5d7b9..64b9988 100644
--- a/pkg/analyzer/test/generated/formal_parameter_parser_test.dart
+++ b/pkg/analyzer/test/generated/formal_parameter_parser_test.dart
@@ -9,6 +9,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../util/ast_type_matchers.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
import 'test_support.dart';
@@ -34,7 +35,7 @@
} else {
fail('$kind');
}
- createParser(parametersCode, featureSet: nonNullable);
+ createParser(parametersCode);
FormalParameterList list =
parserProxy.parseFormalParameterList(inFunctionType: false);
assertErrors(errors: errors);
@@ -77,7 +78,7 @@
void test_functionTyped_named_nullable_disabled() {
ParameterKind kind = ParameterKind.NAMED;
var defaultParameter = parseFormalParameter('a()? : null', kind,
- featureSet: preNonNullable,
+ featureSet: FeatureSets.language_2_9,
errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
as DefaultFormalParameter;
var functionParameter =
@@ -96,7 +97,7 @@
void test_functionTyped_positional_nullable_disabled() {
ParameterKind kind = ParameterKind.POSITIONAL;
var defaultParameter = parseFormalParameter('a()? = null', kind,
- featureSet: preNonNullable,
+ featureSet: FeatureSets.language_2_9,
errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
as DefaultFormalParameter;
var functionParameter =
@@ -115,7 +116,7 @@
void test_functionTyped_required_nullable_disabled() {
ParameterKind kind = ParameterKind.REQUIRED;
var functionParameter = parseFormalParameter('a()?', kind,
- featureSet: preNonNullable,
+ featureSet: FeatureSets.language_2_9,
errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
as FunctionTypedFormalParameter;
expect(functionParameter.returnType, isNull);
diff --git a/pkg/analyzer/test/generated/function_reference_parser_test.dart b/pkg/analyzer/test/generated/function_reference_parser_test.dart
index 2c0c918..6fd9460 100644
--- a/pkg/analyzer/test/generated/function_reference_parser_test.dart
+++ b/pkg/analyzer/test/generated/function_reference_parser_test.dart
@@ -7,6 +7,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
main() {
@@ -36,68 +37,54 @@
}
void test_feature_disabled() {
- expect_f_a_b((parseStatement('f<a, b>;', featureSet: preConstructorTearoffs)
- as ExpressionStatement)
- .expression);
+ expect_f_a_b(
+ (parseStatement('f<a, b>;', featureSet: FeatureSets.language_2_13)
+ as ExpressionStatement)
+ .expression);
listener.assertErrors([
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 6),
]);
}
void test_followingToken_accepted_closeBrace() {
- expect_f_a_b((parseExpression('{f<a, b>}', featureSet: constructorTearoffs)
- as SetOrMapLiteral)
- .elements[0]);
+ expect_f_a_b((parseExpression('{f<a, b>}') as SetOrMapLiteral).elements[0]);
}
void test_followingToken_accepted_closeBracket() {
- expect_f_a_b((parseExpression('[f<a, b>]', featureSet: constructorTearoffs)
- as ListLiteral)
- .elements[0]);
+ expect_f_a_b((parseExpression('[f<a, b>]') as ListLiteral).elements[0]);
}
void test_followingToken_accepted_closeParen() {
- expect_f_a_b((parseExpression('g(f<a, b>)', featureSet: constructorTearoffs)
- as MethodInvocation)
+ expect_f_a_b((parseExpression('g(f<a, b>)') as MethodInvocation)
.argumentList
.arguments[0]);
}
void test_followingToken_accepted_colon() {
- expect_f_a_b(
- ((parseExpression('{f<a, b>: null}', featureSet: constructorTearoffs)
- as SetOrMapLiteral)
- .elements[0] as MapLiteralEntry)
- .key);
+ expect_f_a_b(((parseExpression('{f<a, b>: null}') as SetOrMapLiteral)
+ .elements[0] as MapLiteralEntry)
+ .key);
}
void test_followingToken_accepted_comma() {
expect_f_a_b(
- (parseExpression('[f<a, b>, null]', featureSet: constructorTearoffs)
- as ListLiteral)
- .elements[0]);
+ (parseExpression('[f<a, b>, null]') as ListLiteral).elements[0]);
}
void test_followingToken_accepted_equals() {
expect_f_a_b(
- (parseExpression('f<a, b> == null', featureSet: constructorTearoffs)
- as BinaryExpression)
- .leftOperand);
+ (parseExpression('f<a, b> == null') as BinaryExpression).leftOperand);
}
void test_followingToken_accepted_not_equals() {
expect_f_a_b(
- (parseExpression('f<a, b> != null', featureSet: constructorTearoffs)
- as BinaryExpression)
- .leftOperand);
+ (parseExpression('f<a, b> != null') as BinaryExpression).leftOperand);
}
void test_followingToken_accepted_openParen() {
// This is a special case because when a `(` follows `<typeArguments>` it is
// parsed as a MethodInvocation rather than a GenericInstantiation.
- var methodInvocation =
- parseExpression('f<a, b>()', featureSet: constructorTearoffs)
- as MethodInvocation;
+ var methodInvocation = parseExpression('f<a, b>()') as MethodInvocation;
expect(methodInvocation.methodName.name, 'f');
var typeArgs = methodInvocation.typeArguments!.arguments;
expect(typeArgs, hasLength(2));
@@ -110,10 +97,9 @@
// This is a special case because `f<a, b>.methodName(...)` is parsed as an
// InstanceCreationExpression.
var instanceCreationExpression =
- parseExpression('f<a, b>.toString()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('f<a, b>.toString()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var type = constructorName.type2;
+ var type = constructorName.type;
expect((type.name as SimpleIdentifier).name, 'f');
var typeArgs = type.typeArguments!.arguments;
expect(typeArgs, hasLength(2));
@@ -125,81 +111,60 @@
void test_followingToken_accepted_period_methodInvocation_generic() {
expect_f_a_b(
- (parseExpression('f<a, b>.foo<c>()', featureSet: constructorTearoffs)
- as MethodInvocation)
- .target!);
+ (parseExpression('f<a, b>.foo<c>()') as MethodInvocation).target!);
}
void test_followingToken_accepted_period_propertyAccess() {
expect_f_a_b(
- (parseExpression('f<a, b>.hashCode', featureSet: constructorTearoffs)
- as PropertyAccess)
- .target!);
+ (parseExpression('f<a, b>.hashCode') as PropertyAccess).target!);
}
void test_followingToken_accepted_semicolon() {
- expect_f_a_b((parseStatement('f<a, b>;', featureSet: constructorTearoffs)
- as ExpressionStatement)
- .expression);
+ expect_f_a_b(
+ (parseStatement('f<a, b>;') as ExpressionStatement).expression);
listener.assertNoErrors();
}
void test_followingToken_rejected_ampersand() {
- expect_two_args(parseExpression('f(a<b,c>&d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>&d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_as() {
- expect_two_args(
- parseExpression('f(a<b,c>as)', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>as)') as MethodInvocation);
}
void test_followingToken_rejected_asterisk() {
- expect_two_args(parseExpression('f(a<b,c>*d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>*d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_bang_openBracket() {
- expect_two_args(
- parseExpression('f(a<b,c>![d])', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>![d])') as MethodInvocation);
}
void test_followingToken_rejected_bang_paren() {
- expect_two_args(
- parseExpression('f(a<b,c>!(d))', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>!(d))') as MethodInvocation);
}
void test_followingToken_rejected_bar() {
- expect_two_args(parseExpression('f(a<b,c>|d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>|d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_caret() {
- expect_two_args(parseExpression('f(a<b,c>^d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>^d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_is() {
- var methodInvocation = parseExpression('f(a<b,c> is int)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression('f(a<b,c> is int)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 2),
+ ]) as MethodInvocation;
var arguments = methodInvocation.argumentList.arguments;
expect(arguments, hasLength(2));
expect(arguments[0], TypeMatcher<BinaryExpression>());
@@ -210,22 +175,18 @@
// Note: in principle we could parse this as a generic instantiation of a
// generic instantiation, but such an expression would be meaningless so we
// reject it at the parser level.
- parseExpression('f<a><b>', featureSet: constructorTearoffs, errors: [
+ parseExpression('f<a><b>', errors: [
expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 3, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 0),
]);
}
void test_followingToken_rejected_minus() {
- expect_two_args(
- parseExpression('f(a<b,c>-d)', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>-d)') as MethodInvocation);
}
void test_followingToken_rejected_openBracket() {
- expect_two_args(
- parseExpression('f(a<b,c>[d])', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>[d])') as MethodInvocation);
}
void test_followingToken_rejected_openBracket_error() {
@@ -233,34 +194,25 @@
// `<` and `>` as delimiting type arguments, but the parser doesn't have
// enough lookahead to see that this is the only possible error-free parse;
// it commits to interpreting `<` and `>` as operators when it sees the `[`.
- expect_two_args(parseExpression('f(a<b,c>[d]>e)',
- featureSet: constructorTearoffs,
- errors: [
- expectedError(
- ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 11, 1),
- ]) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>[d]>e)', errors: [
+ expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 11, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_openBracket_unambiguous() {
- expect_two_args(
- parseExpression('f(a<b,c>[d, e])', featureSet: constructorTearoffs)
- as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>[d, e])') as MethodInvocation);
}
void test_followingToken_rejected_percent() {
- expect_two_args(parseExpression('f(a<b,c>%d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>%d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_period_period() {
- var methodInvocation = parseExpression('f(a<b,c>..toString())',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression('f(a<b,c>..toString())', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
+ ]) as MethodInvocation;
var arguments = methodInvocation.argumentList.arguments;
expect(arguments, hasLength(2));
expect(arguments[0], TypeMatcher<BinaryExpression>());
@@ -268,19 +220,15 @@
}
void test_followingToken_rejected_plus() {
- expect_two_args(parseExpression('f(a<b,c>+d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>+d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_question() {
- var methodInvocation = parseExpression('f(a<b,c> ? null : null)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression('f(a<b,c> ? null : null)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
+ ]) as MethodInvocation;
var arguments = methodInvocation.argumentList.arguments;
expect(arguments, hasLength(2));
expect(arguments[0], TypeMatcher<BinaryExpression>());
@@ -288,28 +236,22 @@
}
void test_followingToken_rejected_question_period_methodInvocation() {
- expect_two_args(parseExpression('f(a<b,c>?.toString())',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>?.toString())', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_question_period_methodInvocation_generic() {
- expect_two_args(parseExpression('f(a<b,c>?.foo<c>())',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>?.foo<c>())', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_question_period_period() {
- var methodInvocation = parseExpression('f(a<b,c>?..toString())',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
- ],
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression('f(a<b,c>?..toString())', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
+ ]) as MethodInvocation;
var arguments = methodInvocation.argumentList.arguments;
expect(arguments, hasLength(3));
expect(arguments[0], TypeMatcher<BinaryExpression>());
@@ -318,43 +260,33 @@
}
void test_followingToken_rejected_question_period_propertyAccess() {
- expect_two_args(parseExpression('f(a<b,c>?.hashCode)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>?.hashCode)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_question_question() {
- expect_two_args(parseExpression('f(a<b,c> ?? d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c> ?? d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 2),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_slash() {
- expect_two_args(parseExpression('f(a<b,c>/d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>/d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+ ]) as MethodInvocation);
}
void test_followingToken_rejected_tilde_slash() {
- expect_two_args(parseExpression('f(a<b,c>~/d)',
- errors: [
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
- ],
- featureSet: constructorTearoffs) as MethodInvocation);
+ expect_two_args(parseExpression('f(a<b,c>~/d)', errors: [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 2),
+ ]) as MethodInvocation);
}
void test_functionReference_after_indexExpression() {
// Note: this is not legal Dart, but it's important that we do error
// recovery and don't crash the parser.
- var functionReference =
- parseExpression('x[0]<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ var functionReference = parseExpression('x[0]<a, b>') as FunctionReference;
expect(functionReference.function, TypeMatcher<IndexExpression>());
var typeArgs = functionReference.typeArguments!.arguments;
expect(typeArgs, hasLength(2));
@@ -365,9 +297,7 @@
void test_functionReference_after_indexExpression_bang() {
// Note: this is not legal Dart, but it's important that we do error
// recovery and don't crash the parser.
- var functionReference =
- parseExpression('x[0]!<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ var functionReference = parseExpression('x[0]!<a, b>') as FunctionReference;
expect(functionReference.function, TypeMatcher<PostfixExpression>());
var typeArgs = functionReference.typeArguments!.arguments;
expect(typeArgs, hasLength(2));
@@ -379,8 +309,7 @@
// Note: this is not legal Dart, but it's important that we do error
// recovery and don't crash the parser.
var functionReference =
- parseExpression('x[0]()<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ parseExpression('x[0]()<a, b>') as FunctionReference;
expect(functionReference.function,
TypeMatcher<FunctionExpressionInvocation>());
var typeArgs = functionReference.typeArguments!.arguments;
@@ -392,9 +321,7 @@
void test_functionReference_after_indexExpression_nullAware() {
// Note: this is not legal Dart, but it's important that we do error
// recovery and don't crash the parser.
- var functionReference =
- parseExpression('x?[0]<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ var functionReference = parseExpression('x?[0]<a, b>') as FunctionReference;
expect(functionReference.function, TypeMatcher<IndexExpression>());
var typeArgs = functionReference.typeArguments!.arguments;
expect(typeArgs, hasLength(2));
@@ -403,9 +330,7 @@
}
void test_methodTearoff() {
- var functionReference =
- parseExpression('f().m<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ var functionReference = parseExpression('f().m<a, b>') as FunctionReference;
var function = functionReference.function as PropertyAccess;
var target = function.target as MethodInvocation;
expect(target.methodName.name, 'f');
@@ -418,8 +343,7 @@
void test_methodTearoff_cascaded() {
var cascadeExpression =
- parseExpression('f()..m<a, b>', featureSet: constructorTearoffs)
- as CascadeExpression;
+ parseExpression('f()..m<a, b>') as CascadeExpression;
var functionReference =
cascadeExpression.cascadeSections[0] as FunctionReference;
var function = functionReference.function as PropertyAccess;
@@ -433,8 +357,7 @@
void test_prefixedIdentifier() {
var functionReference =
- parseExpression('prefix.f<a, b>', featureSet: constructorTearoffs)
- as FunctionReference;
+ parseExpression('prefix.f<a, b>') as FunctionReference;
var function = functionReference.function as PrefixedIdentifier;
expect(function.prefix.name, 'prefix');
expect(function.identifier.name, 'f');
@@ -445,8 +368,8 @@
}
void test_three_identifiers() {
- var functionReference = parseExpression('prefix.ClassName.m<a, b>',
- featureSet: constructorTearoffs) as FunctionReference;
+ var functionReference =
+ parseExpression('prefix.ClassName.m<a, b>') as FunctionReference;
var function = functionReference.function as PropertyAccess;
var target = function.target as PrefixedIdentifier;
expect(target.prefix.name, 'prefix');
diff --git a/pkg/analyzer/test/generated/generic_metadata_parser_test.dart b/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
index 9e967e9..cfaf099 100644
--- a/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
+++ b/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
@@ -2,13 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
import 'test_support.dart';
@@ -30,10 +29,7 @@
return parseCompilationUnit(
content,
errors: combinedErrors,
- featureSet: FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.12.0'),
- flags: [],
- ),
+ featureSet: FeatureSets.language_2_12,
);
}
}
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 54794d7..51d910d 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -10,16 +10,82 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InvalidCodeTest);
- defineReflectiveTests(InvalidCodeWithNullSafetyTest);
+ defineReflectiveTests(InvalidCodeWithoutNullSafetyTest);
});
}
+@reflectiveTest
+class InvalidCodeTest extends PubPackageResolutionTest {
+ test_functionExpression_emptyBody() async {
+ await _assertCanBeAnalyzed(r'''
+var v = <T>();
+''');
+ }
+
+ test_functionExpressionInvocation_mustBeNullShortingTerminated() async {
+ // It looks like MethodInvocation, but because `8` is not SimpleIdentifier,
+ // we parse it as FunctionExpressionInvocation.
+ await _assertCanBeAnalyzed(r'''
+var v = a?.8(b);
+''');
+ }
+
+ test_inAnnotation_noFlow_labeledStatement() async {
+ await _assertCanBeAnalyzed('''
+@A(() { label: })
+typedef F = void Function();
+''');
+ }
+
+ test_inDefaultValue_noFlow_ifExpression() async {
+ await _assertCanBeAnalyzed('''
+typedef void F({a = [if (true) 0]});
+''');
+ }
+
+ test_inDefaultValue_noFlow_ifStatement() async {
+ await _assertCanBeAnalyzed('''
+typedef void F([a = () { if (true) 0; }]);
+''');
+ }
+
+ test_issue_40837() async {
+ await _assertCanBeAnalyzed('''
+class A {
+ const A(_);
+}
+
+@A(() => 0)
+class B {}
+''');
+ }
+
+ test_methodInvocation_ofGenericClass_generic_static_fromLegacy() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+ static void foo<T2>() {}
+}
+''');
+ await _assertCanBeAnalyzed('''
+// @dart = 2.9
+import 'a.dart';
+
+const bar = A.foo();
+''');
+ }
+
+ Future<void> _assertCanBeAnalyzed(String text) async {
+ await resolveTestCode(text);
+ assertHasTestErrors();
+ }
+}
+
/// Tests for various end-to-end cases when invalid code caused exceptions
/// in one or another Analyzer subsystem. We are not interested not in specific
/// errors generated, but we want to make sure that there is at least one,
/// and analysis finishes without exceptions.
@reflectiveTest
-class InvalidCodeTest extends PubPackageResolutionTest
+class InvalidCodeWithoutNullSafetyTest extends PubPackageResolutionTest
with WithoutNullSafetyMixin {
// TODO(https://github.com/dart-lang/sdk/issues/44666): Use null safety in
// test cases.
@@ -409,69 +475,3 @@
assertHasTestErrors();
}
}
-
-@reflectiveTest
-class InvalidCodeWithNullSafetyTest extends PubPackageResolutionTest {
- test_functionExpression_emptyBody() async {
- await _assertCanBeAnalyzed(r'''
-var v = <T>();
-''');
- }
-
- test_functionExpressionInvocation_mustBeNullShortingTerminated() async {
- // It looks like MethodInvocation, but because `8` is not SimpleIdentifier,
- // we parse it as FunctionExpressionInvocation.
- await _assertCanBeAnalyzed(r'''
-var v = a?.8(b);
-''');
- }
-
- test_inAnnotation_noFlow_labeledStatement() async {
- await _assertCanBeAnalyzed('''
-@A(() { label: })
-typedef F = void Function();
-''');
- }
-
- test_inDefaultValue_noFlow_ifExpression() async {
- await _assertCanBeAnalyzed('''
-typedef void F({a = [if (true) 0]});
-''');
- }
-
- test_inDefaultValue_noFlow_ifStatement() async {
- await _assertCanBeAnalyzed('''
-typedef void F([a = () { if (true) 0; }]);
-''');
- }
-
- test_issue_40837() async {
- await _assertCanBeAnalyzed('''
-class A {
- const A(_);
-}
-
-@A(() => 0)
-class B {}
-''');
- }
-
- test_methodInvocation_ofGenericClass_generic_static_fromLegacy() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-class A<T> {
- static void foo<T2>() {}
-}
-''');
- await _assertCanBeAnalyzed('''
-// @dart = 2.9
-import 'a.dart';
-
-const bar = A.foo();
-''');
- }
-
- Future<void> _assertCanBeAnalyzed(String text) async {
- await resolveTestCode(text);
- assertHasTestErrors();
- }
-}
diff --git a/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart b/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart
index bd35b65..7beae7f 100644
--- a/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart
+++ b/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart
@@ -7,6 +7,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
main() {
@@ -21,139 +22,128 @@
void test_constructor_field_initializer() {
// Even though `C() : this.new();` is allowed, `C() : this.new = ...;`
// should not be.
- parseCompilationUnit(
- '''
+ parseCompilationUnit('''
class C {
C() : this.new = null;
}
-''',
- featureSet: constructorTearoffs,
- errors: [
- expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 18, 4),
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 3),
- expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 23, 3),
- expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 23, 3),
- expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 27, 1),
- expectedError(ParserErrorCode.INVALID_OPERATOR, 27, 1),
- expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 27, 1),
- expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 4),
- expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 29, 4),
- expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 33, 1),
- ]);
+''', errors: [
+ expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 18, 4),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 3),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 23, 3),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 23, 3),
+ expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 27, 1),
+ expectedError(ParserErrorCode.INVALID_OPERATOR, 27, 1),
+ expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 27, 1),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 4),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 29, 4),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 33, 1),
+ ]);
}
void test_constructor_invocation_const() {
var instanceCreationExpression =
- parseExpression('const C.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('const C.new()') as InstanceCreationExpression;
// Parsing treats `new` as an identifier, so `D.new` is classified as a
// type. Resolution will change the type to `D` and the name to `new` if
// appropriate.
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'C');
expect(typeName.identifier.name, 'new');
- expect(constructorName.type2.typeArguments, isNull);
+ expect(constructorName.type.typeArguments, isNull);
expect(constructorName.name, isNull);
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_const_generic() {
var instanceCreationExpression =
- parseExpression('const C<int>.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('const C<int>.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as SimpleIdentifier;
+ var typeName = constructorName.type.name as SimpleIdentifier;
expect(typeName.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_const_prefixed() {
var instanceCreationExpression =
- parseExpression('const prefix.C.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('const prefix.C.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'C');
- expect(constructorName.type2.typeArguments, isNull);
+ expect(constructorName.type.typeArguments, isNull);
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_const_prefixed_generic() {
var instanceCreationExpression = parseExpression(
- 'const prefix.C<int>.new()',
- featureSet: constructorTearoffs) as InstanceCreationExpression;
+ 'const prefix.C<int>.new()',
+ ) as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_explicit() {
var instanceCreationExpression =
- parseExpression('new C.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('new C.new()') as InstanceCreationExpression;
// Parsing treats `new` as an identifier, so `D.new` is classified as a
// type. Resolution will change the type to `D` and the name to `new` if
// appropriate.
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'C');
expect(typeName.identifier.name, 'new');
- expect(constructorName.type2.typeArguments, isNull);
+ expect(constructorName.type.typeArguments, isNull);
expect(constructorName.name, isNull);
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_explicit_generic() {
var instanceCreationExpression =
- parseExpression('new C<int>.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('new C<int>.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as SimpleIdentifier;
+ var typeName = constructorName.type.name as SimpleIdentifier;
expect(typeName.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_explicit_prefixed() {
var instanceCreationExpression =
- parseExpression('new prefix.C.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('new prefix.C.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'C');
- expect(constructorName.type2.typeArguments, isNull);
+ expect(constructorName.type.typeArguments, isNull);
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_explicit_prefixed_generic() {
- var instanceCreationExpression = parseExpression('new prefix.C<int>.new()',
- featureSet: constructorTearoffs) as InstanceCreationExpression;
+ var instanceCreationExpression = parseExpression(
+ 'new prefix.C<int>.new()',
+ ) as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_implicit() {
- var methodInvocation =
- parseExpression('C.new()', featureSet: constructorTearoffs)
- as MethodInvocation;
+ var methodInvocation = parseExpression('C.new()') as MethodInvocation;
var target = methodInvocation.target as SimpleIdentifier;
expect(target.name, 'C');
expect(methodInvocation.methodName.name, 'new');
@@ -163,20 +153,18 @@
void test_constructor_invocation_implicit_generic() {
var instanceCreationExpression =
- parseExpression('C<int>.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('C<int>.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as SimpleIdentifier;
+ var typeName = constructorName.type.name as SimpleIdentifier;
expect(typeName.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
void test_constructor_invocation_implicit_prefixed() {
var methodInvocation =
- parseExpression('prefix.C.new()', featureSet: constructorTearoffs)
- as MethodInvocation;
+ parseExpression('prefix.C.new()') as MethodInvocation;
var target = methodInvocation.target as PrefixedIdentifier;
expect(target.prefix.name, 'prefix');
expect(target.identifier.name, 'C');
@@ -187,13 +175,12 @@
void test_constructor_invocation_implicit_prefixed_generic() {
var instanceCreationExpression =
- parseExpression('prefix.C<int>.new()', featureSet: constructorTearoffs)
- as InstanceCreationExpression;
+ parseExpression('prefix.C<int>.new()') as InstanceCreationExpression;
var constructorName = instanceCreationExpression.constructorName;
- var typeName = constructorName.type2.name as PrefixedIdentifier;
+ var typeName = constructorName.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'C');
- expect(constructorName.type2.typeArguments!.arguments, hasLength(1));
+ expect(constructorName.type.typeArguments!.arguments, hasLength(1));
expect(constructorName.name!.name, 'new');
expect(instanceCreationExpression.argumentList, isNotNull);
}
@@ -203,7 +190,7 @@
class C {
C.new();
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
@@ -216,7 +203,7 @@
factory C.new() => C._();
C._();
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members[0] as ConstructorDeclaration;
@@ -224,17 +211,13 @@
}
void test_constructor_tearoff() {
- var prefixedIdentifier =
- parseExpression('C.new', featureSet: constructorTearoffs)
- as PrefixedIdentifier;
+ var prefixedIdentifier = parseExpression('C.new') as PrefixedIdentifier;
expect(prefixedIdentifier.prefix.name, 'C');
expect(prefixedIdentifier.identifier.name, 'new');
}
void test_constructor_tearoff_generic() {
- var propertyAccess =
- parseExpression('C<int>.new', featureSet: constructorTearoffs)
- as PropertyAccess;
+ var propertyAccess = parseExpression('C<int>.new') as PropertyAccess;
var target = propertyAccess.target as FunctionReference;
var className = target.function as SimpleIdentifier;
expect(className.name, 'C');
@@ -243,8 +226,8 @@
}
void test_constructor_tearoff_generic_method_invocation() {
- var methodInvocation = parseExpression('C<int>.new.toString()',
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation =
+ parseExpression('C<int>.new.toString()') as MethodInvocation;
var target = methodInvocation.target as PropertyAccess;
var functionReference = target.target as FunctionReference;
var className = functionReference.function as SimpleIdentifier;
@@ -266,8 +249,7 @@
void test_constructor_tearoff_method_invocation() {
var methodInvocation =
- parseExpression('C.new.toString()', featureSet: constructorTearoffs)
- as MethodInvocation;
+ parseExpression('C.new.toString()') as MethodInvocation;
var target = methodInvocation.target as PrefixedIdentifier;
expect(target.prefix.name, 'C');
expect(target.identifier.name, 'new');
@@ -277,9 +259,7 @@
}
void test_constructor_tearoff_prefixed() {
- var propertyAccess =
- parseExpression('prefix.C.new', featureSet: constructorTearoffs)
- as PropertyAccess;
+ var propertyAccess = parseExpression('prefix.C.new') as PropertyAccess;
var target = propertyAccess.target as PrefixedIdentifier;
expect(target.prefix.name, 'prefix');
expect(target.identifier.name, 'C');
@@ -287,9 +267,7 @@
}
void test_constructor_tearoff_prefixed_generic() {
- var propertyAccess =
- parseExpression('prefix.C<int>.new', featureSet: constructorTearoffs)
- as PropertyAccess;
+ var propertyAccess = parseExpression('prefix.C<int>.new') as PropertyAccess;
var target = propertyAccess.target as FunctionReference;
var className = target.function as PrefixedIdentifier;
expect(className.prefix.name, 'prefix');
@@ -299,8 +277,9 @@
}
void test_constructor_tearoff_prefixed_generic_method_invocation() {
- var methodInvocation = parseExpression('prefix.C<int>.new.toString()',
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression(
+ 'prefix.C<int>.new.toString()',
+ ) as MethodInvocation;
var target = methodInvocation.target as PropertyAccess;
var functionReference = target.target as FunctionReference;
var className = functionReference.function as PrefixedIdentifier;
@@ -314,8 +293,9 @@
}
void test_constructor_tearoff_prefixed_method_invocation() {
- var methodInvocation = parseExpression('prefix.C.new.toString()',
- featureSet: constructorTearoffs) as MethodInvocation;
+ var methodInvocation = parseExpression(
+ 'prefix.C.new.toString()',
+ ) as MethodInvocation;
var target = methodInvocation.target as PropertyAccess;
var prefixedIdentifier = target.target as PrefixedIdentifier;
expect(prefixedIdentifier.prefix.name, 'prefix');
@@ -333,7 +313,7 @@
C.new();
}
''',
- featureSet: preConstructorTearoffs,
+ featureSet: FeatureSets.language_2_13,
errors: [
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 3),
]);
@@ -348,7 +328,7 @@
class C {
factory C() = D.new;
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
@@ -357,10 +337,10 @@
// type. Resolution will change the type to `D` and the name to `new` if
// appropriate.
var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
- var typeName = redirectedConstructor.type2.name as PrefixedIdentifier;
+ var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'D');
expect(typeName.identifier.name, 'new');
- expect(redirectedConstructor.type2.typeArguments, isNull);
+ expect(redirectedConstructor.type.typeArguments, isNull);
expect(redirectedConstructor.name, isNull);
}
@@ -369,15 +349,15 @@
class C {
factory C() = D<int>.new;
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
expect(constructorDeclaration.initializers, isEmpty);
var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
- var typeName = redirectedConstructor.type2.name as SimpleIdentifier;
+ var typeName = redirectedConstructor.type.name as SimpleIdentifier;
expect(typeName.name, 'D');
- expect(redirectedConstructor.type2.typeArguments!.arguments, hasLength(1));
+ expect(redirectedConstructor.type.typeArguments!.arguments, hasLength(1));
expect(redirectedConstructor.name!.name, 'new');
}
@@ -386,16 +366,16 @@
class C {
factory C() = prefix.D.new;
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
expect(constructorDeclaration.initializers, isEmpty);
var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
- var typeName = redirectedConstructor.type2.name as PrefixedIdentifier;
+ var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'D');
- expect(redirectedConstructor.type2.typeArguments, isNull);
+ expect(redirectedConstructor.type.typeArguments, isNull);
expect(redirectedConstructor.name!.name, 'new');
}
@@ -404,16 +384,16 @@
class C {
factory C() = prefix.D<int>.new;
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
expect(constructorDeclaration.initializers, isEmpty);
var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
- var typeName = redirectedConstructor.type2.name as PrefixedIdentifier;
+ var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
expect(typeName.prefix.name, 'prefix');
expect(typeName.identifier.name, 'D');
- expect(redirectedConstructor.type2.typeArguments!.arguments, hasLength(1));
+ expect(redirectedConstructor.type.typeArguments!.arguments, hasLength(1));
expect(redirectedConstructor.name!.name, 'new');
}
@@ -422,7 +402,7 @@
class C extends B {
C() : super.new();
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members.single as ConstructorDeclaration;
@@ -438,7 +418,7 @@
C.named() : this.new();
C();
}
-''', featureSet: constructorTearoffs);
+''');
var classDeclaration = unit.declarations.single as ClassDeclaration;
var constructorDeclaration =
classDeclaration.members[0] as ConstructorDeclaration;
diff --git a/pkg/analyzer/test/generated/nnbd_parser_test.dart b/pkg/analyzer/test/generated/nnbd_parser_test.dart
index 53a1772..62c9f59 100644
--- a/pkg/analyzer/test/generated/nnbd_parser_test.dart
+++ b/pkg/analyzer/test/generated/nnbd_parser_test.dart
@@ -12,6 +12,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../util/ast_type_matchers.dart';
+import '../util/feature_sets.dart';
import 'parser_test_base.dart';
import 'test_support.dart';
@@ -201,7 +202,7 @@
void test_enableNonNullable_false() {
parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
void test_for() {
@@ -227,7 +228,7 @@
void test_functionTypedFormalParameter_nullable_disabled() {
parseCompilationUnit('void f(void p()?) {}',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
test_fuzz_38113() async {
@@ -235,9 +236,9 @@
parseCompilationUnit(r'+t{{r?this}}', errors: [
expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 10, 1),
]);
}
@@ -301,7 +302,7 @@
void test_indexExpression_nullable_disabled() {
parseCompilationUnit('main(a) { a?[0]; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
void test_is_nullable() {
@@ -357,7 +358,7 @@
main() {
f(new C());
}
-''', featureSet: preNonNullable);
+''', featureSet: FeatureSets.language_2_9);
}
void test_late_as_identifier_optOut() {
@@ -547,7 +548,7 @@
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as VariableDeclarationStatement;
@@ -609,7 +610,7 @@
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
void test_nullCheckMethodResult() {
@@ -746,7 +747,7 @@
void test_nullCheckOnLiteral_disabled() {
parseCompilationUnit('f() { var x = 0!; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
void test_nullCheckOnLiteralDouble() {
@@ -825,7 +826,7 @@
void test_nullCheckOnValue_disabled() {
parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
void test_nullCheckParenthesizedExpression() {
@@ -871,6 +872,6 @@
void test_typeName_nullable_disabled() {
parseCompilationUnit('int? x;',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 3, 1)],
- featureSet: preNonNullable);
+ featureSet: FeatureSets.language_2_9);
}
}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 8891e87..bc4e648 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:test/test.dart';
@@ -21,6 +22,17 @@
@reflectiveTest
class NonErrorResolverTest extends PubPackageResolutionTest
with NonErrorResolverTestCases {
+ test_async_callback_in_with_unknown_return_type_context() async {
+ await assertNoErrorsInCode('''
+abstract class C {
+ R run<R>(R Function() action);
+}
+f(C c) {
+ c.run(() async {});
+}
+''');
+ }
+
test_await_flattened() async {
await assertNoErrorsInCode('''
Future<Future<int>>? ffi() => null;
@@ -51,6 +63,20 @@
''');
}
+ test_generic_staticParameterElement_annotation() async {
+ await assertNoErrorsInCode('''
+class C<T> {
+ const C.named({arg});
+}
+@C<bool>.named(arg: true)
+test() {}
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
test_inconsistentMethodInheritance_accessors_typeParameters1() async {
await assertNoErrorsInCode(r'''
abstract class A<E> {
@@ -94,6 +120,23 @@
''');
}
+ test_no_call_tearoff_on_promoted_var() async {
+ await assertNoErrorsInCode('''
+class B {
+ Object call() => '';
+}
+void test(Object x) {
+ x as Object Function();
+ x; // promoted
+ x = B(); // No implicit tearoff of `.call`, demotes x
+ x; // demoted
+}
+''');
+ assertType(findNode.simple('x; // promoted'), 'Object Function()');
+ assertType(findNode.assignment('x = B()'), 'B');
+ assertType(findNode.simple('x; // demoted'), 'Object');
+ }
+
test_typedef_not_function() async {
newFile('$testPackageLibPath/a.dart', content: '''
typedef F = int;
@@ -1339,6 +1382,103 @@
''');
}
+ test_generic_staticParameterElement_annotation_implicitTypeArg() async {
+ var required = isNullSafetyEnabled ? 'required' : '';
+ await assertNoErrorsInCode('''
+class C<T> {
+ const C.named({$required T arg});
+}
+@C.named(arg: true)
+test() {}
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
+ test_generic_staticParameterElement_instanceCreation_explicitNew() async {
+ await assertNoErrorsInCode('''
+class C<T> {
+ C.named({arg});
+}
+test() => new C<bool>.named(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
+ test_generic_staticParameterElement_instanceCreation_explicitNew_implicitTypeArg() async {
+ await assertNoErrorsInCode('''
+class C<T> {
+ C.named({arg});
+}
+C<bool> test() => new C.named(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
+ test_generic_staticParameterElement_instanceCreation_implicitNew() async {
+ await assertNoErrorsInCode('''
+class C<T> {
+ C.named({arg});
+}
+test() => C<bool>.named(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
+ test_generic_staticParameterElement_instanceCreation_implicitNew_implicitTypeArg() async {
+ await assertNoErrorsInCode('''
+class C<T> {
+ C.named({arg});
+}
+C<bool> test() => C.named(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ expect(y, TypeMatcher<ParameterMember>());
+ expect(y.declaration, findElement.parameter('arg'));
+ }
+
+ test_generic_staticParameterElement_methodCall() async {
+ await assertNoErrorsInCode('''
+abstract class C {
+ T method<T>({arg});
+}
+test(C c) => c.method<bool>(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ // Note: the staticParameterElement is synthetic; see
+ // https://github.com/dart-lang/sdk/issues/48500
+ expect(y, isNot(TypeMatcher<ParameterMember>()));
+ expect(y.enclosingElement, isNull);
+ }
+
+ test_generic_staticParameterElement_methodCall_implicitTypeArg() async {
+ await assertNoErrorsInCode('''
+abstract class C {
+ T method<T>({arg});
+}
+bool test(C c) => c.method<bool>(arg: true);
+''');
+ var x = findNode.namedExpression('arg: true');
+ var y = x.staticParameterElement!;
+ // Note: the staticParameterElement is synthetic; see
+ // https://github.com/dart-lang/sdk/issues/48500
+ expect(y, isNot(TypeMatcher<ParameterMember>()));
+ expect(y.enclosingElement, isNull);
+ }
+
test_genericTypeAlias_castsAndTypeChecks_hasTypeParameters() async {
await assertNoErrorsInCode('''
// @dart = 2.9
@@ -1471,6 +1611,20 @@
''');
}
+ test_implicit_call_tearoff_assignment_rhs() async {
+ await assertNoErrorsInCode('''
+class C {
+ void call() {}
+}
+test() {
+ void Function() f;
+ f = C();
+ return f;
+}
+''');
+ assertType(findNode.assignment('f = C()'), 'void Function()');
+ }
+
test_importDuplicatedLibraryName() async {
newFile("$testPackageLibPath/lib.dart", content: "library lib;");
await assertErrorsInCode(r'''
@@ -3292,4 +3446,34 @@
}
''');
}
+
+ test_yieldStar_inside_method_async() async {
+ await assertNoErrorsInCode('''
+class A {
+ m() async* {
+ yield* Stream.fromIterable([1]);
+ }
+}
+''');
+
+ assertType(
+ findNode
+ .yieldStatement('yield* Stream.fromIterable([1]);')
+ .expression
+ .staticType,
+ 'Stream<int>');
+ }
+
+ test_yieldStar_inside_method_sync() async {
+ await assertNoErrorsInCode('''
+class A {
+ m() sync* {
+ yield* [1];
+ }
+}
+''');
+
+ assertType(findNode.yieldStatement('yield* [1];').expression.staticType,
+ 'List<int>');
+ }
}
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index d588af2..1b59a3a 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -86,9 +86,10 @@
}
@override
- void beginClassDeclaration(
- Token beginToken, Token? abstractToken, Token? macroToken, Token name) {
- super.beginClassDeclaration(beginToken, abstractToken, macroToken, name);
+ void beginClassDeclaration(Token beginToken, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
+ super.beginClassDeclaration(
+ beginToken, abstractToken, macroToken, augmentToken, name);
begin('ClassDeclaration');
}
@@ -367,20 +368,22 @@
@override
void beginMethod(
DeclarationKind declarationKind,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
Token? varFinalOrConst,
Token? getOrSet,
Token name) {
- super.beginMethod(declarationKind, externalToken, staticToken,
+ super.beginMethod(declarationKind, augmentToken, externalToken, staticToken,
covariantToken, varFinalOrConst, getOrSet, name);
begin('Method');
}
@override
- void beginMixinDeclaration(Token mixinKeyword, Token name) {
- super.beginMixinDeclaration(mixinKeyword, name);
+ void beginMixinDeclaration(
+ Token? augmentToken, Token mixinKeyword, Token name) {
+ super.beginMixinDeclaration(augmentToken, mixinKeyword, name);
begin('MixinDeclaration');
}
@@ -391,10 +394,10 @@
}
@override
- void beginNamedMixinApplication(
- Token beginToken, Token? abstractToken, Token? macroToken, Token name) {
+ void beginNamedMixinApplication(Token beginToken, Token? abstractToken,
+ Token? macroToken, Token? augmentToken, Token name) {
super.beginNamedMixinApplication(
- beginToken, abstractToken, macroToken, name);
+ beginToken, abstractToken, macroToken, augmentToken, name);
begin('NamedMixinApplication');
}
@@ -477,8 +480,9 @@
}
@override
- void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
- super.beginTopLevelMethod(lastConsumed, externalToken);
+ void beginTopLevelMethod(
+ Token lastConsumed, Token? augmentToken, Token? externalToken) {
+ super.beginTopLevelMethod(lastConsumed, augmentToken, externalToken);
begin('TopLevelMethod');
}
@@ -630,6 +634,7 @@
@override
void endClassFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -642,6 +647,7 @@
expectIn('Member');
super.endClassFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -756,6 +762,7 @@
@override
void endEnumFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -767,6 +774,7 @@
expectIn('Member');
super.endEnumFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -817,6 +825,7 @@
@override
void endExtensionFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -829,6 +838,7 @@
expectIn('Member');
super.endExtensionFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
@@ -966,9 +976,9 @@
}
@override
- void endImport(Token importKeyword, Token? semicolon) {
+ void endImport(Token importKeyword, Token? augmentToken, Token? semicolon) {
end('Import');
- super.endImport(importKeyword, semicolon);
+ super.endImport(importKeyword, augmentToken, semicolon);
}
@override
@@ -1076,6 +1086,7 @@
@override
void endMixinFields(
Token? abstractToken,
+ Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
@@ -1088,6 +1099,7 @@
expectIn('Member');
super.endMixinFields(
abstractToken,
+ augmentToken,
externalToken,
staticToken,
covariantToken,
diff --git a/pkg/analyzer/test/generated/parser_test_base.dart b/pkg/analyzer/test/generated/parser_test_base.dart
index 4c2d5a6..e565e23 100644
--- a/pkg/analyzer/test/generated/parser_test_base.dart
+++ b/pkg/analyzer/test/generated/parser_test_base.dart
@@ -14,7 +14,6 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart' show CompilationUnitImpl;
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
@@ -28,6 +27,7 @@
import 'package:pub_semver/src/version.dart';
import 'package:test/test.dart';
+import '../util/feature_sets.dart';
import 'parser_fasta_listener.dart';
import 'test_support.dart';
@@ -221,25 +221,6 @@
implements AbstractParserTestCase {
static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];
- final constructorTearoffs = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.currentVersion,
- flags: [EnableString.constructor_tearoffs],
- );
-
- final controlFlow = FeatureSet.latestLanguageVersion();
-
- final spread = FeatureSet.latestLanguageVersion();
-
- final nonNullable = FeatureSet.latestLanguageVersion();
-
- final preConstructorTearoffs = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.13.0'), flags: []);
-
- final preNonNullable = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: Version.parse('2.9.0'),
- flags: [],
- );
-
late ParserProxy parserProxy;
late Token _fastaTokens;
@@ -298,10 +279,12 @@
? ScannerConfiguration.nonNullable
: ScannerConfiguration.classic,
includeComments: true);
+ var lineInfo = LineInfo(result.lineStarts);
_fastaTokens = result.tokens;
parserProxy = ParserProxy(_fastaTokens, featureSet,
allowNativeClause: allowNativeClause,
- expectedEndOffset: expectedEndOffset);
+ expectedEndOffset: expectedEndOffset,
+ lineInfo: lineInfo);
}
@override
@@ -435,8 +418,8 @@
source,
isNonNullableByDefault: false,
);
- AstBuilder astBuilder =
- AstBuilder(errorReporter, source.uri, true, featureSet!);
+ AstBuilder astBuilder = AstBuilder(errorReporter, source.uri, true,
+ featureSet!, LineInfo.fromContent(content));
fasta.Parser parser = fasta.Parser(astBuilder);
astBuilder.parser = parser;
astBuilder.allowNativeClause = allowNativeClause;
@@ -762,19 +745,26 @@
/// Creates a [ParserProxy] which is prepared to begin parsing at the given
/// Fasta token.
factory ParserProxy(Token firstToken, FeatureSet featureSet,
- {bool allowNativeClause = false, int? expectedEndOffset}) {
+ {bool allowNativeClause = false,
+ int? expectedEndOffset,
+ required LineInfo lineInfo}) {
TestSource source = TestSource();
var errorListener = GatheringErrorListener(checkRanges: true);
return ParserProxy._(firstToken, source, errorListener, featureSet,
allowNativeClause: allowNativeClause,
- expectedEndOffset: expectedEndOffset);
+ expectedEndOffset: expectedEndOffset,
+ lineInfo: lineInfo);
}
ParserProxy._(Token firstToken, Source source, this.errorListener,
FeatureSet featureSet,
- {bool allowNativeClause = false, this.expectedEndOffset})
+ {bool allowNativeClause = false,
+ this.expectedEndOffset,
+ required LineInfo lineInfo})
: super(source, errorListener,
- featureSet: featureSet, allowNativeClause: allowNativeClause) {
+ featureSet: featureSet,
+ allowNativeClause: allowNativeClause,
+ lineInfo: lineInfo) {
_eventListener = ForwardingTestListener(astBuilder);
fastaParser.listener = _eventListener;
currentToken = firstToken;
@@ -815,6 +805,7 @@
null,
null,
null,
+ null,
Token(Keyword.CLASS, 0),
astFactory.simpleIdentifier(
fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
@@ -1047,12 +1038,14 @@
fasta.ScannerResult result =
fasta.scanString(content, includeComments: true);
- listener.setLineInfo(source, result.lineStarts);
+ LineInfo lineInfo = LineInfo(result.lineStarts);
+ listener.setLineInfo(source, lineInfo);
parser = analyzer.Parser(
source,
listener,
featureSet: featureSet,
+ lineInfo: lineInfo,
);
parser.allowNativeClause = allowNativeClause;
parser.parseFunctionBodies = parseFunctionBodies;
@@ -1165,12 +1158,14 @@
fasta.ScannerResult result =
fasta.scanString(content, includeComments: true);
- listener.setLineInfo(source, result.lineStarts);
+ LineInfo lineInfo = LineInfo(result.lineStarts);
+ listener.setLineInfo(source, lineInfo);
analyzer.Parser parser = analyzer.Parser(
source,
listener,
- featureSet: FeatureSet.latestLanguageVersion(),
+ featureSet: FeatureSets.latestWithExperiments,
+ lineInfo: lineInfo,
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
@@ -1193,15 +1188,16 @@
fasta.ScannerResult result =
fasta.scanString(content, includeComments: true);
+ LineInfo lineInfo = LineInfo(result.lineStarts);
analyzer.Parser parser = analyzer.Parser(
source,
listener,
featureSet: FeatureSet.latestLanguageVersion(),
+ lineInfo: lineInfo,
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
var unit = parser.parseCompilationUnit(result.tokens);
- unit.lineInfo = LineInfo(result.lineStarts);
return unit;
}
@@ -1470,12 +1466,14 @@
fasta.ScannerResult result =
fasta.scanString(content, includeComments: true);
- listener.setLineInfo(source, result.lineStarts);
+ LineInfo lineInfo = LineInfo(result.lineStarts);
+ listener.setLineInfo(source, lineInfo);
analyzer.Parser parser = analyzer.Parser(
source,
listener,
featureSet: FeatureSet.latestLanguageVersion(),
+ lineInfo: lineInfo,
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
Statement statement = parser.parseStatement(result.tokens);
diff --git a/pkg/analyzer/test/generated/recovery_parser_test.dart b/pkg/analyzer/test/generated/recovery_parser_test.dart
index 1ae179e..196e3ca 100644
--- a/pkg/analyzer/test/generated/recovery_parser_test.dart
+++ b/pkg/analyzer/test/generated/recovery_parser_test.dart
@@ -880,9 +880,7 @@
}
void test_incompleteForEach2() {
- var statement =
- parseStatement('for (String item i) {}', featureSet: controlFlow)
- as ForStatement;
+ var statement = parseStatement('for (String item i) {}') as ForStatement;
listener.assertErrors([
expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 08cf6ac..8dff3c5 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -193,7 +193,8 @@
featureSet: featureSet,
);
Token result = scanner.tokenize();
- listener.setLineInfo(TestSource(), scanner.lineStarts);
+ LineInfo lineInfo = LineInfo(scanner.lineStarts);
+ listener.setLineInfo(TestSource(), lineInfo);
return result;
}
}
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
index e183e2a..6237d6f 100644
--- a/pkg/analyzer/test/generated/simple_parser_test.dart
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -1175,7 +1175,7 @@
ConstructorName name = parseConstructorName('A.n');
expectNotNullIfNoErrors(name);
assertNoErrors();
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNull);
expect(name.name, isNull);
}
@@ -1184,7 +1184,7 @@
ConstructorName name = parseConstructorName('p.A.n');
expectNotNullIfNoErrors(name);
assertNoErrors();
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNotNull);
expect(name.name, isNotNull);
}
@@ -1193,7 +1193,7 @@
ConstructorName name = parseConstructorName('A');
expectNotNullIfNoErrors(name);
assertNoErrors();
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNull);
expect(name.name, isNull);
}
@@ -1202,7 +1202,7 @@
ConstructorName name = parseConstructorName('p.A');
expectNotNullIfNoErrors(name);
assertNoErrors();
- expect(name.type2, isNotNull);
+ expect(name.type, isNotNull);
expect(name.period, isNull);
expect(name.name, isNull);
}
@@ -1250,8 +1250,8 @@
expectNotNullIfNoErrors(clause);
assertNoErrors();
expect(clause.extendsKeyword, isNotNull);
- expect(clause.superclass2, isNotNull);
- expect(clause.superclass2, isNamedType);
+ expect(clause.superclass, isNotNull);
+ expect(clause.superclass, isNamedType);
}
void test_parseFunctionBody_block() {
@@ -1385,7 +1385,7 @@
ImplementsClause clause = parseImplementsClause('implements A, B, C');
expectNotNullIfNoErrors(clause);
assertNoErrors();
- expect(clause.interfaces2, hasLength(3));
+ expect(clause.interfaces, hasLength(3));
expect(clause.implementsKeyword, isNotNull);
}
@@ -1393,7 +1393,7 @@
ImplementsClause clause = parseImplementsClause('implements A');
expectNotNullIfNoErrors(clause);
assertNoErrors();
- expect(clause.interfaces2, hasLength(1));
+ expect(clause.interfaces, hasLength(1));
expect(clause.implementsKeyword, isNotNull);
}
@@ -1436,7 +1436,7 @@
var creation = body.expression as InstanceCreationExpressionImpl;
expect(creation.keyword, isNull);
ConstructorName constructorName = creation.constructorName;
- expect(constructorName.type2.toSource(), 'C<E>');
+ expect(constructorName.type.toSource(), 'C<E>');
expect(constructorName.period, isNotNull);
expect(constructorName.name, isNotNull);
expect(creation.argumentList, isNotNull);
@@ -1471,7 +1471,7 @@
var creation = body.expression as InstanceCreationExpression;
expect(creation.keyword, isNull);
ConstructorName constructorName = creation.constructorName;
- expect(constructorName.type2.toSource(), 'p.C<E>');
+ expect(constructorName.type.toSource(), 'p.C<E>');
expect(constructorName.period, isNotNull);
expect(constructorName.name, isNotNull);
expect(creation.argumentList, isNotNull);
@@ -1990,8 +1990,8 @@
}
void test_parseVariableDeclaration_final_late() {
- var statement = parseStatement('final late a;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement =
+ parseStatement('final late a;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertErrors(
errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
@@ -2001,8 +2001,7 @@
}
void test_parseVariableDeclaration_late() {
- var statement = parseStatement('late a;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement = parseStatement('late a;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertErrors(errors: [
expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
@@ -2013,8 +2012,8 @@
}
void test_parseVariableDeclaration_late_final() {
- var statement = parseStatement('late final a;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement =
+ parseStatement('late final a;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'final');
@@ -2023,8 +2022,8 @@
}
void test_parseVariableDeclaration_late_init() {
- var statement = parseStatement('late a = 0;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement =
+ parseStatement('late a = 0;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertErrors(errors: [
expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
@@ -2035,8 +2034,7 @@
}
void test_parseVariableDeclaration_late_type() {
- var statement = parseStatement('late A a;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement = parseStatement('late A a;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertNoErrors();
expect(declarationList.lateKeyword, isNotNull);
@@ -2046,8 +2044,8 @@
}
void test_parseVariableDeclaration_late_var() {
- var statement = parseStatement('late var a;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement =
+ parseStatement('late var a;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertNoErrors();
expect(declarationList.lateKeyword, isNotNull);
@@ -2057,8 +2055,8 @@
}
void test_parseVariableDeclaration_late_var_init() {
- var statement = parseStatement('late var a = 0;', featureSet: nonNullable)
- as VariableDeclarationStatement;
+ var statement =
+ parseStatement('late var a = 0;') as VariableDeclarationStatement;
var declarationList = statement.variables;
assertNoErrors();
expect(declarationList.lateKeyword, isNotNull);
@@ -2081,7 +2079,7 @@
expectNotNullIfNoErrors(clause);
assertNoErrors();
expect(clause.withKeyword, isNotNull);
- expect(clause.mixinTypes2, hasLength(3));
+ expect(clause.mixinTypes, hasLength(3));
}
void test_parseWithClause_single() {
@@ -2089,7 +2087,7 @@
expectNotNullIfNoErrors(clause);
assertNoErrors();
expect(clause.withKeyword, isNotNull);
- expect(clause.mixinTypes2, hasLength(1));
+ expect(clause.mixinTypes, hasLength(1));
}
void test_typeAlias_37733() {
diff --git a/pkg/analyzer/test/generated/statement_parser_test.dart b/pkg/analyzer/test/generated/statement_parser_test.dart
index ff93ba2..702d950 100644
--- a/pkg/analyzer/test/generated/statement_parser_test.dart
+++ b/pkg/analyzer/test/generated/statement_parser_test.dart
@@ -256,7 +256,6 @@
var forStatement = parseStatement(
'await for (element in list) {}',
inAsync: true,
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNotNull);
@@ -273,7 +272,6 @@
void test_parseForStatement_each_finalExternal() {
var forStatement = parseStatement(
'for (final external in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -290,7 +288,6 @@
void test_parseForStatement_each_finalRequired() {
var forStatement = parseStatement(
'for (final required in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -325,7 +322,6 @@
void test_parseForStatement_each_genericFunctionType2() {
var forStatement = parseStatement(
'for (void Function<T>(T) element in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -359,7 +355,6 @@
void test_parseForStatement_each_identifier2() {
var forStatement = parseStatement(
'for (element in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -394,7 +389,6 @@
void test_parseForStatement_each_noType_metadata2() {
var forStatement = parseStatement(
'for (@A var element in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -429,7 +423,6 @@
void test_parseForStatement_each_type2() {
var forStatement = parseStatement(
'for (A element in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -463,7 +456,6 @@
void test_parseForStatement_each_var2() {
var forStatement = parseStatement(
'for (var element in list) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
@@ -497,7 +489,6 @@
void test_parseForStatement_loop_c2() {
var forStatement = parseStatement(
'for (; i < count;) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -533,7 +524,6 @@
void test_parseForStatement_loop_cu2() {
var forStatement = parseStatement(
'for (; i < count; i++) {}',
- featureSet: controlFlow,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -569,7 +559,6 @@
void test_parseForStatement_loop_ecu2() {
var forStatement = parseStatement(
'for (i--; i < count; i++) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -607,7 +596,6 @@
void test_parseForStatement_loop_i2() {
var forStatement = parseStatement(
'for (var i = 0;;) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -649,7 +637,6 @@
void test_parseForStatement_loop_i_withMetadata2() {
var forStatement = parseStatement(
'for (@A var i = 0;;) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -690,7 +677,6 @@
void test_parseForStatement_loop_ic2() {
var forStatement = parseStatement(
'for (var i = 0; i < count;) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -730,7 +716,6 @@
void test_parseForStatement_loop_icu2() {
var forStatement = parseStatement(
'for (var i = 0; i < count; i++) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -771,7 +756,6 @@
void test_parseForStatement_loop_iicuu2() {
var forStatement = parseStatement(
'for (int i = 0, j = count; i < j; i++, j--) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -811,7 +795,6 @@
void test_parseForStatement_loop_iu2() {
var forStatement = parseStatement(
'for (var i = 0;; i++) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -848,7 +831,6 @@
void test_parseForStatement_loop_u2() {
var forStatement = parseStatement(
'for (;; i++) {}',
- featureSet: spread,
) as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
@@ -949,7 +931,7 @@
}
void test_parseLocalVariable_external() {
- parseStatement('external int i;', featureSet: nonNullable);
+ parseStatement('external int i;');
assertErrors(errors: [
expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 8),
]);
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 4cde594..cfbc48c 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -372,7 +372,7 @@
var exp = stmt.expression as InstanceCreationExpression;
ClassElement elementB = AstFinder.getClass(unit, "B").declaredElement!;
ClassElement elementA = AstFinder.getClass(unit, "A").declaredElement!;
- expect(exp.constructorName.type2.typeOrThrow.element, elementB);
+ expect(exp.constructorName.type.typeOrThrow.element, elementB);
_isInstantiationOf(_hasElement(elementB))([
_isType(elementA.typeParameters[0]
.instantiate(nullabilitySuffix: NullabilitySuffix.star))
@@ -2372,7 +2372,7 @@
var bConstructor = b.members[0] as ConstructorDeclaration;
var redirected = bConstructor.redirectedConstructor as ConstructorName;
- var typeName = redirected.type2;
+ var typeName = redirected.type;
assertType(typeName.type, 'A<T2, U2>');
assertType(typeName.type, 'A<T2, U2>');
@@ -2408,7 +2408,7 @@
var bConstructor = b.members[0] as ConstructorDeclaration;
var redirected = bConstructor.redirectedConstructor as ConstructorName;
- var typeName = redirected.type2;
+ var typeName = redirected.type;
assertType(typeName.type, 'A<T2, U2>');
assertType(typeName.type, 'A<T2, U2>');
@@ -4087,11 +4087,15 @@
v = 3;
v; // marker
}''');
- if (hasAssignmentLeftResolution) {
- assertTypeDynamic(findNode.simple('v ='));
- } else {
- assertTypeNull(findNode.simple('v ='));
- }
+ assertAssignment(
+ findNode.assignment('= 3'),
+ readElement: null,
+ readType: null,
+ writeElement: findElement.localVar('v'),
+ writeType: 'dynamic',
+ operatorElement: null,
+ type: 'int',
+ );
assertTypeDynamic(findNode.simple('v; // marker'));
}
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 927a542..b34ef50 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -398,10 +398,9 @@
_errors.add(error);
}
- /// Set the line information associated with the given [source] to the given
- /// list of [lineStarts].
- void setLineInfo(Source source, List<int> lineStarts) {
- _lineInfoMap[source] = LineInfo(lineStarts);
+ /// Set the line information associated with the given [source] to [lineInfo].
+ void setLineInfo(Source source, LineInfo lineInfo) {
+ _lineInfoMap[source] = lineInfo;
}
}
@@ -530,9 +529,9 @@
@Deprecated('Use Source.uri instead')
@override
UriKind get uriKind {
- if (uri.scheme == 'dart') {
+ if (uri.isScheme('dart')) {
return UriKind.DART_URI;
- } else if (uri.scheme == 'package') {
+ } else if (uri.isScheme('package')) {
return UriKind.PACKAGE_URI;
}
return UriKind.FILE_URI;
diff --git a/pkg/analyzer/test/generated/top_level_parser_test.dart b/pkg/analyzer/test/generated/top_level_parser_test.dart
index bde8059..8bb9be2 100644
--- a/pkg/analyzer/test/generated/top_level_parser_test.dart
+++ b/pkg/analyzer/test/generated/top_level_parser_test.dart
@@ -398,7 +398,7 @@
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.implementsClause, isNotNull);
expect(typeAlias.implementsClause!.implementsKeyword, isNotNull);
- expect(typeAlias.implementsClause!.interfaces2.length, 1);
+ expect(typeAlias.implementsClause!.interfaces.length, 1);
expect(typeAlias.semicolon, isNotNull);
}
@@ -414,7 +414,7 @@
expect(typeAlias.typeParameters, isNull);
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.withClause.withKeyword, isNotNull);
- expect(typeAlias.withClause.mixinTypes2.length, 1);
+ expect(typeAlias.withClause.mixinTypes.length, 1);
expect(typeAlias.implementsClause, isNull);
expect(typeAlias.semicolon, isNotNull);
}
@@ -935,7 +935,7 @@
expect(typeAlias.typeParameters, isNull);
expect(typeAlias.equals, isNotNull);
expect(typeAlias.abstractKeyword, isNotNull);
- expect(typeAlias.superclass2.name.name, "S");
+ expect(typeAlias.superclass.name.name, "S");
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.implementsClause, isNull);
expect(typeAlias.semicolon, isNotNull);
@@ -953,7 +953,7 @@
expect(typeAlias.typeParameters!.typeParameters, hasLength(1));
expect(typeAlias.equals, isNotNull);
expect(typeAlias.abstractKeyword, isNull);
- expect(typeAlias.superclass2.name.name, "S");
+ expect(typeAlias.superclass.name.name, "S");
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.implementsClause, isNotNull);
expect(typeAlias.semicolon, isNotNull);
@@ -971,7 +971,7 @@
expect(typeAlias.typeParameters, isNull);
expect(typeAlias.equals, isNotNull);
expect(typeAlias.abstractKeyword, isNull);
- expect(typeAlias.superclass2.name.name, "S");
+ expect(typeAlias.superclass.name.name, "S");
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.implementsClause, isNotNull);
expect(typeAlias.semicolon, isNotNull);
@@ -989,7 +989,7 @@
expect(typeAlias.typeParameters, isNull);
expect(typeAlias.equals, isNotNull);
expect(typeAlias.abstractKeyword, isNull);
- expect(typeAlias.superclass2.name.name, "S");
+ expect(typeAlias.superclass.name.name, "S");
expect(typeAlias.withClause, isNotNull);
expect(typeAlias.implementsClause, isNull);
expect(typeAlias.semicolon, isNotNull);
@@ -1949,7 +1949,7 @@
expect(declaration.onClause, isNull);
var implementsClause = declaration.implementsClause!;
expect(implementsClause.implementsKeyword, isNotNull);
- NodeList<NamedType> interfaces = implementsClause.interfaces2;
+ NodeList<NamedType> interfaces = implementsClause.interfaces;
expect(interfaces, hasLength(1));
expect(interfaces[0].name.name, 'B');
expect(interfaces[0].typeArguments, isNull);
@@ -1971,7 +1971,7 @@
expect(declaration.onClause, isNull);
var implementsClause = declaration.implementsClause!;
expect(implementsClause.implementsKeyword, isNotNull);
- NodeList<NamedType> interfaces = implementsClause.interfaces2;
+ NodeList<NamedType> interfaces = implementsClause.interfaces;
expect(interfaces, hasLength(2));
expect(interfaces[0].name.name, 'B');
expect(interfaces[0].typeArguments!.arguments, hasLength(1));
@@ -2013,7 +2013,7 @@
expect(declaration.documentationComment, isNull);
var onClause = declaration.onClause!;
expect(onClause.onKeyword, isNotNull);
- NodeList<NamedType> constraints = onClause.superclassConstraints2;
+ NodeList<NamedType> constraints = onClause.superclassConstraints;
expect(constraints, hasLength(1));
expect(constraints[0].name.name, 'B');
expect(constraints[0].typeArguments, isNull);
@@ -2035,7 +2035,7 @@
expect(declaration.documentationComment, isNull);
var onClause = declaration.onClause!;
expect(onClause.onKeyword, isNotNull);
- NodeList<NamedType> constraints = onClause.superclassConstraints2;
+ NodeList<NamedType> constraints = onClause.superclassConstraints;
expect(constraints, hasLength(2));
expect(constraints[0].name.name, 'B');
expect(constraints[0].typeArguments, isNull);
@@ -2059,13 +2059,13 @@
expect(declaration.documentationComment, isNull);
var onClause = declaration.onClause!;
expect(onClause.onKeyword, isNotNull);
- NodeList<NamedType> constraints = onClause.superclassConstraints2;
+ NodeList<NamedType> constraints = onClause.superclassConstraints;
expect(constraints, hasLength(1));
expect(constraints[0].name.name, 'B');
expect(constraints[0].typeArguments, isNull);
var implementsClause = declaration.implementsClause!;
expect(implementsClause.implementsKeyword, isNotNull);
- NodeList<NamedType> interfaces = implementsClause.interfaces2;
+ NodeList<NamedType> interfaces = implementsClause.interfaces;
expect(interfaces, hasLength(1));
expect(interfaces[0].name.name, 'C');
expect(interfaces[0].typeArguments, isNull);
@@ -2139,34 +2139,29 @@
}
void test_parseTopLevelVariable_external() {
- var unit = parseCompilationUnit('external int i;', featureSet: nonNullable);
+ var unit = parseCompilationUnit('external int i;');
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
expect(declaration.externalKeyword, isNotNull);
}
void test_parseTopLevelVariable_external_late() {
- var unit = parseCompilationUnit('external late int? i;',
- featureSet: nonNullable,
- errors: [
- expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
- ]);
+ var unit = parseCompilationUnit('external late int? i;', errors: [
+ expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+ ]);
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
expect(declaration.externalKeyword, isNotNull);
}
void test_parseTopLevelVariable_external_late_final() {
- var unit = parseCompilationUnit('external late final int? i;',
- featureSet: nonNullable,
- errors: [
- expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
- ]);
+ var unit = parseCompilationUnit('external late final int? i;', errors: [
+ expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+ ]);
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
expect(declaration.externalKeyword, isNotNull);
}
void test_parseTopLevelVariable_final_late() {
var unit = parseCompilationUnit('final late a;',
- featureSet: nonNullable,
errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var declarationList = declaration.variables;
@@ -2176,11 +2171,9 @@
}
void test_parseTopLevelVariable_late() {
- var unit = parseCompilationUnit('late a;',
- featureSet: nonNullable,
- errors: [
- expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
- ]);
+ var unit = parseCompilationUnit('late a;', errors: [
+ expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+ ]);
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var declarationList = declaration.variables;
expect(declarationList.keyword, isNull);
@@ -2189,7 +2182,7 @@
}
void test_parseTopLevelVariable_late_final() {
- var unit = parseCompilationUnit('late final a;', featureSet: nonNullable);
+ var unit = parseCompilationUnit('late final a;');
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var declarationList = declaration.variables;
expect(declarationList.keyword!.lexeme, 'final');
@@ -2198,11 +2191,9 @@
}
void test_parseTopLevelVariable_late_init() {
- var unit = parseCompilationUnit('late a = 0;',
- featureSet: nonNullable,
- errors: [
- expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
- ]);
+ var unit = parseCompilationUnit('late a = 0;', errors: [
+ expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+ ]);
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var declarationList = declaration.variables;
expect(declarationList.keyword, isNull);
@@ -2211,7 +2202,7 @@
}
void test_parseTopLevelVariable_late_type() {
- var unit = parseCompilationUnit('late A a;', featureSet: nonNullable);
+ var unit = parseCompilationUnit('late A a;');
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var declarationList = declaration.variables;
expect(declarationList.lateKeyword, isNotNull);
@@ -2221,7 +2212,7 @@
}
void test_parseTopLevelVariable_non_external() {
- var unit = parseCompilationUnit('int i;', featureSet: nonNullable);
+ var unit = parseCompilationUnit('int i;');
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
expect(declaration.externalKeyword, isNull);
}
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index dfaa5e0..4db863b 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -2,11 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
@@ -14,6 +12,8 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/feature_sets.dart';
+
main() {
defineReflectiveSuite(() {
defineReflectiveTests(BooleanArrayTest);
@@ -457,7 +457,7 @@
source: findNode.classTypeAlias('B<U>'),
childAccessors: [
(node) => node.documentationComment!,
- (node) => node.superclass2,
+ (node) => node.superclass,
(node) => node.implementsClause!,
(node) => node.name,
(node) => node.typeParameters!,
@@ -604,7 +604,7 @@
destination: findNode.constructorName('A.foo'),
source: findNode.constructorName('B.bar'),
childAccessors: [
- (node) => node.type2,
+ (node) => node.type,
(node) => node.name!,
],
);
@@ -797,7 +797,7 @@
destination: findNode.extendsClause('A0'),
source: findNode.extendsClause('B0'),
childAccessors: [
- (node) => node.superclass2,
+ (node) => node.superclass,
],
);
}
@@ -1122,8 +1122,8 @@
var node = findNode.implementsClause('implements');
_assertReplaceInList(
destination: node,
- child: node.interfaces2[0],
- replacement: node.interfaces2[1],
+ child: node.interfaces[0],
+ replacement: node.interfaces[1],
);
}
@@ -1950,8 +1950,8 @@
var node = findNode.withClause('with');
_assertReplaceInList(
destination: node,
- child: node.mixinTypes2[0],
- replacement: node.mixinTypes2[1],
+ child: node.mixinTypes[0],
+ replacement: node.mixinTypes[1],
);
}
@@ -2041,13 +2041,7 @@
FindNode _parseStringToFindNode(String content) {
var parseResult = parseString(
content: content,
- featureSet: FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.currentVersion,
- flags: [
- Feature.enhanced_enums.enableString,
- Feature.super_parameters.enableString,
- ],
- ),
+ featureSet: FeatureSets.latestWithExperiments,
);
return FindNode(parseResult.content, parseResult.unit);
}
diff --git a/pkg/analyzer/test/id_tests/inferred_type_arguments_test.dart b/pkg/analyzer/test/id_tests/inferred_type_arguments_test.dart
index 7401b6c..2ba48a6 100644
--- a/pkg/analyzer/test/id_tests/inferred_type_arguments_test.dart
+++ b/pkg/analyzer/test/id_tests/inferred_type_arguments_test.dart
@@ -55,9 +55,9 @@
TypeArgumentList? typeArguments;
List<DartType> typeArgumentTypes;
if (node is InstanceCreationExpression) {
- typeArguments = node.constructorName.type2.typeArguments;
+ typeArguments = node.constructorName.type.typeArguments;
typeArgumentTypes =
- (node.constructorName.type2.type as InterfaceType).typeArguments;
+ (node.constructorName.type.type as InterfaceType).typeArguments;
} else if (node is InvocationExpression) {
typeArguments = node.typeArguments;
typeArgumentTypes = node.typeArgumentTypes!;
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index d56b63b..ebf8025 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -670,7 +670,7 @@
var constructorName = constC.constructorName;
expect(constructorName.staticElement, constructorC);
- expect(constructorName.type2.type, interfaceTypeNone(elementC));
+ expect(constructorName.type.type, interfaceTypeNone(elementC));
}
test_annotation_unprefixed_topLevelVariable() async {
@@ -796,11 +796,20 @@
}
''');
- assertBinaryExpression(
- findNode.binary('>>> 3'),
- element: findElement.method('>>>'),
- type: 'A',
- );
+ assertResolvedNodeText(findNode.binary('>>> 3'), r'''
+BinaryExpression
+ leftOperand: SimpleIdentifier
+ token: a
+ staticElement: a@54
+ staticType: A
+ operator: >>>
+ rightOperand: IntegerLiteral
+ literal: 3
+ staticType: int
+ staticElement: self::@class::A::@method::>>>
+ staticInvokeType: A Function(int)
+ staticType: A
+''');
}
test_binaryExpression_ifNull() async {
@@ -1309,7 +1318,7 @@
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(aUnnamed));
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, interfaceTypeNone(aElement));
var identifier = namedType.name as SimpleIdentifier;
@@ -1329,7 +1338,7 @@
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(aNamed));
- var namedType = constructorName.type2;
+ var namedType = constructorName.type;
expect(namedType.type, interfaceTypeNone(aElement));
var identifier = namedType.name as SimpleIdentifier;
@@ -1378,7 +1387,7 @@
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(actualMember));
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, auType);
var identifier = namedType.name as SimpleIdentifier;
@@ -1400,7 +1409,7 @@
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(actualMember));
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, auType);
var identifier = namedType.name as SimpleIdentifier;
@@ -1522,24 +1531,13 @@
{
var prefixed = findNode.prefixed('a.v = 1;');
- if (hasAssignmentLeftResolution) {
- assertElement(prefixed, v.setter);
- assertType(prefixed, 'int');
- } else {
- assertElementNull(prefixed);
- assertTypeNull(prefixed);
- }
+ assertElementNull(prefixed);
+ assertTypeNull(prefixed);
assertElement(prefixed.prefix, import.prefix);
assertType(prefixed.prefix, null);
- if (hasAssignmentLeftResolution) {
- assertElement(prefixed.identifier, v.setter);
- assertType(prefixed.identifier, 'int');
- } else {
- assertElementNull(prefixed.identifier);
- assertTypeNull(prefixed.identifier);
- }
+ assertUnresolvedSimpleIdentifier(prefixed.identifier);
}
}
@@ -1696,9 +1694,6 @@
''');
await resolveTestFile();
- var enumNode = result.unit.declarations[0] as EnumDeclaration;
- ClassElement enumElement = enumNode.declaredElement!;
-
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as ExpressionStatement;
@@ -1707,7 +1702,7 @@
var methodElement = invocation.methodName.staticElement as MethodElement;
expect(methodElement.name, 'toString');
- expect(methodElement.enclosingElement, same(enumElement));
+ expect(methodElement.enclosingElement, same(objectElement));
}
test_error_unresolvedTypeAnnotation() async {
@@ -1770,13 +1765,7 @@
{
var fRef = findNode.simple('f = 1;');
- if (hasAssignmentLeftResolution) {
- assertMember(fRef, findElement.setter('f'), {'T': 'int'});
- assertType(fRef, 'int');
- } else {
- assertElementNull(fRef);
- assertTypeNull(fRef);
- }
+ assertUnresolvedSimpleIdentifier(fRef);
}
}
@@ -2069,7 +2058,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
@@ -2087,7 +2076,7 @@
expect(constructorName.staticElement, namedConstructor);
expect(constructorName.name!.staticType, isNull);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
@@ -2122,7 +2111,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, constructorElement);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
@@ -2163,7 +2152,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
@@ -2185,7 +2174,7 @@
expect(constructorName.name!.staticElement, namedConstructor);
expect(constructorName.name!.staticType, isNull);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
@@ -2237,7 +2226,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as PrefixedIdentifier;
@@ -2267,7 +2256,7 @@
expect(constructorName.name!.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as PrefixedIdentifier;
@@ -2297,7 +2286,7 @@
expect(constructorName.name!.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
@@ -2352,7 +2341,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
@@ -2374,7 +2363,7 @@
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
@@ -2399,7 +2388,7 @@
expect(constructorName.name!.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
@@ -2422,7 +2411,7 @@
expect(constructorName.name!.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
@@ -2454,7 +2443,7 @@
assertMember(creation, defaultConstructor, {'K': 'int', 'V': 'double'});
assertType(creation, 'C<int, double>');
- var namedType = creation.constructorName.type2;
+ var namedType = creation.constructorName.type;
assertNamedType(namedType, cElement, 'C<int, double>');
var typeArguments = namedType.typeArguments!.arguments;
@@ -2473,7 +2462,7 @@
assertMember(creation, namedConstructor, {'K': 'num', 'V': 'String'});
assertType(creation, 'C<num, String>');
- var namedType = creation.constructorName.type2;
+ var namedType = creation.constructorName.type;
assertNamedType(namedType, cElement, 'C<num, String>');
var typeArguments = namedType.typeArguments!.arguments;
@@ -3069,7 +3058,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
- NamedType type = constructorName.type2;
+ NamedType type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertTypeNull(type.name);
@@ -3086,7 +3075,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name!.name, 'named');
- NamedType type = constructorName.type2;
+ NamedType type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertType(type.name, 'C<bool>');
@@ -3103,7 +3092,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name!.name, 'named2');
- NamedType type = constructorName.type2;
+ NamedType type = constructorName.type;
assertTypeArguments(type.typeArguments!, [doubleType]);
assertElement(type.name, c);
assertType(type.name, 'C<double>');
@@ -5614,7 +5603,7 @@
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
- assertNamedType(creation.constructorName.type2, c, 'C');
+ assertNamedType(creation.constructorName.type, c, 'C');
}
{
@@ -5623,7 +5612,7 @@
assertElement(creation, namedConstructor);
assertType(creation, 'C');
- assertNamedType(creation.constructorName.type2, c, 'C');
+ assertNamedType(creation.constructorName.type, c, 'C');
assertElement(creation.constructorName.name, namedConstructor);
}
}
@@ -5650,7 +5639,7 @@
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
- assertNamedType(creation.constructorName.type2, c, 'C',
+ assertNamedType(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix);
}
@@ -5660,7 +5649,7 @@
assertElement(creation, namedConstructor);
assertType(creation, 'C');
- assertNamedType(creation.constructorName.type2, c, 'C',
+ assertNamedType(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix);
assertElement(creation.constructorName.name, namedConstructor);
}
@@ -5684,7 +5673,7 @@
assertMember(creation, c.unnamedConstructor!, {'T': 'int'});
assertType(creation, 'C<int>');
- assertNamedType(creation.constructorName.type2, c, 'C<int>');
+ assertNamedType(creation.constructorName.type, c, 'C<int>');
assertNamedType(findNode.namedType('int>'), intElement, 'int');
}
@@ -5694,7 +5683,7 @@
assertMember(creation, namedConstructor, {'T': 'String'});
assertType(creation, 'C<String>');
- assertNamedType(creation.constructorName.type2, c, 'C<String>');
+ assertNamedType(creation.constructorName.type, c, 'C<String>');
assertNamedType(findNode.namedType('String>'), stringElement, 'String');
assertMember(
@@ -5944,13 +5933,7 @@
await resolveTestFile();
var xRef = findNode.simple('x ++');
- if (hasAssignmentLeftResolution) {
- assertElement(xRef, findElement.parameter('x'));
- assertType(xRef, 'int');
- } else {
- // assertElementNull(xRef);
- assertTypeNull(xRef);
- }
+ assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_postfixExpression_local() async {
@@ -5982,13 +5965,7 @@
expect(postfix.staticType, typeProvider.intType);
var operand = postfix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- expect(operand.staticElement, same(v));
- expect(operand.staticType, typeProvider.intType);
- } else {
- // expect(operand.staticElement, same(v));
- expect(operand.staticType, isNull);
- }
+ assertUnresolvedSimpleIdentifier(operand, disableElementCheck: true);
}
}
@@ -6004,11 +5981,6 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit;
-
- var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
- ClassElement cClassElement = cClassDeclaration.declaredElement!;
- FieldElement fElement = cClassElement.getField('f')!;
List<Statement> mainStatements = _getMainStatements(result);
@@ -6021,20 +5993,10 @@
expect(postfix.staticType, typeProvider.intType);
var propertyAccess = postfix.operand as PropertyAccess;
- if (hasAssignmentLeftResolution) {
- expect(propertyAccess.staticType, typeProvider.intType);
- } else {
- assertTypeNull(propertyAccess);
- }
+ assertUnresolvedPropertyAccess(propertyAccess);
SimpleIdentifier propertyName = propertyAccess.propertyName;
- if (hasAssignmentLeftResolution) {
- expect(propertyName.staticElement, same(fElement.setter));
- expect(propertyName.staticType, typeProvider.intType);
- } else {
- assertElementNull(propertyName);
- assertTypeNull(propertyName);
- }
+ assertUnresolvedSimpleIdentifier(propertyName);
}
}
@@ -6060,13 +6022,7 @@
await resolveTestFile();
var xRef = findNode.simple('x++');
- if (hasAssignmentLeftResolution) {
- assertElement(xRef, findElement.parameter('x'));
- assertType(xRef, 'int');
- } else {
- // assertElementNull(xRef);
- assertTypeNull(xRef);
- }
+ assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_prefix_increment_of_prefix_increment() async {
@@ -6078,13 +6034,7 @@
await resolveTestFile();
var xRef = findNode.simple('x;');
- if (hasAssignmentLeftResolution) {
- assertElement(xRef, findElement.parameter('x'));
- assertType(xRef, 'int');
- } else {
- // assertElementNull(xRef);
- assertTypeNull(xRef);
- }
+ assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_prefixedIdentifier_classInstance_instanceField() async {
@@ -6268,14 +6218,7 @@
var assignment = statement.expression as AssignmentExpression;
var left = assignment.leftHandSide as PrefixedIdentifier;
assertPrefix(left.prefix);
-
- if (hasAssignmentLeftResolution) {
- expect(left.identifier.staticElement, same(mySetter));
- expect(left.identifier.staticType, typeProvider.intType);
- } else {
- assertElementNull(left.identifier);
- assertTypeNull(left.identifier);
- }
+ assertUnresolvedSimpleIdentifier(left.identifier);
}
}
@@ -6309,13 +6252,7 @@
expect(prefix.staticType, typeProvider.intType);
var operand = prefix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- expect(operand.staticElement, same(v));
- expect(operand.staticType, typeProvider.intType);
- } else {
- // assertElementNull(operand);
- assertTypeNull(operand);
- }
+ assertUnresolvedSimpleIdentifier(operand, disableElementCheck: true);
}
{
@@ -6396,20 +6333,10 @@
expect(prefix.staticType, typeProvider.intType);
var propertyAccess = prefix.operand as PropertyAccess;
- if (hasAssignmentLeftResolution) {
- expect(propertyAccess.staticType, typeProvider.intType);
- } else {
- assertTypeNull(propertyAccess);
- }
+ assertUnresolvedPropertyAccess(propertyAccess);
SimpleIdentifier propertyName = propertyAccess.propertyName;
- if (hasAssignmentLeftResolution) {
- expect(propertyName.staticElement, same(fElement.setter));
- expect(propertyName.staticType, typeProvider.intType);
- } else {
- assertElementNull(propertyName.staticElement);
- assertTypeNull(propertyName);
- }
+ assertUnresolvedSimpleIdentifier(propertyName);
}
{
@@ -6635,8 +6562,6 @@
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
aNode.members[1].declaredElement as PropertyAccessorElement;
- var setterElement =
- aNode.members[2].declaredElement as PropertyAccessorElement;
var operatorElement = aNode.members[3].declaredElement as MethodElement;
var testNode = bNode.members[0] as MethodDeclaration;
@@ -6694,13 +6619,7 @@
var assignment = statement.expression as AssignmentExpression;
var identifier = assignment.leftHandSide as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- expect(identifier.staticElement, same(setterElement));
- expect(identifier.staticType, typeProvider.intType);
- } else {
- assertElementNull(identifier);
- assertTypeNull(identifier);
- }
+ assertUnresolvedSimpleIdentifier(identifier);
}
// this.setter = 4;
@@ -6714,13 +6633,7 @@
expect(
target.staticType, interfaceTypeNone(bNode.declaredElement!)); // raw
- if (hasAssignmentLeftResolution) {
- expect(propertyAccess.propertyName.staticElement, same(setterElement));
- expect(propertyAccess.propertyName.staticType, typeProvider.intType);
- } else {
- assertElementNull(propertyAccess.propertyName);
- assertTypeNull(propertyAccess.propertyName);
- }
+ assertUnresolvedSimpleIdentifier(propertyAccess.propertyName);
}
// super + 5;
@@ -6763,8 +6676,6 @@
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
aNode.members[1].declaredElement as PropertyAccessorElement;
- var setterElement =
- aNode.members[2].declaredElement as PropertyAccessorElement;
var operatorElement = aNode.members[3].declaredElement as MethodElement;
var testNode = aNode.members[4] as MethodDeclaration;
@@ -6823,13 +6734,7 @@
var assignment = statement.expression as AssignmentExpression;
var identifier = assignment.leftHandSide as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- expect(identifier.staticElement, same(setterElement));
- expect(identifier.staticType, typeProvider.intType);
- } else {
- assertElementNull(identifier);
- assertTypeNull(identifier);
- }
+ assertUnresolvedSimpleIdentifier(identifier);
}
// this.setter = 4;
@@ -6842,13 +6747,7 @@
var target = propertyAccess.target as ThisExpression;
expect(target.staticType, thisTypeA); // raw
- if (hasAssignmentLeftResolution) {
- expect(propertyAccess.propertyName.staticElement, same(setterElement));
- expect(propertyAccess.propertyName.staticType, typeProvider.intType);
- } else {
- assertElementNull(propertyAccess.propertyName);
- assertTypeNull(propertyAccess.propertyName);
- }
+ assertUnresolvedSimpleIdentifier(propertyAccess.propertyName);
}
// this + 5;
@@ -6941,7 +6840,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType superClass = dNode.extendsClause!.superclass2;
+ NamedType superClass = dNode.extendsClause!.superclass;
expect(superClass.type, expectedType);
var identifier = superClass.name as SimpleIdentifier;
@@ -6955,7 +6854,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType mixinType = dNode.withClause!.mixinTypes2[0];
+ NamedType mixinType = dNode.withClause!.mixinTypes[0];
expect(mixinType.type, expectedType);
var identifier = mixinType.name as SimpleIdentifier;
@@ -6969,7 +6868,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType implementedType = dNode.implementsClause!.interfaces2[0];
+ NamedType implementedType = dNode.implementsClause!.interfaces[0];
expect(implementedType.type, expectedType);
var identifier = implementedType.name as SimpleIdentifier;
@@ -7010,7 +6909,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType superClass = dNode.superclass2;
+ NamedType superClass = dNode.superclass;
expect(superClass.type, expectedType);
var identifier = superClass.name as SimpleIdentifier;
@@ -7024,7 +6923,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType mixinType = dNode.withClause.mixinTypes2[0];
+ NamedType mixinType = dNode.withClause.mixinTypes[0];
expect(mixinType.type, expectedType);
var identifier = mixinType.name as SimpleIdentifier;
@@ -7038,7 +6937,7 @@
nullabilitySuffix: NullabilitySuffix.none,
);
- NamedType interfaceType = dNode.implementsClause!.interfaces2[0];
+ NamedType interfaceType = dNode.implementsClause!.interfaces[0];
expect(interfaceType.type, expectedType);
var identifier = interfaceType.name as SimpleIdentifier;
@@ -7943,7 +7842,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typeIdentifier = namedType.name as SimpleIdentifier;
@@ -7975,7 +7874,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
@@ -8019,7 +7918,7 @@
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
@@ -8057,7 +7956,7 @@
ConstructorName constructorName = creation.constructorName;
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
@@ -8103,7 +8002,7 @@
ConstructorName constructorName = creation.constructorName;
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
@@ -8150,7 +8049,7 @@
ConstructorName constructorName = creation.constructorName;
- NamedType namedType = constructorName.type2;
+ NamedType namedType = constructorName.type;
assertType(namedType, 'Random');
var typePrefixed = namedType.name as PrefixedIdentifier;
@@ -8274,13 +8173,7 @@
assertTypeDynamic(postfix);
var aRef = postfix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- assertElementNull(aRef);
- assertTypeDynamic(aRef);
- } else {
- assertElementNull(aRef);
- assertTypeNull(aRef);
- }
+ assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_postfix_operator() async {
@@ -8299,13 +8192,7 @@
assertType(postfix, 'A');
var aRef = postfix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- assertElement(aRef, findElement.topSet('a'));
- assertType(aRef, 'A');
- } else {
- assertElementNull(aRef);
- assertTypeNull(aRef);
- }
+ assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefix_operand() async {
@@ -8322,13 +8209,7 @@
assertTypeDynamic(prefix);
var aRef = prefix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- assertElementNull(aRef);
- assertTypeDynamic(aRef);
- } else {
- assertElementNull(aRef);
- assertTypeNull(aRef);
- }
+ assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefix_operator() async {
@@ -8347,13 +8228,7 @@
assertTypeDynamic(prefix);
var aRef = prefix.operand as SimpleIdentifier;
- if (hasAssignmentLeftResolution) {
- assertElement(aRef, findElement.topSet('a'));
- assertType(aRef, 'A');
- } else {
- assertElementNull(aRef);
- assertTypeNull(aRef);
- }
+ assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefixedIdentifier_identifier() async {
@@ -8619,7 +8494,7 @@
var constructorElement = classElement.unnamedConstructor;
expect(constructorName.staticElement, constructorElement);
- var namedType = constructorName.type2;
+ var namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 807866c..afefd83 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -3436,17 +3436,11 @@
}
extension on AnalysisDriver {
- Set<String> get loadedLibraryUriSet {
- var elementFactory = this.test.libraryContext!.elementFactory;
- var libraryReferences = elementFactory.rootReference.children;
- return libraryReferences.map((e) => e.name).toSet();
- }
-
void assertLoadedLibraryUriSet({
Iterable<String>? included,
Iterable<String>? excluded,
}) {
- var uriSet = loadedLibraryUriSet;
+ var uriSet = this.test.loadedLibraryUriSet;
if (included != null) {
expect(uriSet, containsAll(included));
}
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 539ff59..3cc2617 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -200,6 +200,40 @@
unorderedEquals(['a', 'b', 'd', 'e', 'f', 'g']));
}
+ test_definedClassMemberNames_enum() {
+ String path = convertPath('/aaa/lib/a.dart');
+ newFile(path, content: r'''
+enum E1 {
+ v1;
+ int field1, field2;
+ const E1();
+ const E1.namedConstructor();
+ void method() {}
+ get getter => 0;
+ set setter(_) {}
+}
+
+enum E2 {
+ v2;
+ get getter2 => 0;
+}
+''');
+ FileState file = fileSystemState.getFileForPath(path);
+ expect(
+ file.definedClassMemberNames,
+ unorderedEquals([
+ 'v1',
+ 'field1',
+ 'field2',
+ 'method',
+ 'getter',
+ 'setter',
+ 'v2',
+ 'getter2',
+ ]),
+ );
+ }
+
test_definedTopLevelNames() {
String path = convertPath('/aaa/lib/a.dart');
newFile(path, content: r'''
@@ -439,7 +473,7 @@
);
}
- test_getFilesSubtypingName() {
+ test_getFilesSubtypingName_class() {
String a = convertPath('/a.dart');
String b = convertPath('/b.dart');
@@ -476,6 +510,75 @@
);
}
+ test_getFilesSubtypingName_enum_implements() {
+ String a = convertPath('/a.dart');
+ String b = convertPath('/b.dart');
+
+ newFile(a, content: r'''
+class A {}
+enum E1 implements A {
+ v
+}
+''');
+ newFile(b, content: r'''
+class A {}
+enum E2 implements A {
+ v
+}
+''');
+
+ FileState aFile = fileSystemState.getFileForPath(a);
+ FileState bFile = fileSystemState.getFileForPath(b);
+
+ expect(
+ fileSystemState.getFilesSubtypingName('A'),
+ unorderedEquals([aFile, bFile]),
+ );
+
+ // Change b.dart so that it does not subtype A.
+ newFile(b, content: r'''
+class C {}
+enum E2 implements C {
+ v
+}
+''');
+ bFile.refresh();
+ expect(
+ fileSystemState.getFilesSubtypingName('A'),
+ unorderedEquals([aFile]),
+ );
+ expect(
+ fileSystemState.getFilesSubtypingName('C'),
+ unorderedEquals([bFile]),
+ );
+ }
+
+ test_getFilesSubtypingName_enum_with() {
+ String a = convertPath('/a.dart');
+ String b = convertPath('/b.dart');
+
+ newFile(a, content: r'''
+mixin M {}
+enum E1 with M {
+ v
+}
+''');
+ newFile(b, content: r'''
+mixin M {}
+enum E2 with M {
+ v
+}
+''');
+
+ FileState aFile = fileSystemState.getFileForPath(a);
+ FileState bFile = fileSystemState.getFileForPath(b);
+
+ expect(
+ fileSystemState.getFilesSubtypingName('M'),
+ unorderedEquals([aFile, bFile]),
+ );
+ }
+
test_hasUri() {
Uri uri = Uri.parse('package:aaa/foo.dart');
String templatePath = convertPath('/aaa/lib/foo.dart');
@@ -783,7 +886,7 @@
if (file is LibraryCycle) {
return !file.libraries.any((file) => file.uri.isScheme('dart'));
} else if (file is FileState) {
- return file.uri.scheme != 'dart';
+ return !file.uri.isScheme('dart');
} else if (file == null) {
return true;
} else {
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 9375dc1..4c31935 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -215,6 +215,19 @@
..isReferencedAt('B; // 3', false);
}
+ test_isImplementedBy_enum() async {
+ await _indexTestUnit('''
+class A {} // 1
+enum E implements A { // 2
+ v;
+}
+''');
+ ClassElement elementA = findElement.class_('A');
+ assertThat(elementA)
+ ..isImplementedAt('A { // 2', false)
+ ..isReferencedAt('A { // 2', false);
+ }
+
test_isImplementedBy_MixinDeclaration_implementsClause() async {
await _indexTestUnit('''
class A {} // 1
@@ -269,7 +282,7 @@
assertThat(element).isInvokedAt('loadLibrary(); // 2', true);
}
- test_isInvokedBy_MethodElement() async {
+ test_isInvokedBy_MethodElement_class() async {
await _indexTestUnit('''
class A {
foo() {}
@@ -284,6 +297,26 @@
..isInvokedAt('foo(); // nq', false);
}
+ test_isInvokedBy_MethodElement_enum() async {
+ await _indexTestUnit('''
+enum E {
+ v;
+ void foo() {}
+ void bar() {
+ this.foo(); // q1
+ foo(); // nq
+ }
+}
+void f(E e) {
+ e.foo(); // q2
+}
+''');
+ assertThat(findElement.method('foo'))
+ ..isInvokedAt('foo(); // q1', true)
+ ..isInvokedAt('foo(); // nq', false)
+ ..isInvokedAt('foo(); // q2', true);
+ }
+
test_isInvokedBy_MethodElement_ofNamedExtension_instance() async {
await _indexTestUnit('''
extension E on int {
@@ -351,7 +384,7 @@
assertThat(element).isInvokedAt('foo();', true);
}
- test_isInvokedBy_operator_binary() async {
+ test_isInvokedBy_operator_class_binary() async {
await _indexTestUnit('''
class A {
operator +(other) => this;
@@ -371,7 +404,7 @@
..isInvokedAt('++;', true, length: 2);
}
- test_isInvokedBy_operator_index() async {
+ test_isInvokedBy_operator_class_index() async {
await _indexTestUnit('''
class A {
operator [](i) => null;
@@ -388,7 +421,7 @@
assertThat(writeElement).isInvokedAt('[1]', true, length: 1);
}
- test_isInvokedBy_operator_prefix() async {
+ test_isInvokedBy_operator_class_prefix() async {
await _indexTestUnit('''
class A {
A operator ~() => this;
@@ -401,6 +434,58 @@
assertThat(element).isInvokedAt('~a', true, length: 1);
}
+ test_isInvokedBy_operator_enum_binary() async {
+ await _indexTestUnit('''
+enum E {
+ v;
+ int operator +(other) => 0;
+}
+void f(E e) {
+ e + 1;
+ e += 2;
+ ++e;
+ e++;
+}
+''');
+ assertThat(findElement.method('+'))
+ ..isInvokedAt('+ 1', true, length: 1)
+ ..isInvokedAt('+= 2', true, length: 2)
+ ..isInvokedAt('++e', true, length: 2)
+ ..isInvokedAt('++;', true, length: 2);
+ }
+
+ test_isInvokedBy_operator_enum_index() async {
+ await _indexTestUnit('''
+enum E {
+ v;
+ int operator [](int index) => 0;
+ operator []=(int index, int value) {}
+}
+void f(E e) {
+ e[0];
+ e[1] = 42;
+}
+''');
+ MethodElement readElement = findElement.method('[]');
+ MethodElement writeElement = findElement.method('[]=');
+ assertThat(readElement).isInvokedAt('[0]', true, length: 1);
+ assertThat(writeElement).isInvokedAt('[1]', true, length: 1);
+ }
+
+ test_isInvokedBy_operator_enum_prefix() async {
+ await _indexTestUnit('''
+enum E {
+ e;
+ int operator ~() => 0;
+}
+void f(E e) {
+ ~e;
+}
+''');
+ MethodElement element = findElement.method('~');
+ assertThat(element).isInvokedAt('~e', true, length: 1);
+ }
+
test_isMixedBy_ClassDeclaration_TypeAliasElement() async {
await _indexTestUnit('''
class A<T> {}
@@ -465,6 +550,18 @@
assertThat(elementA).isMixedInAt('A; // 2', false);
}
+ test_isMixedInBy_enum_mixin() async {
+ await _indexTestUnit('''
+mixin M {} // 1
+enum E with M { // 2
+ v
+}
+''');
+ assertThat(findElement.mixin('M'))
+ ..isMixedInAt('M { // 2', false)
+ ..isReferencedAt('M { // 2', false);
+ }
+
test_isReferencedAt_PropertyAccessorElement_field_call() async {
await _indexTestUnit('''
class A {
@@ -659,6 +756,141 @@
// No exception, even though a.dart is a part of b.dart part.
}
+ test_isReferencedBy_ConstructorElement_class_named() async {
+ await _indexTestUnit('''
+/// [new A.foo] 1
+class A {
+ A.foo() {}
+ A.bar() : this.foo(); // 2
+}
+class B extends A {
+ B() : super.foo(); // 3
+ factory B.bar() = A.foo; // 4
+}
+void f() {
+ A.foo(); // 5
+ A.foo; // 6
+}
+''');
+ var element = findElement.constructor('foo');
+ assertThat(element)
+ ..hasRelationCount(6)
+ ..isReferencedAt('.foo] 1', true, length: 4)
+ ..isInvokedAt('.foo(); // 2', true, length: 4)
+ ..isInvokedAt('.foo(); // 3', true, length: 4)
+ ..isReferencedAt('.foo; // 4', true, length: 4)
+ ..isInvokedAt('.foo(); // 5', true, length: 4)
+ ..isReferencedByConstructorTearOffAt('.foo; // 6', length: 4);
+ }
+
+ test_isReferencedBy_ConstructorElement_class_namedOnlyWithDot() async {
+ await _indexTestUnit('''
+class A {
+ A.named() {}
+}
+main() {
+ new A.named();
+}
+''');
+ // has ".named()", but does not have "named()"
+ var constructorName = findNode.constructorName('.named();');
+ var offsetWithoutDot = constructorName.name!.offset;
+ var offsetWithDot = constructorName.period!.offset;
+ expect(index.usedElementOffsets, isNot(contains(offsetWithoutDot)));
+ expect(index.usedElementOffsets, contains(offsetWithDot));
+ }
+
+ test_isReferencedBy_ConstructorElement_class_redirection() async {
+ await _indexTestUnit('''
+class A {
+ A() : this.bar(); // 1
+ A.foo() : this(); // 2
+ A.bar();
+}
+''');
+ var constA = findElement.unnamedConstructor('A');
+ var constA_bar = findElement.constructor('bar');
+ assertThat(constA).isInvokedAt('(); // 2', true, length: 0);
+ assertThat(constA_bar).isInvokedAt('.bar(); // 1', true, length: 4);
+ }
+
+ test_isReferencedBy_ConstructorElement_class_unnamed_declared() async {
+ await _indexTestUnit('''
+/// [new A] 1
+class A {
+ A() {}
+ A.other() : this(); // 2
+}
+class B extends A {
+ B() : super(); // 3
+ factory B.other() = A; // 4
+}
+void f() {
+ A(); // 5
+ A.new; // 6
+}
+''');
+ var element = findElement.unnamedConstructor('A');
+ assertThat(element)
+ ..hasRelationCount(6)
+ ..isReferencedAt('] 1', true, length: 0)
+ ..isInvokedAt('(); // 2', true, length: 0)
+ ..isInvokedAt('(); // 3', true, length: 0)
+ ..isReferencedAt('; // 4', true, length: 0)
+ ..isInvokedAt('(); // 5', true, length: 0)
+ ..isReferencedByConstructorTearOffAt('.new; // 6', length: 4);
+ }
+
+ test_isReferencedBy_ConstructorElement_class_unnamed_declared_new() async {
+ await _indexTestUnit('''
+/// [new A] 1
+class A {
+ A.new() {}
+ A.other() : this(); // 2
+}
+class B extends A {
+ B() : super(); // 3
+ factory B.bar() = A; // 4
+}
+void f() {
+ A(); // 5
+ A.new; // 6
+}
+''');
+ var element = findElement.unnamedConstructor('A');
+ assertThat(element)
+ ..hasRelationCount(6)
+ ..isReferencedAt('] 1', true, length: 0)
+ ..isInvokedAt('(); // 2', true, length: 0)
+ ..isInvokedAt('(); // 3', true, length: 0)
+ ..isReferencedAt('; // 4', true, length: 0)
+ ..isInvokedAt('(); // 5', true, length: 0)
+ ..isReferencedByConstructorTearOffAt('.new; // 6', length: 4);
+ }
+
+ test_isReferencedBy_ConstructorElement_class_unnamed_synthetic() async {
+ await _indexTestUnit('''
+/// [new A] 1
+class A {}
+class B extends A {
+ B() : super(); // 2
+ factory B.bar() = A; // 3
+}
+void f() {
+ A(); // 4
+ A.new; // 5
+}
+''');
+ var element = findElement.unnamedConstructor('A');
+ assertThat(element)
+ ..hasRelationCount(5)
+ ..isReferencedAt('] 1', true, length: 0)
+ ..isInvokedAt('(); // 2', true, length: 0)
+ ..isReferencedAt('; // 3', true, length: 0)
+ ..isInvokedAt('(); // 4', true, length: 0)
+ ..isReferencedByConstructorTearOffAt('.new; // 5', length: 4);
+ }
+
test_isReferencedBy_ConstructorElement_classTypeAlias() async {
await _indexTestUnit('''
class M {}
@@ -698,139 +930,81 @@
// No additional validation, but it should not fail with stack overflow.
}
- test_isReferencedBy_ConstructorElement_named() async {
+ test_isReferencedBy_ConstructorElement_enum_named() async {
await _indexTestUnit('''
-/// [new A.foo] 1
-class A {
- A.foo() {}
- A.bar() : this.foo(); // 2
-}
-class B extends A {
- B() : super.foo(); // 3
- factory B.bar() = A.foo; // 4
-}
-void f() {
- A.foo(); // 5
- A.foo; // 6
+/// [new E.foo] 1
+enum E {
+ v.foo(); // 2
+ E.foo();
+ E.bar() : this.foo(); // 3
}
''');
var element = findElement.constructor('foo');
assertThat(element)
- ..hasRelationCount(6)
+ ..hasRelationCount(3)
..isReferencedAt('.foo] 1', true, length: 4)
..isInvokedAt('.foo(); // 2', true, length: 4)
- ..isInvokedAt('.foo(); // 3', true, length: 4)
- ..isReferencedAt('.foo; // 4', true, length: 4)
- ..isInvokedAt('.foo(); // 5', true, length: 4)
- ..isReferencedByConstructorTearOffAt('.foo; // 6', length: 4);
+ ..isInvokedAt('.foo(); // 3', true, length: 4);
}
- test_isReferencedBy_ConstructorElement_namedOnlyWithDot() async {
+ test_isReferencedBy_ConstructorElement_enum_unnamed_declared() async {
await _indexTestUnit('''
-class A {
- A.named() {}
-}
-main() {
- new A.named();
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+ E();
+ E.other() : this(); // 5
}
''');
- // has ".named()", but does not have "named()"
- var constructorName = findNode.constructorName('.named();');
- var offsetWithoutDot = constructorName.name!.offset;
- var offsetWithDot = constructorName.period!.offset;
- expect(index.usedElementOffsets, isNot(contains(offsetWithoutDot)));
- expect(index.usedElementOffsets, contains(offsetWithDot));
- }
-
- test_isReferencedBy_ConstructorElement_redirection() async {
- await _indexTestUnit('''
-class A {
- A() : this.bar(); // 1
- A.foo() : this(); // 2
- A.bar();
-}
-''');
- var constA = findElement.unnamedConstructor('A');
- var constA_bar = findElement.constructor('bar');
- assertThat(constA).isInvokedAt('(); // 2', true, length: 0);
- assertThat(constA_bar).isInvokedAt('.bar(); // 1', true, length: 4);
- }
-
- test_isReferencedBy_ConstructorElement_unnamed_declared() async {
- await _indexTestUnit('''
-/// [new A] 1
-class A {
- A() {}
- A.other() : this(); // 2
-}
-class B extends A {
- B() : super(); // 3
- factory B.other() = A; // 4
-}
-void f() {
- A(); // 5
- A.new; // 6
-}
-''');
- var element = findElement.unnamedConstructor('A');
- assertThat(element)
- ..hasRelationCount(6)
- ..isReferencedAt('] 1', true, length: 0)
- ..isInvokedAt('(); // 2', true, length: 0)
- ..isInvokedAt('(); // 3', true, length: 0)
- ..isReferencedAt('; // 4', true, length: 0)
- ..isInvokedAt('(); // 5', true, length: 0)
- ..isReferencedByConstructorTearOffAt('.new; // 6', length: 4);
- }
-
- test_isReferencedBy_ConstructorElement_unnamed_declared_new() async {
- await _indexTestUnit('''
-/// [new A] 1
-class A {
- A.new() {}
- A.other() : this(); // 2
-}
-class B extends A {
- B() : super(); // 3
- factory B.bar() = A; // 4
-}
-void f() {
- A(); // 5
- A.new; // 6
-}
-''');
- var element = findElement.unnamedConstructor('A');
- assertThat(element)
- ..hasRelationCount(6)
- ..isReferencedAt('] 1', true, length: 0)
- ..isInvokedAt('(); // 2', true, length: 0)
- ..isInvokedAt('(); // 3', true, length: 0)
- ..isReferencedAt('; // 4', true, length: 0)
- ..isInvokedAt('(); // 5', true, length: 0)
- ..isReferencedByConstructorTearOffAt('.new; // 6', length: 4);
- }
-
- test_isReferencedBy_ConstructorElement_unnamed_synthetic() async {
- await _indexTestUnit('''
-/// [new A] 1
-class A {}
-class B extends A {
- B() : super(); // 2
- factory B.bar() = A; // 3
-}
-void f() {
- A(); // 4
- A.new; // 5
-}
-''');
- var element = findElement.unnamedConstructor('A');
+ var element = findElement.unnamedConstructor('E');
assertThat(element)
..hasRelationCount(5)
..isReferencedAt('] 1', true, length: 0)
- ..isInvokedAt('(); // 2', true, length: 0)
- ..isReferencedAt('; // 3', true, length: 0)
- ..isInvokedAt('(); // 4', true, length: 0)
- ..isReferencedByConstructorTearOffAt('.new; // 5', length: 4);
+ ..isInvokedByEnumConstantWithoutArgumentsAt(', // 2', length: 0)
+ ..isInvokedAt('(), // 3', true, length: 0)
+ ..isInvokedAt('.new(); // 4', true, length: 4)
+ ..isInvokedAt('(); // 5', true, length: 0);
+ }
+
+ test_isReferencedBy_ConstructorElement_enum_unnamed_declared_new() async {
+ await _indexTestUnit('''
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+ E.new() {}
+ E.other() : this(); // 5
+}
+''');
+ var element = findElement.unnamedConstructor('E');
+ assertThat(element)
+ ..hasRelationCount(5)
+ ..isReferencedAt('] 1', true, length: 0)
+ ..isInvokedByEnumConstantWithoutArgumentsAt(', // 2', length: 0)
+ ..isInvokedAt('(), // 3', true, length: 0)
+ ..isInvokedAt('.new(); // 4', true, length: 4)
+ ..isInvokedAt('(); // 5', true, length: 0);
+ }
+
+ test_isReferencedBy_ConstructorElement_enum_unnamed_synthetic() async {
+ await _indexTestUnit('''
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+}
+''');
+ var element = findElement.unnamedConstructor('E');
+ assertThat(element)
+ ..hasRelationCount(4)
+ ..isReferencedAt('] 1', true, length: 0)
+ ..isInvokedByEnumConstantWithoutArgumentsAt(', // 2', length: 0)
+ ..isInvokedAt('(), // 3', true, length: 0)
+ ..isInvokedAt('.new(); // 4', true, length: 4);
}
test_isReferencedBy_DynamicElement() async {
@@ -854,7 +1028,7 @@
assertThat(element)..isReferencedAt('E(0).foo()', false);
}
- test_isReferencedBy_FieldElement() async {
+ test_isReferencedBy_FieldElement_class() async {
await _indexTestUnit('''
class A {
var field;
@@ -884,7 +1058,7 @@
assertThat(field)..isReferencedAt('field: 4', true);
}
- test_isReferencedBy_FieldElement_multiple() async {
+ test_isReferencedBy_FieldElement_class_multiple() async {
await _indexTestUnit('''
class A {
var aaa;
@@ -918,7 +1092,72 @@
}
}
- test_isReferencedBy_FieldElement_ofEnum() async {
+ test_isReferencedBy_FieldElement_class_synthetic_hasGetter() async {
+ await _indexTestUnit('''
+class A {
+ A() : f = 42;
+ int get f => 0;
+}
+''');
+ ClassElement element2 = findElement.class_('A');
+ assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ }
+
+ test_isReferencedBy_FieldElement_class_synthetic_hasGetterSetter() async {
+ await _indexTestUnit('''
+class A {
+ A() : f = 42;
+ int get f => 0;
+ set f(_) {}
+}
+''');
+ ClassElement element2 = findElement.class_('A');
+ assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ }
+
+ test_isReferencedBy_FieldElement_class_synthetic_hasSetter() async {
+ await _indexTestUnit('''
+class A {
+ A() : f = 42;
+ set f(_) {}
+}
+''');
+ ClassElement element2 = findElement.class_('A');
+ assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ }
+
+ test_isReferencedBy_FieldElement_enum() async {
+ await _indexTestUnit('''
+enum E {
+ v;
+ int? field; // a compile-time error
+ E({this.field});
+ void foo() {
+ field = 2; // nq
+ field; // nq
+ }
+}
+void f(E e) {
+ e.field = 3; // q
+ e.field; // q
+ E(field: 4);
+}
+''');
+ FieldElement field = findElement.field('field');
+ PropertyAccessorElement getter = field.getter!;
+ PropertyAccessorElement setter = field.setter!;
+ // E()
+ assertThat(field)..isWrittenAt('field});', true);
+ // foo()
+ assertThat(setter)..isReferencedAt('field = 2; // nq', false);
+ assertThat(getter)..isReferencedAt('field; // nq', false);
+ // f()
+ assertThat(setter)..isReferencedAt('field = 3; // q', true);
+ assertThat(getter)..isReferencedAt('field; // q', true);
+ assertThat(field)..isReferencedAt('field: 4', true);
+ }
+
+ test_isReferencedBy_FieldElement_enum_index() async {
await _indexTestUnit('''
enum MyEnum {
A, B, C
@@ -933,44 +1172,44 @@
ClassElement enumElement = findElement.enum_('MyEnum');
assertThat(enumElement.getGetter('values')!)
..isReferencedAt('values);', true);
- assertThat(enumElement.getGetter('index')!)
+ assertThat(typeProvider.enumElement!.getGetter('index')!)
..isReferencedAt('index);', true);
assertThat(enumElement.getGetter('A')!)..isReferencedAt('A);', true);
assertThat(enumElement.getGetter('B')!)..isReferencedAt('B);', true);
}
- test_isReferencedBy_FieldElement_synthetic_hasGetter() async {
+ test_isReferencedBy_FieldElement_enum_synthetic_hasGetter() async {
await _indexTestUnit('''
-class A {
- A() : f = 42;
+enum E {
+ v;
+ E() : f = 42;
int get f => 0;
}
''');
- ClassElement element2 = findElement.class_('A');
- assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ assertThat(findElement.field('f')).isWrittenAt('f = 42', true);
}
- test_isReferencedBy_FieldElement_synthetic_hasGetterSetter() async {
+ test_isReferencedBy_FieldElement_enum_synthetic_hasGetterSetter() async {
await _indexTestUnit('''
-class A {
- A() : f = 42;
+enum E {
+ v;
+ E() : f = 42;
int get f => 0;
set f(_) {}
}
''');
- ClassElement element2 = findElement.class_('A');
- assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ assertThat(findElement.field('f')).isWrittenAt('f = 42', true);
}
- test_isReferencedBy_FieldElement_synthetic_hasSetter() async {
+ test_isReferencedBy_FieldElement_enum_synthetic_hasSetter() async {
await _indexTestUnit('''
-class A {
- A() : f = 42;
+enum E {
+ v;
+ E() : f = 42;
set f(_) {}
}
''');
- ClassElement element2 = findElement.class_('A');
- assertThat(element2.getField('f')!).isWrittenAt('f = 42', true);
+ assertThat(findElement.field('f')).isWrittenAt('f = 42', true);
}
test_isReferencedBy_FunctionElement() async {
@@ -1031,7 +1270,7 @@
assertThat(element)..isReferencedAt('A] text', false);
}
- test_isReferencedBy_MethodElement() async {
+ test_isReferencedBy_MethodElement_class() async {
await _indexTestUnit('''
class A {
method() {}
@@ -1046,6 +1285,26 @@
..isReferencedAt('method); // nq', false);
}
+ test_isReferencedBy_MethodElement_enum() async {
+ await _indexTestUnit('''
+enum E {
+ v;
+ void foo() {}
+ void bar() {
+ this.foo; // q1
+ foo; // nq
+ }
+}
+void f(E e) {
+ e.foo; // q2
+}
+''');
+ assertThat(findElement.method('foo'))
+ ..isReferencedAt('foo; // q1', true)
+ ..isReferencedAt('foo; // nq', false)
+ ..isReferencedAt('foo; // q2', true);
+ }
+
test_isReferencedBy_MultiplyDefinedElement() async {
newFile('$testPackageLibPath/a1.dart', content: 'class A {}');
newFile('$testPackageLibPath/a2.dart', content: 'class A {}');
@@ -1488,6 +1747,36 @@
expect(index.subtypes, isEmpty);
}
+ test_subtypes_enum_implements() async {
+ String libP = 'package:test/test.dart;package:test/test.dart';
+ await _indexTestUnit('''
+class A {}
+
+enum E implements A {
+ v;
+ void foo() {}
+}
+''');
+
+ expect(index.subtypes, hasLength(1));
+ _assertSubtype(0, '$libP;A', 'E', ['foo']);
+ }
+
+ test_subtypes_enum_with() async {
+ String libP = 'package:test/test.dart;package:test/test.dart';
+ await _indexTestUnit('''
+mixin M {}
+
+enum E with M {
+ v;
+ void foo() {}
+}
+''');
+
+ expect(index.subtypes, hasLength(1));
+ _assertSubtype(0, '$libP;M', 'E', ['foo']);
+ }
+
test_subtypes_mixinDeclaration() async {
String libP = 'package:test/lib.dart;package:test/lib.dart';
newFile('$testPackageLibPath/lib.dart', content: '''
@@ -1641,6 +1930,16 @@
test._expectedLocation(search, isQualified, length: length));
}
+ void isInvokedByEnumConstantWithoutArgumentsAt(String search,
+ {required int length}) {
+ test._assertHasRelation(
+ element,
+ relations,
+ IndexRelationKind.IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
+ test._expectedLocation(search, true, length: length),
+ );
+ }
+
void isMixedInAt(String search, bool isQualified, {int? length}) {
test._assertHasRelation(
element,
diff --git a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
index e241371..d570325 100644
--- a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
@@ -87,7 +87,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -96,7 +96,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
@@ -139,7 +139,7 @@
B() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -148,7 +148,20 @@
''');
result.assertResolvedNodes([
- 'B() {print(0); bar; print(1);}',
+ 'B() {print(0); bar print; (1);}',
+ ]);
+ }
+
+ test_constructorDeclaration_fieldFormalParameter_name() async {
+ var result = _resolveTestCode(r'''
+class A {
+ final int f;
+ A(this.^);
+}
+''');
+
+ result.assertResolvedNodes([
+ 'A(this.);',
]);
}
@@ -201,6 +214,23 @@
result.assertResolvedNodes([]);
}
+ test_constructorDeclaration_superFormalParameter_name() async {
+ var result = _resolveTestCode(r'''
+class A {
+ A(int first, double second);
+ A.named(int third);
+}
+
+class B extends A {
+ B(super.^);
+}
+''');
+
+ result.assertResolvedNodes([
+ 'B(super.);',
+ ]);
+ }
+
test_doubleLiteral() async {
var result = _resolveTestCode(r'''
var v = 1.2^;
@@ -216,7 +246,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -225,7 +255,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
@@ -267,6 +297,24 @@
void foo2() {
print(0);
+ bar^
+ print(1);
+}
+
+void foo3() {}
+''');
+
+ result.assertResolvedNodes([
+ 'void foo2() {print(0); bar print; (1);}',
+ ]);
+ }
+
+ test_functionDeclaration_body_withSemicolon() async {
+ var result = _resolveTestCode(r'''
+void foo1() {}
+
+void foo2() {
+ print(0);
bar^;
print(1);
}
@@ -366,7 +414,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -375,7 +423,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 8e54e31..6c5e71d 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -89,6 +89,28 @@
unorderedEquals([a.methods[0], b.fields[0]]));
}
+ test_classMembers_enum() async {
+ await resolveTestCode('''
+enum E1 {
+ v;
+ void test() {}
+}
+
+enum E2 {
+ v;
+ final int test = 0;
+}
+''');
+
+ expect(
+ await _findClassMembers('test'),
+ unorderedEquals([
+ findElement.method('test', of: 'E1'),
+ findElement.field('test', of: 'E2'),
+ ]),
+ );
+ }
+
test_classMembers_importNotDart() async {
await resolveTestCode('''
import 'not-dart.txt';
@@ -596,7 +618,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_ConstructorElement_named() async {
+ test_searchReferences_ConstructorElement_class_named() async {
await resolveTestCode('''
/// [new A.named] 1
class A {
@@ -638,7 +660,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_ConstructorElement_named_viaTypeAlias() async {
+ test_searchReferences_ConstructorElement_class_named_viaTypeAlias() async {
await resolveTestCode('''
class A<T> {
A.named();
@@ -663,7 +685,7 @@
]);
}
- test_searchReferences_ConstructorElement_unnamed_declared() async {
+ test_searchReferences_ConstructorElement_class_unnamed_declared() async {
await resolveTestCode('''
/// [new A] 1
class A {
@@ -703,7 +725,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_ConstructorElement_unnamed_otherFile() async {
+ test_searchReferences_ConstructorElement_class_unnamed_otherFile() async {
String other = convertPath('$testPackageLibPath/other.dart');
String otherCode = '''
import 'test.dart';
@@ -733,7 +755,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_ConstructorElement_unnamed_synthetic() async {
+ test_searchReferences_ConstructorElement_class_unnamed_synthetic() async {
await resolveTestCode('''
/// [new A] 1
class A {}
@@ -767,6 +789,91 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_ConstructorElement_enum_named() async {
+ await resolveTestCode('''
+/// [new E.named] 1
+enum E {
+ v.named(); // 2
+ const E.named();
+ const E.other() : this.named(); // 3
+}
+''');
+ var element = findElement.constructor('named');
+ var expected = [
+ _expectIdQ(
+ findElement.enum_('E'), SearchResultKind.REFERENCE, '.named] 1',
+ length: '.named'.length),
+ _expectIdQ(findElement.field('v', of: 'E'), SearchResultKind.INVOCATION,
+ '.named(); // 2',
+ length: '.named'.length),
+ _expectIdQ(findElement.constructor('other', of: 'E'),
+ SearchResultKind.INVOCATION, '.named(); // 3',
+ length: '.named'.length),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
+ test_searchReferences_ConstructorElement_enum_unnamed_declared() async {
+ await resolveTestCode('''
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+ const E();
+ const E.other() : this(); // 5
+}
+''');
+ var element = findElement.unnamedConstructor('E');
+ var expected = [
+ _expectIdQ(findElement.enum_('E'), SearchResultKind.REFERENCE, '] 1',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v1'),
+ SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
+ ', // 2',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v2'), SearchResultKind.INVOCATION, '(), // 3',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v3'), SearchResultKind.INVOCATION, '.new(); // 4',
+ length: '.new'.length),
+ _expectIdQ(findElement.constructor('other'), SearchResultKind.INVOCATION,
+ '(); // 5',
+ length: 0),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
+ test_searchReferences_ConstructorElement_enum_unnamed_synthetic() async {
+ await resolveTestCode('''
+/// [new E] 1
+enum E {
+ v1, // 2
+ v2(), // 3
+ v3.new(); // 4
+}
+''');
+ var element = findElement.unnamedConstructor('E');
+ var expected = [
+ _expectIdQ(findElement.enum_('E'), SearchResultKind.REFERENCE, '] 1',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v1'),
+ SearchResultKind.INVOCATION_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS,
+ ', // 2',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v2'), SearchResultKind.INVOCATION, '(), // 3',
+ length: 0),
+ _expectIdQ(
+ findElement.field('v3'), SearchResultKind.INVOCATION, '.new(); // 4',
+ length: '.new'.length),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_ExtensionElement() async {
await resolveTestCode('''
extension E on int {
@@ -788,7 +895,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_FieldElement() async {
+ test_searchReferences_FieldElement_class() async {
await resolveTestCode('''
class A {
var field;
@@ -822,33 +929,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_FieldElement_ofEnum() async {
- await resolveTestCode('''
-enum MyEnum {
- A, B, C
-}
-main() {
- print(MyEnum.A.index);
- print(MyEnum.values);
- print(MyEnum.A);
- print(MyEnum.B);
-}
-''');
- var enumElement = findElement.enum_('MyEnum');
- var main = findElement.function('main');
- await _verifyReferences(enumElement.getField('index')!,
- [_expectIdQ(main, SearchResultKind.READ, 'index);')]);
- await _verifyReferences(enumElement.getField('values')!,
- [_expectIdQ(main, SearchResultKind.READ, 'values);')]);
- await _verifyReferences(enumElement.getField('A')!, [
- _expectIdQ(main, SearchResultKind.READ, 'A.index);'),
- _expectIdQ(main, SearchResultKind.READ, 'A);')
- ]);
- await _verifyReferences(enumElement.getField('B')!,
- [_expectIdQ(main, SearchResultKind.READ, 'B);')]);
- }
-
- test_searchReferences_FieldElement_synthetic() async {
+ test_searchReferences_FieldElement_class_synthetic() async {
await resolveTestCode('''
class A {
get field => null;
@@ -878,6 +959,54 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_FieldElement_enum() async {
+ await resolveTestCode('''
+enum E {
+ v(field: 0);
+ final int field;
+ const E({required this.field}); // 1
+}
+
+void f(E e) {
+ e.field; // 2
+}
+''');
+ await _verifyReferences(findElement.field('field'), [
+ _expectIdQ(
+ findElement.field('v'), SearchResultKind.REFERENCE, 'field: 0'),
+ _expectIdQ(findElement.parameter('field'), SearchResultKind.WRITE,
+ 'field}); // 1'),
+ _expectIdQ(
+ findElement.topFunction('f'), SearchResultKind.READ, 'field; // 2'),
+ ]);
+ }
+
+ test_searchReferences_FieldElement_enum_values() async {
+ await resolveTestCode('''
+enum MyEnum {
+ A, B, C
+}
+main() {
+ print(MyEnum.A.index);
+ print(MyEnum.values);
+ print(MyEnum.A);
+ print(MyEnum.B);
+}
+''');
+ var enumElement = findElement.enum_('MyEnum');
+ var main = findElement.function('main');
+ await _verifyReferences(typeProvider.enumElement!.getField('index')!,
+ [_expectIdQ(main, SearchResultKind.READ, 'index);')]);
+ await _verifyReferences(enumElement.getField('values')!,
+ [_expectIdQ(main, SearchResultKind.READ, 'values);')]);
+ await _verifyReferences(enumElement.getField('A')!, [
+ _expectIdQ(main, SearchResultKind.READ, 'A.index);'),
+ _expectIdQ(main, SearchResultKind.READ, 'A);')
+ ]);
+ await _verifyReferences(enumElement.getField('B')!,
+ [_expectIdQ(main, SearchResultKind.READ, 'B);')]);
+ }
+
test_searchReferences_FunctionElement() async {
await resolveTestCode('''
test() {}
@@ -1264,55 +1393,35 @@
await _verifyReferences(method, expected);
}
- test_searchReferences_MethodElement_extension_named() async {
+ test_searchReferences_MethodElement_enum() async {
await resolveTestCode('''
-extension E on int {
+enum E {
+ v;
void foo() {}
-
void bar() {
foo(); // 1
this.foo(); // 2
- print(foo); // 3
- print(this.foo); // 4
}
}
-''');
- var foo = findElement.method('foo');
- var bar = findElement.method('bar');
- var expected = [
- _expectId(bar, SearchResultKind.INVOCATION, 'foo(); // 1'),
- _expectIdQ(bar, SearchResultKind.INVOCATION, 'foo(); // 2'),
- _expectId(bar, SearchResultKind.REFERENCE, 'foo); // 3'),
- _expectIdQ(bar, SearchResultKind.REFERENCE, 'foo); // 4')
- ];
- await _verifyReferences(foo, expected);
- }
- test_searchReferences_MethodElement_extension_unnamed() async {
- await resolveTestCode('''
-extension on int {
- void foo() {}
-
- void bar() {
- foo(); // 1
- this.foo(); // 2
- print(foo); // 3
- print(this.foo); // 4
- }
+void f(E e) {
+ e.foo(); // 3
+ e.foo; // 4
}
''');
- var foo = findElement.method('foo');
- var bar = findElement.method('bar');
- var expected = [
- _expectId(bar, SearchResultKind.INVOCATION, 'foo(); // 1'),
- _expectIdQ(bar, SearchResultKind.INVOCATION, 'foo(); // 2'),
- _expectId(bar, SearchResultKind.REFERENCE, 'foo); // 3'),
- _expectIdQ(bar, SearchResultKind.REFERENCE, 'foo); // 4')
- ];
- await _verifyReferences(foo, expected);
+ await _verifyReferences(findElement.method('foo'), [
+ _expectId(findElement.method('bar'), SearchResultKind.INVOCATION,
+ 'foo(); // 1'),
+ _expectIdQ(findElement.method('bar'), SearchResultKind.INVOCATION,
+ 'foo(); // 2'),
+ _expectIdQ(findElement.topFunction('f'), SearchResultKind.INVOCATION,
+ 'foo(); // 3'),
+ _expectIdQ(findElement.topFunction('f'), SearchResultKind.REFERENCE,
+ 'foo; // 4'),
+ ]);
}
- test_searchReferences_MethodElement_ofExtension_instance() async {
+ test_searchReferences_MethodElement_extension_instance() async {
await resolveTestCode('''
extension E on int {
void foo() {}
@@ -1348,7 +1457,31 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_MethodElement_ofExtension_static() async {
+ test_searchReferences_MethodElement_extension_named() async {
+ await resolveTestCode('''
+extension E on int {
+ void foo() {}
+
+ void bar() {
+ foo(); // 1
+ this.foo(); // 2
+ print(foo); // 3
+ print(this.foo); // 4
+ }
+}
+''');
+ var foo = findElement.method('foo');
+ var bar = findElement.method('bar');
+ var expected = [
+ _expectId(bar, SearchResultKind.INVOCATION, 'foo(); // 1'),
+ _expectIdQ(bar, SearchResultKind.INVOCATION, 'foo(); // 2'),
+ _expectId(bar, SearchResultKind.REFERENCE, 'foo); // 3'),
+ _expectIdQ(bar, SearchResultKind.REFERENCE, 'foo); // 4')
+ ];
+ await _verifyReferences(foo, expected);
+ }
+
+ test_searchReferences_MethodElement_extension_static() async {
await resolveTestCode('''
extension E on int {
static void foo() {}
@@ -1376,6 +1509,30 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_MethodElement_extension_unnamed() async {
+ await resolveTestCode('''
+extension on int {
+ void foo() {}
+
+ void bar() {
+ foo(); // 1
+ this.foo(); // 2
+ print(foo); // 3
+ print(this.foo); // 4
+ }
+}
+''');
+ var foo = findElement.method('foo');
+ var bar = findElement.method('bar');
+ var expected = [
+ _expectId(bar, SearchResultKind.INVOCATION, 'foo(); // 1'),
+ _expectIdQ(bar, SearchResultKind.INVOCATION, 'foo(); // 2'),
+ _expectId(bar, SearchResultKind.REFERENCE, 'foo); // 3'),
+ _expectIdQ(bar, SearchResultKind.REFERENCE, 'foo); // 4')
+ ];
+ await _verifyReferences(foo, expected);
+ }
+
test_searchReferences_MethodMember_class() async {
await resolveTestCode('''
class A<T> {
@@ -2024,6 +2181,29 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_TypeParameterElement_ofEnum() async {
+ await resolveTestCode('''
+enum E<T> {
+ v;
+ final T a;
+ void foo(T b) {}
+}
+''');
+ var element = findElement.typeParameter('T');
+ await _verifyReferences(element, [
+ _expectId(
+ findElement.field('a'),
+ SearchResultKind.REFERENCE,
+ 'T a',
+ ),
+ _expectId(
+ findElement.parameter('b'),
+ SearchResultKind.REFERENCE,
+ 'T b',
+ ),
+ ]);
+ }
+
test_searchReferences_TypeParameterElement_ofLocalFunction() async {
await resolveTestCode('''
main() {
@@ -2107,7 +2287,7 @@
await _verifyReferences(element, expected);
}
- test_subtypes() async {
+ test_subtypes_class() async {
await resolveTestCode('''
class A {}
@@ -2162,7 +2342,7 @@
}
}
- test_subtypes_discover() async {
+ test_subtypes_class_discover() async {
var aaaPackageRootPath = '$packagesRootPath/aaa';
var bbbPackageRootPath = '$packagesRootPath/bbb';
@@ -2232,7 +2412,7 @@
expect(b.members, ['method1']);
}
- test_subTypes_discover() async {
+ test_subTypes_class_discover() async {
var aaaPackageRootPath = '$packagesRootPath/aaa';
var bbbPackageRootPath = '$packagesRootPath/bbb';
var cccPackageRootPath = '$packagesRootPath/ccc';
@@ -2273,7 +2453,7 @@
assertHasResult(cccFilePath, 'C', not: true);
}
- test_subtypes_files() async {
+ test_subtypes_class_files() async {
String pathB = convertPath('$testPackageLibPath/b.dart');
String pathC = convertPath('$testPackageLibPath/c.dart');
newFile(pathB, content: r'''
@@ -2302,6 +